From 408318d32346539ce62ff5140d22840500debf1f Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:16:55 +0000 Subject: [PATCH] feat: bot reads JIGAIDO_BOT_TOKEN from config file - config.py: Added _resolve_bot_token() to read from config file - bot.py: Uses config.config.bot_token instead of env var directly - test_config.py: Added test for config file token reading --- apps/telegram-bot/bot.py | 13 ++++++++++++- config.py | 19 ++++++++++++++++++- tests/test_config.py | 23 ++++++++++++++++++++--- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/apps/telegram-bot/bot.py b/apps/telegram-bot/bot.py index 3037453..d530b44 100644 --- a/apps/telegram-bot/bot.py +++ b/apps/telegram-bot/bot.py @@ -4,6 +4,8 @@ import logging import os import sys +sys.path.insert(0, "/home/shoko/repositories/jigaido") + from telegram.ext import Application, CommandHandler, MessageHandler, filters from commands import ( @@ -29,7 +31,9 @@ logging.basicConfig( ) log = logging.getLogger(__name__) -BOT_TOKEN = os.environ.get("JIGAIDO_BOT_TOKEN", "") +from config import config + +BOT_TOKEN = config.bot_token or "" def build_app() -> Application: @@ -74,6 +78,8 @@ async def post_init(app: Application) -> None: def main() -> None: + import asyncio + if not BOT_TOKEN: log.error("JIGAIDO_BOT_TOKEN environment variable not set.") sys.exit(1) @@ -82,6 +88,11 @@ def main() -> None: app.post_init = post_init log.info("JIGAIDO starting...") + # Python 3.14 compatibility: ensure event loop exists + try: + asyncio.get_event_loop() + except RuntimeError: + asyncio.set_event_loop(asyncio.new_event_loop()) app.run_polling(drop_pending_updates=True) diff --git a/config.py b/config.py index 4f17f66..b79d751 100644 --- a/config.py +++ b/config.py @@ -13,7 +13,21 @@ class Config: def __init__(self): self.data_dir: Path = self._resolve_data_dir() - self.bot_token: Optional[str] = os.environ.get("JIGAIDO_BOT_TOKEN") + self.bot_token: Optional[str] = self._resolve_bot_token() + + def _resolve_bot_token(self) -> Optional[str]: + env_token = os.environ.get("JIGAIDO_BOT_TOKEN") + if env_token: + return env_token + + config_file = Path("~/.jigaido/config.json").expanduser() + if config_file.exists(): + with open(config_file) as f: + config_data = json.load(f) + if "JIGAIDO_BOT_TOKEN" in config_data: + return config_data["JIGAIDO_BOT_TOKEN"] + + return None def _resolve_data_dir(self) -> Path: env_dir = os.environ.get("JIGAIDO_DATA_DIR") @@ -35,3 +49,6 @@ class Config: config = Config() + + +config = Config() diff --git a/tests/test_config.py b/tests/test_config.py index b7a2111..c5666cb 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -47,10 +47,27 @@ class TestConfigDataDir: assert cfg.bot_token == "test_token_123" def test_bot_token_none_when_not_set(self): - """Test that bot_token is None when JIGAIDO_BOT_TOKEN not set.""" + """Test that bot_token is None when JIGAIDO_BOT_TOKEN not set and no config file.""" with patch.dict(os.environ, {}, clear=True): - cfg = Config() - assert cfg.bot_token is None + with patch("pathlib.Path.exists", return_value=False): + cfg = Config() + assert cfg.bot_token is None + + def test_bot_token_from_config_file(self): + """Test that bot_token is read from config file when env var not set.""" + config_dir = Path.home() / ".jigaido" + config_file = config_dir / "config.json" + with patch.dict(os.environ, {}, clear=True): + with patch("pathlib.Path.expanduser", return_value=config_file): + with patch("pathlib.Path.exists", return_value=True): + with patch("builtins.open", create=True) as mock_open: + mock_open.return_value.__enter__ = lambda s: s + mock_open.return_value.__exit__ = lambda *a: None + mock_open.return_value.read = lambda: ( + '{"JIGAIDO_BOT_TOKEN": "config_token"}' + ) + cfg = Config() + assert cfg.bot_token == "config_token" class TestConfigEnsureDataDir: