feat(gateway): introduce GATEWAY_TELEGRAM_INTAKE_MODE for Telegram integration

This commit is contained in:
Anish Sarkar 2026-05-28 05:02:07 +05:30
parent 7ff0120fc9
commit c958fe5bc6
5 changed files with 53 additions and 14 deletions

View file

@ -17,10 +17,12 @@ REDIS_APP_URL=redis://localhost:6379/0
# Telegram Gateway
# TELEGRAM_WEBHOOK_SECRET must be 1-256 chars and contain only A-Z, a-z, 0-9, _ or -
# GATEWAY_TELEGRAM_INTAKE_MODE: webhook for production, longpoll for single-replica self-host fallback, disabled to skip Telegram intake
TELEGRAM_SHARED_BOT_TOKEN=
TELEGRAM_SHARED_BOT_USERNAME=
TELEGRAM_WEBHOOK_SECRET=
GATEWAY_BASE_URL=http://localhost:8000
GATEWAY_TELEGRAM_INTAKE_MODE=webhook
# Platform Web Search (SearXNG)
# Set this to enable built-in web search. Docker Compose sets it automatically.

View file

@ -546,9 +546,13 @@ class Config:
TELEGRAM_SHARED_BOT_USERNAME = os.getenv("TELEGRAM_SHARED_BOT_USERNAME")
TELEGRAM_WEBHOOK_SECRET = os.getenv("TELEGRAM_WEBHOOK_SECRET")
GATEWAY_BASE_URL = os.getenv("GATEWAY_BASE_URL", BACKEND_URL)
GATEWAY_BYO_LONGPOLL_ENABLED = (
os.getenv("GATEWAY_BYO_LONGPOLL_ENABLED", "TRUE").upper() == "TRUE"
)
GATEWAY_TELEGRAM_INTAKE_MODE = os.getenv(
"GATEWAY_TELEGRAM_INTAKE_MODE", "webhook"
).lower()
if GATEWAY_TELEGRAM_INTAKE_MODE not in {"webhook", "longpoll", "disabled"}:
raise ValueError(
"GATEWAY_TELEGRAM_INTAKE_MODE must be one of: webhook, longpoll, disabled"
)
# Stripe checkout for pay-as-you-go page packs
STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY")

View file

@ -46,7 +46,7 @@ async def start_byo_long_poll_supervisors() -> None:
"""Start one BYO long-poll supervisor per active non-system Telegram account."""
global _shutdown_event
if not config.GATEWAY_BYO_LONGPOLL_ENABLED:
if config.GATEWAY_TELEGRAM_INTAKE_MODE != "longpoll":
return
if _tasks:
return

View file

@ -38,8 +38,8 @@ async def cleanup_supervisors():
@pytest.mark.asyncio
async def test_start_byo_long_poll_noops_when_flag_off(monkeypatch):
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_BYO_LONGPOLL_ENABLED", False)
async def test_start_byo_long_poll_noops_when_mode_is_webhook(monkeypatch):
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_TELEGRAM_INTAKE_MODE", "webhook")
await byo_long_poll.start_byo_long_poll_supervisors()
@ -48,7 +48,7 @@ async def test_start_byo_long_poll_noops_when_flag_off(monkeypatch):
@pytest.mark.asyncio
async def test_start_byo_long_poll_noops_when_no_byo_accounts(mocker, monkeypatch):
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_BYO_LONGPOLL_ENABLED", True)
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_TELEGRAM_INTAKE_MODE", "longpoll")
session = mocker.AsyncMock()
session.execute.return_value = ScalarResult([])
monkeypatch.setattr(
@ -64,7 +64,7 @@ async def test_start_byo_long_poll_noops_when_no_byo_accounts(mocker, monkeypatc
@pytest.mark.asyncio
async def test_start_byo_long_poll_spawns_one_supervisor_per_account(mocker, monkeypatch):
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_BYO_LONGPOLL_ENABLED", True)
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_TELEGRAM_INTAKE_MODE", "longpoll")
accounts = [mocker.Mock(id=1), mocker.Mock(id=2)]
session = mocker.AsyncMock()
session.execute.return_value = ScalarResult(accounts)
@ -108,7 +108,7 @@ async def test_supervisor_retries_after_run_returns(mocker, monkeypatch):
@pytest.mark.asyncio
async def test_shutdown_cancels_running_supervisors(mocker, monkeypatch):
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_BYO_LONGPOLL_ENABLED", True)
monkeypatch.setattr(byo_long_poll.config, "GATEWAY_TELEGRAM_INTAKE_MODE", "longpoll")
session = mocker.AsyncMock()
session.execute.return_value = ScalarResult([mocker.Mock(id=1)])
monkeypatch.setattr(