forked from Rockachopa/Timmy-time-dashboard
Bridges Telegram messages to Timmy via python-telegram-bot (optional dependency). The bot token can be supplied through the TELEGRAM_TOKEN env var or at runtime via the new POST /telegram/setup dashboard endpoint, which (re)starts the bot without a restart. Changes: - src/telegram_bot/bot.py — TelegramBot singleton: token persistence (telegram_state.json), lifecycle (start/stop), /start command and message handler that forwards to Timmy - src/dashboard/routes/telegram.py — /telegram/setup and /telegram/status FastAPI routes - src/dashboard/app.py — register telegram router; auto-start/stop bot in lifespan hook - src/config.py — TELEGRAM_TOKEN setting (pydantic-settings) - pyproject.toml — [telegram] optional extra (python-telegram-bot>=21), telegram_bot wheel include - .env.example — TELEGRAM_TOKEN section - .gitignore — exclude telegram_state.json (contains token) - tests/conftest.py — stub telegram/telegram.ext for offline test runs - tests/test_telegram_bot.py — 16 tests covering token helpers, lifecycle, and all dashboard routes (370 total, all passing) https://claude.ai/code/session_01CNBm3ZLobtx3Z1YogHq8ZS
42 lines
1.1 KiB
Python
42 lines
1.1 KiB
Python
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
# ── Stub heavy optional dependencies so tests run without them installed ──────
|
|
# Uses setdefault: real module is used if already installed, mock otherwise.
|
|
for _mod in [
|
|
"agno",
|
|
"agno.agent",
|
|
"agno.models",
|
|
"agno.models.ollama",
|
|
"agno.db",
|
|
"agno.db.sqlite",
|
|
# AirLLM is optional (bigbrain extra) — stub it so backend tests can
|
|
# import timmy.backends and instantiate TimmyAirLLMAgent without a GPU.
|
|
"airllm",
|
|
# python-telegram-bot is optional (telegram extra) — stub so tests run
|
|
# without the package installed.
|
|
"telegram",
|
|
"telegram.ext",
|
|
]:
|
|
sys.modules.setdefault(_mod, MagicMock())
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def reset_message_log():
|
|
"""Clear the in-memory chat log before and after every test."""
|
|
from dashboard.store import message_log
|
|
message_log.clear()
|
|
yield
|
|
message_log.clear()
|
|
|
|
|
|
@pytest.fixture
|
|
def client():
|
|
from dashboard.app import app
|
|
with TestClient(app) as c:
|
|
yield c
|