feat: prompt users to start Telegram bot for notifications
This commit is contained in:
@@ -438,6 +438,11 @@ class AccountLinkingPanelTests(unittest.IsolatedAsyncioTestCase):
|
||||
"bot.services.notification_service.NotificationService",
|
||||
return_value=notification_service,
|
||||
),
|
||||
patch.object(
|
||||
account_routes,
|
||||
"_probe_telegram_notifications_for_user_id",
|
||||
AsyncMock(),
|
||||
) as probe_telegram_notifications,
|
||||
):
|
||||
response = await account_routes.account_telegram_link_route(request)
|
||||
|
||||
@@ -453,6 +458,7 @@ class AccountLinkingPanelTests(unittest.IsolatedAsyncioTestCase):
|
||||
source_user_id=-100,
|
||||
target_user_id=42,
|
||||
)
|
||||
probe_telegram_notifications.assert_awaited_once_with(request, 42)
|
||||
self.assertEqual(panel_calls, ["delete", "update"])
|
||||
panel_service.delete_user_from_panel.assert_awaited_once_with(
|
||||
"panel-email",
|
||||
|
||||
@@ -108,6 +108,7 @@ def _user(**overrides):
|
||||
|
||||
def test_send_stage_records_telegram_and_email_channel_keys(monkeypatch):
|
||||
recorded = []
|
||||
status_changes = []
|
||||
|
||||
async def fake_has(session, subscription_id, notification_key):
|
||||
return notification_key in recorded
|
||||
@@ -115,8 +116,19 @@ def test_send_stage_records_telegram_and_email_channel_keys(monkeypatch):
|
||||
async def fake_record(session, subscription_id, notification_key, *, sent_at=None):
|
||||
recorded.append(notification_key)
|
||||
|
||||
async def fake_mark_status(session, user_id, status, *, telegram_id=None, checked_at=None):
|
||||
status_changes.append(
|
||||
{
|
||||
"user_id": user_id,
|
||||
"status": status,
|
||||
"telegram_id": telegram_id,
|
||||
"checked_at": checked_at,
|
||||
}
|
||||
)
|
||||
|
||||
monkeypatch.setattr(lifecycle.subscription_dal, "has_subscription_notification", fake_has)
|
||||
monkeypatch.setattr(lifecycle.subscription_dal, "record_subscription_notification", fake_record)
|
||||
monkeypatch.setattr(lifecycle, "mark_telegram_notifications_status", fake_mark_status)
|
||||
|
||||
bot = FakeBot()
|
||||
email_service = FakeEmailService()
|
||||
@@ -154,6 +166,15 @@ def test_send_stage_records_telegram_and_email_channel_keys(monkeypatch):
|
||||
assert email_service.messages[0]["email"] == "user@example.test"
|
||||
assert "Mirrored Telegram notice" in email_service.messages[0]["content"].html
|
||||
assert recorded == ["before_3d:telegram", "before_3d:email"]
|
||||
assert status_changes == [
|
||||
{
|
||||
"user_id": 123,
|
||||
"status": lifecycle.TELEGRAM_NOTIFICATIONS_ENABLED,
|
||||
"telegram_id": 555,
|
||||
"checked_at": status_changes[0]["checked_at"],
|
||||
}
|
||||
]
|
||||
assert status_changes[0]["checked_at"] is not None
|
||||
|
||||
|
||||
def test_legacy_stage_key_suppresses_only_telegram(monkeypatch):
|
||||
@@ -199,8 +220,9 @@ def test_legacy_stage_key_suppresses_only_telegram(monkeypatch):
|
||||
assert recorded == ["before_3d", "before_3d:email"]
|
||||
|
||||
|
||||
def test_terminal_telegram_failure_is_recorded_to_avoid_retry_spam(monkeypatch):
|
||||
def test_unstarted_telegram_failure_marks_status_without_recording_delivery(monkeypatch):
|
||||
recorded = []
|
||||
status_changes = []
|
||||
|
||||
async def fake_has(session, subscription_id, notification_key):
|
||||
return notification_key in recorded
|
||||
@@ -208,8 +230,19 @@ def test_terminal_telegram_failure_is_recorded_to_avoid_retry_spam(monkeypatch):
|
||||
async def fake_record(session, subscription_id, notification_key, *, sent_at=None):
|
||||
recorded.append(notification_key)
|
||||
|
||||
async def fake_mark_status(session, user_id, status, *, telegram_id=None, checked_at=None):
|
||||
status_changes.append(
|
||||
{
|
||||
"user_id": user_id,
|
||||
"status": status,
|
||||
"telegram_id": telegram_id,
|
||||
"checked_at": checked_at,
|
||||
}
|
||||
)
|
||||
|
||||
monkeypatch.setattr(lifecycle.subscription_dal, "has_subscription_notification", fake_has)
|
||||
monkeypatch.setattr(lifecycle.subscription_dal, "record_subscription_notification", fake_record)
|
||||
monkeypatch.setattr(lifecycle, "mark_telegram_notifications_status", fake_mark_status)
|
||||
|
||||
bot = ChatNotFoundBot()
|
||||
settings = _settings()
|
||||
@@ -241,7 +274,15 @@ def test_terminal_telegram_failure_is_recorded_to_avoid_retry_spam(monkeypatch):
|
||||
assert delivery.telegram_sent is False
|
||||
assert delivery.email_sent is False
|
||||
assert bot.calls[0][0] == 777
|
||||
assert recorded == ["before_3d:telegram"]
|
||||
assert recorded == []
|
||||
assert status_changes == [
|
||||
{
|
||||
"user_id": 123,
|
||||
"status": lifecycle.TELEGRAM_NOTIFICATIONS_NEEDS_START,
|
||||
"telegram_id": None,
|
||||
"checked_at": None,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_email_only_user_gets_email_name_direct_copy_and_renewal_login_link(monkeypatch):
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from bot.services.telegram_notifications import telegram_notifications_need_prompt
|
||||
|
||||
|
||||
def _user(status: str):
|
||||
return SimpleNamespace(telegram_id=123, telegram_notifications_status=status)
|
||||
|
||||
|
||||
def test_telegram_notifications_prompt_only_for_explicit_unreachable_statuses():
|
||||
assert telegram_notifications_need_prompt(_user("needs_start")) is True
|
||||
assert telegram_notifications_need_prompt(_user("blocked")) is True
|
||||
assert telegram_notifications_need_prompt(_user("enabled")) is False
|
||||
assert telegram_notifications_need_prompt(_user("unknown")) is False
|
||||
|
||||
|
||||
def test_telegram_notifications_prompt_requires_linked_telegram():
|
||||
user = SimpleNamespace(
|
||||
email="user@example.test",
|
||||
telegram_id=None,
|
||||
telegram_notifications_status="needs_start",
|
||||
)
|
||||
|
||||
assert telegram_notifications_need_prompt(user) is False
|
||||
Reference in New Issue
Block a user