diff --git a/src/takopi/exec_bridge.py b/src/takopi/exec_bridge.py index 2955d44..c8c8721 100644 --- a/src/takopi/exec_bridge.py +++ b/src/takopi/exec_bridge.py @@ -351,14 +351,19 @@ def _parse_bridge_config( token = config["bot_token"] except KeyError: raise ConfigError(f"Missing key `bot_token` in {config_path}.") from None + if not isinstance(token, str) or not token.strip(): + raise ConfigError( + f"Invalid `bot_token` in {config_path}; expected a non-empty string." + ) from None try: - chat_id = int(config["chat_id"]) + chat_id_value = config["chat_id"] except KeyError: raise ConfigError(f"Missing key `chat_id` in {config_path}.") from None - except (TypeError, ValueError): + if isinstance(chat_id_value, bool) or not isinstance(chat_id_value, int): raise ConfigError( f"Invalid `chat_id` in {config_path}; expected an integer." ) from None + chat_id = chat_id_value codex_cmd = shutil.which("codex") if not codex_cmd: diff --git a/tests/test_exec_bridge.py b/tests/test_exec_bridge.py index a8d8388..fccb304 100644 --- a/tests/test_exec_bridge.py +++ b/tests/test_exec_bridge.py @@ -1,5 +1,7 @@ import asyncio +import pytest + from takopi.exec_bridge import ( extract_session_id, prepare_telegram, @@ -8,6 +10,36 @@ from takopi.exec_bridge import ( ) +def _patch_config(monkeypatch, config): + from pathlib import Path + + from takopi import exec_bridge + + monkeypatch.setattr( + exec_bridge, + "load_telegram_config", + lambda: (config, Path("takopi.toml")), + ) + + +def test_parse_bridge_config_rejects_empty_token(monkeypatch) -> None: + from takopi import exec_bridge + + _patch_config(monkeypatch, {"bot_token": " ", "chat_id": 123}) + + with pytest.raises(exec_bridge.ConfigError, match="bot_token"): + exec_bridge._parse_bridge_config(final_notify=True, profile=None) + + +def test_parse_bridge_config_rejects_string_chat_id(monkeypatch) -> None: + from takopi import exec_bridge + + _patch_config(monkeypatch, {"bot_token": "token", "chat_id": "123"}) + + with pytest.raises(exec_bridge.ConfigError, match="chat_id"): + exec_bridge._parse_bridge_config(final_notify=True, profile=None) + + def test_extract_session_id_finds_uuid_v7() -> None: uuid = "019b66fc-64c2-7a71-81cd-081c504cfeb2" text = f"resume: `{uuid}`"