Skip to content

Commit

Permalink
Add unsupported media handler to Telegram agent frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
Saluev committed Dec 26, 2023
1 parent 276b574 commit f9b3109
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 43 deletions.
64 changes: 45 additions & 19 deletions suppgram/frontends/telegram/agent_frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
CommandHandler,
Application,
CallbackQueryHandler,
BaseHandler,
)
from telegram.ext.filters import TEXT, ChatType

Expand Down Expand Up @@ -84,23 +85,7 @@ def __init__(
self._telegram_apps: List[Application] = []
for token in agent_bot_tokens:
app = app_manager.get_app(token)
app.add_handlers(
[
CommandHandler("start", self._handle_start_command, filters=ChatType.PRIVATE),
CommandHandler(
self._POSTPONE_COMMAND,
self._handle_postpone_command,
filters=ChatType.PRIVATE,
),
CommandHandler(
self._RESOLVE_COMMAND,
self._handle_resolve_command,
filters=ChatType.PRIVATE,
),
MessageHandler(TEXT & ChatType.PRIVATE, self._handle_text_message),
CallbackQueryHandler(self._handle_callback_query),
]
)
app.add_handlers(self._make_handlers())
self._telegram_apps.append(app)
self._telegram_app_by_bot_id: Mapping[int, Application] = {}
self._manager_bot: Optional[Bot] = (
Expand All @@ -111,6 +96,24 @@ def __init__(
self._handle_new_message_for_agent_events
)

def _make_handlers(self) -> List[BaseHandler]:
return [
CommandHandler("start", self._handle_start_command, filters=ChatType.PRIVATE),
CommandHandler(
self._POSTPONE_COMMAND,
self._handle_postpone_command,
filters=ChatType.PRIVATE,
),
CommandHandler(
self._RESOLVE_COMMAND,
self._handle_resolve_command,
filters=ChatType.PRIVATE,
),
MessageHandler(ChatType.PRIVATE & TEXT, self._handle_text_message),
MessageHandler(ChatType.PRIVATE & ~TEXT, self._handle_unsupported_message),
CallbackQueryHandler(self._handle_callback_query),
]

async def initialize(self):
await super().initialize()
await flat_gather(app.initialize() for app in self._telegram_apps)
Expand Down Expand Up @@ -236,8 +239,8 @@ async def _handle_text_message(self, update: Update, context: ContextTypes.DEFAU
)
except ConversationNotFound:
await context.bot.send_message(
update.effective_chat.id,
self._texts.telegram_workplace_is_not_assigned_message,
chat_id=update.effective_chat.id,
text=self._texts.telegram_workplace_is_not_assigned_message,
)
return
await self._backend.process_message(
Expand All @@ -249,6 +252,29 @@ async def _handle_text_message(self, update: Update, context: ContextTypes.DEFAU
),
)

async def _handle_unsupported_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
assert update.effective_chat, "message update should have `effective_chat`"
assert update.effective_user, "message update should have `effective_user`"
assert update.message, "message update should have `message`"
try:
await self._backend.identify_agent_conversation(
WorkplaceIdentification(
telegram_user_id=update.effective_user.id,
telegram_bot_id=context.bot.bot.id,
)
)
except ConversationNotFound:
await context.bot.send_message(
chat_id=update.effective_chat.id,
text=self._texts.telegram_workplace_is_not_assigned_message,
)
return
await context.bot.send_message(
chat_id=update.effective_chat.id,
text=self._texts.telegram_agent_unsupported_message_content,
reply_to_message_id=update.message.message_id,
)

async def _handle_callback_query(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
assert update.callback_query, "callback query update should have `callback_query`"
assert update.effective_chat, "callback query update should have `effective_chat`"
Expand Down
21 changes: 11 additions & 10 deletions suppgram/frontends/telegram/customer_frontend.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import json
import logging
from typing import cast
from typing import cast, List

from telegram import Update, Bot, InlineKeyboardMarkup, InlineKeyboardButton
from telegram.ext import (
CommandHandler,
ContextTypes,
MessageHandler,
CallbackQueryHandler,
BaseHandler,
)
from telegram.ext.filters import TEXT, ChatType

Expand Down Expand Up @@ -67,19 +68,20 @@ def __init__(
self._storage = storage
self._telegram_app = app_manager.get_app(token)
self._telegram_bot: Bot = self._telegram_app.bot
self._telegram_app.add_handlers(
[
CommandHandler("start", self._handle_start_command),
CallbackQueryHandler(self._handle_callback_query),
MessageHandler(ChatType.PRIVATE & TEXT, self._handle_text_message),
MessageHandler(ChatType.PRIVATE & ~TEXT, self._handle_unsupported_message),
]
)
self._telegram_app.add_handlers(self._make_handlers())
self._backend.on_new_message_for_customer.add_handler(
self._handle_new_message_for_customer_event
)
self._backend.on_conversation_rated.add_handler(self._handle_conversation_rated)

def _make_handlers(self) -> List[BaseHandler]:
return [
CommandHandler("start", self._handle_start_command),
CallbackQueryHandler(self._handle_callback_query),
MessageHandler(ChatType.PRIVATE & TEXT, self._handle_text_message),
MessageHandler(ChatType.PRIVATE & ~TEXT, self._handle_unsupported_message),
]

async def initialize(self):
await super().initialize()
await self._telegram_app.initialize()
Expand Down Expand Up @@ -130,7 +132,6 @@ async def _handle_text_message(self, update: Update, context: ContextTypes.DEFAU
async def _handle_unsupported_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
assert update.message, "message update should have `message`"
assert update.effective_chat, "message update should have `effective_chat`"
print(update.message)
await self._telegram_bot.send_message(
chat_id=update.effective_chat.id,
text=self._texts.telegram_customer_unsupported_message_content,
Expand Down
4 changes: 4 additions & 0 deletions suppgram/texts/en.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ class EnglishTextsProvider(TextsProvider):
"😞 Sorry, this kind of content is not supported right now. "
"Support agent will not see this message."
)
telegram_agent_unsupported_message_content = (
"😞 Sorry, this kind of content is not supported right now. "
"Customer will not see this message."
)

telegram_customer_start_message = "👋 Welcome to support service! Please describe your problem."
telegram_customer_conversation_resolved_message_placeholder = (
Expand Down
1 change: 1 addition & 0 deletions suppgram/texts/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class TextsProvider:
"""Provides static texts and functions to compose dynamic texts where necessary."""

telegram_customer_unsupported_message_content: str
telegram_agent_unsupported_message_content: str

telegram_customer_start_message: str
telegram_customer_conversation_resolved_message_placeholder: str
Expand Down
13 changes: 13 additions & 0 deletions tests/frontends/telegram/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,3 +386,16 @@ async def compose_telegram_update(
return update

return compose_telegram_update


@pytest.fixture
def sticker() -> Sticker:
return Sticker(
file_id="CAACAgQAAxkBAAIG-mWAv3L-CcgEs86whsGGTybEjjD6AAJ2AAMv3_gJdvG_3FZCYjgzBA",
file_unique_id="AgADdgADL9_4CQ",
width=512,
height=512,
is_animated=False,
is_video=False,
type=Sticker.REGULAR,
)
27 changes: 27 additions & 0 deletions tests/frontends/telegram/test_agent_frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,27 @@ async def test_nudge_to_start_bot(
)


@pytest.mark.asyncio
async def test_agent_unsupported_message_kind(
backend, telegram_update, sticker, customer_conversation, agent, workplaces, send_message_mock
):
await backend.assign_agent(agent, agent, customer_conversation.id)

update = await telegram_update(from_workplace=workplaces[0], sticker=sticker)
send_message_mock.assert_called_with(
chat_id=update.effective_chat.id,
text="😞 Sorry, this kind of content is not supported right now. "
"Customer will not see this message.",
reply_to_message_id=update.message.message_id,
)

update = await telegram_update(from_workplace=workplaces[1], sticker=sticker)
send_message_mock.assert_called_with(
chat_id=update.effective_chat.id,
text="📭 This chat is not assigned to any ongoing conversation with a customer right now.",
)


@pytest.mark.asyncio
async def test_agent_text_message_forwarding(
backend,
Expand All @@ -146,3 +167,9 @@ async def test_agent_text_message_forwarding(
customer_send_message_mock.assert_called_once_with(
chat_id=customer.telegram_user_id, text="How can I help you?"
)

await telegram_update(from_workplace=workplaces[1], text="How can I help you?")
agent_send_message_mocks[1].assert_called_with(
chat_id=agent.telegram_user_id,
text="📭 This chat is not assigned to any ongoing conversation with a customer right now.",
)
17 changes: 3 additions & 14 deletions tests/frontends/telegram/test_customer_frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from unittest import mock

import pytest
from telegram import InlineKeyboardMarkup, Sticker
from telegram import InlineKeyboardMarkup

from suppgram.entities import (
CustomerIdentification,
Expand All @@ -25,19 +25,8 @@ async def test_customer_start(storage, telegram_update, send_message_mock):


@pytest.mark.asyncio
async def test_customer_unsupported_message_kind(storage, telegram_update, send_message_mock):
update = await telegram_update(
from_customer=True,
sticker=Sticker(
file_id="CAACAgQAAxkBAAIG-mWAv3L-CcgEs86whsGGTybEjjD6AAJ2AAMv3_gJdvG_3FZCYjgzBA",
file_unique_id="AgADdgADL9_4CQ",
width=512,
height=512,
is_animated=False,
is_video=False,
type=Sticker.REGULAR,
),
)
async def test_customer_unsupported_message_kind(telegram_update, sticker, send_message_mock):
update = await telegram_update(from_customer=True, sticker=sticker)
send_message_mock.assert_called_once_with(
chat_id=update.effective_chat.id,
text="😞 Sorry, this kind of content is not supported right now. "
Expand Down

0 comments on commit f9b3109

Please sign in to comment.