Skip to content

Commit dd2cb1b

Browse files
committed
Fix all CI lint errors, critical bugs, and deprecation warnings
- Fix unused imports across client.py, handler.py, gui.py, config.py, main.py, logger.py, web/gui.py - Fix unused variables (key, model_str, thinking_msg, bs) in handler.py and web/gui.py - Fix line length violations (>120 chars) in handler.py and gui.py - Fix import sorting (I001) and collections.abc imports (UP035) - Replace try-except-pass with contextlib.suppress (SIM105) - Fix file handle leaks with proper context managers (SIM115) - Replace deprecated datetime.utcnow() with datetime.now(timezone.utc) - Fix double ApplicationBuilder bug in main.py - Fix stdout pipe deadlock risk in server.py (DEVNULL instead of PIPE) - Fix wrong cache key (all -> providers) in handler.py - Replace blocking time.sleep() with non-blocking Tkinter after() in gui.py
1 parent beb6a5a commit dd2cb1b

16 files changed

Lines changed: 263 additions & 123 deletions

File tree

src/opencode_telegram_bot/api/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
import json
44
import logging
5-
from typing import Any, AsyncGenerator
5+
from collections.abc import AsyncGenerator
6+
from typing import Any
67

78
import httpx
89

src/opencode_telegram_bot/api/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def start(self, port: int = 4096) -> None:
3535
self._process = subprocess.Popen(
3636
[self.command, "serve", "--port", str(port)],
3737
cwd=self.work_dir,
38-
stdout=subprocess.PIPE,
38+
stdout=subprocess.DEVNULL,
3939
stderr=subprocess.STDOUT,
4040
text=True,
4141
)

src/opencode_telegram_bot/bot/handler.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import asyncio
4+
import contextlib
45
import logging
56
import os
67
import tempfile
@@ -15,11 +16,7 @@
1516
Update,
1617
)
1718
from telegram.ext import (
18-
CallbackQueryHandler,
19-
CommandHandler,
2019
ContextTypes,
21-
MessageHandler,
22-
filters,
2320
)
2421

2522
from opencode_telegram_bot.api import OpenCodeClient, OpenCodeServer
@@ -146,21 +143,15 @@ async def _ensure_session(self) -> str:
146143

147144
async def _cache_metadata(self) -> None:
148145
if not self._cached_providers:
149-
try:
146+
with contextlib.suppress(Exception):
150147
providers_data = await self.client.get_providers()
151-
self._cached_providers = providers_data.get("all", [])
152-
except Exception:
153-
pass
148+
self._cached_providers = providers_data.get("providers", [])
154149
if not self._cached_agents:
155-
try:
150+
with contextlib.suppress(Exception):
156151
self._cached_agents = await self.client.get_agents()
157-
except Exception:
158-
pass
159152
if not self._cached_commands:
160-
try:
153+
with contextlib.suppress(Exception):
161154
self._cached_commands = await self.client.get_commands()
162-
except Exception:
163-
pass
164155

165156
async def cmd_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
166157
if not self._is_authorized(update.effective_user.id):
@@ -296,7 +287,6 @@ async def cmd_mode(self, update: Update, context: ContextTypes.DEFAULT_TYPE) ->
296287
current = self.bot_settings.get("agent_mode", "build")
297288
new_mode = "plan" if current == "build" else "build"
298289
self.bot_settings.set("agent_mode", new_mode)
299-
key = "mode_plan" if new_mode == "plan" else "mode_build"
300290
await update.message.reply_text(t("mode_switched", locale=self._locale(), mode=new_mode.capitalize()))
301291

302292
async def cmd_models(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
@@ -410,8 +400,11 @@ async def callback_handler(self, update: Update, context: ContextTypes.DEFAULT_T
410400
parts = data.split(":", 2)
411401
provider = parts[1]
412402
model_id = parts[2]
413-
model_str = f"{provider}/{model_id}" if model_id else provider
414-
await self._send(context, chat_id, t("model_switched", locale=self._locale(), provider=provider, model=model_id or "default"))
403+
await self._send(
404+
context, chat_id,
405+
t("model_switched", locale=self._locale(),
406+
provider=provider, model=model_id or "default"),
407+
)
415408

416409
elif data.startswith("runcmd:"):
417410
command = data.split(":", 1)[1]
@@ -498,7 +491,7 @@ async def _process_prompt(
498491
await self._send(context, chat_id, t("error", locale=self._locale(), message=str(e)))
499492
return
500493

501-
thinking_msg = await self._send(context, chat_id, t("thinking", locale=self._locale()))
494+
await self._send(context, chat_id, t("thinking", locale=self._locale()))
502495

503496
try:
504497
agent_mode = self.bot_settings.get("agent_mode", "build")
@@ -517,25 +510,34 @@ async def _process_prompt(
517510

518511
if response_text:
519512
if len(response_text) > 4000:
520-
with tempfile.NamedTemporaryFile(suffix=".txt", delete=False, mode="w", encoding="utf-8") as f:
513+
with tempfile.NamedTemporaryFile(
514+
suffix=".txt", delete=False, mode="w", encoding="utf-8",
515+
) as f:
521516
f.write(response_text)
522517
f.flush()
523-
await context.bot.send_document(
524-
chat_id=chat_id,
525-
document=open(f.name, "rb"),
526-
filename="response.txt",
527-
)
528-
os.unlink(f.name)
518+
tmp_path = f.name
519+
with open(tmp_path, "rb") as doc:
520+
await context.bot.send_document(
521+
chat_id=chat_id,
522+
document=doc,
523+
filename="response.txt",
524+
)
525+
os.unlink(tmp_path)
529526
else:
530527
await self._send(context, chat_id, response_text)
531528

532529
if self.bot_settings.tts_enabled and self.tts.is_configured:
533530
audio = await self.tts.synthesize(response_text[:4000])
534531
if audio:
535-
with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f:
532+
with tempfile.NamedTemporaryFile(
533+
suffix=".mp3", delete=False,
534+
) as f:
536535
f.write(audio)
537536
audio_path = f.name
538-
await context.bot.send_voice(chat_id=chat_id, voice=open(audio_path, "rb"))
537+
with open(audio_path, "rb") as voice_file:
538+
await context.bot.send_voice(
539+
chat_id=chat_id, voice=voice_file,
540+
)
539541
os.unlink(audio_path)
540542
else:
541543
raw = str(response)[:4000]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .config import Settings, BotSettings
1+
from .config import BotSettings, Settings
22
from .session import SessionManager
33

44
__all__ = ["Settings", "BotSettings", "SessionManager"]

src/opencode_telegram_bot/core/config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from pathlib import Path
66
from typing import Any
77

8-
from pydantic import BaseModel, Field
98
from pydantic_settings import BaseSettings, SettingsConfigDict
109

1110
logger = logging.getLogger(__name__)

src/opencode_telegram_bot/core/session.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import json
44
import logging
5-
from datetime import datetime
5+
from datetime import datetime, timezone
66
from pathlib import Path
77
from typing import Any
88

@@ -30,17 +30,18 @@ def _save(self) -> None:
3030
self._file.write_text(json.dumps(self._sessions, indent=2), encoding="utf-8")
3131

3232
def add(self, session_id: str, metadata: dict[str, Any]) -> None:
33+
now = datetime.now(timezone.utc).isoformat()
3334
self._sessions[session_id] = {
3435
**metadata,
35-
"created_at": datetime.utcnow().isoformat(),
36-
"updated_at": datetime.utcnow().isoformat(),
36+
"created_at": now,
37+
"updated_at": now,
3738
}
3839
self._save()
3940

4041
def update(self, session_id: str, metadata: dict[str, Any]) -> None:
4142
if session_id in self._sessions:
4243
self._sessions[session_id].update(metadata)
43-
self._sessions[session_id]["updated_at"] = datetime.utcnow().isoformat()
44+
self._sessions[session_id]["updated_at"] = datetime.now(timezone.utc).isoformat()
4445
self._save()
4546

4647
def remove(self, session_id: str) -> None:

0 commit comments

Comments
 (0)