Skip to content

Commit bad5213

Browse files
authored
Merge pull request #10 from ionet-official/fix/telegram-responds-when-not-tagged
fix telegram for responding all messages, even if not tagged
2 parents d533ae5 + dc4f5f3 commit bad5213

File tree

3 files changed

+65
-9
lines changed

3 files changed

+65
-9
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ The Discord bot responds to:
9696
### Telegram Bot
9797

9898
The Telegram bot responds to:
99-
- **All Messages**: Send any message directly to the bot
100-
- **Group Chats**: Add the bot to a group and interact normally
99+
- **Private Messages**: Send any message directly to the bot in private chat
100+
- **Mentions**: `@botusername hello there!` in group chats
101+
- **Replies**: Reply to any bot message in group chats
101102

102103
**Commands:**
103104
- `/help` - Show help information

app/telegram.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,23 @@ async def _handle_message(self, update: Update, context: ContextTypes.DEFAULT_TY
8989
user = update.effective_user
9090
chat_id = update.effective_chat.id
9191
message_text = update.message.text
92+
bot_username = context.bot.username
9293

9394
logger.debug(f"Received message from {user.first_name} in chat {chat_id}: {message_text[:100]}...")
9495

96+
# Check if bot should respond (similar to Discord logic)
97+
is_private_chat = update.effective_chat.type == 'private'
98+
is_mentioned = f"@{bot_username}" in message_text if bot_username else False
99+
is_reply_to_bot = (update.message.reply_to_message and
100+
update.message.reply_to_message.from_user and
101+
update.message.reply_to_message.from_user.id == context.bot.id)
102+
103+
logger.debug(f"Message triggers: private={is_private_chat}, mentioned={is_mentioned}, reply_to_bot={is_reply_to_bot}")
104+
105+
if not (is_private_chat or is_mentioned or is_reply_to_bot):
106+
logger.debug("Message doesn't trigger bot, ignoring")
107+
return
108+
95109
msg = Message(
96110
content=message_text,
97111
author=user.first_name or user.username or "Unknown",
@@ -128,7 +142,7 @@ async def _handle_message(self, update: Update, context: ContextTypes.DEFAULT_TY
128142
user_mention = f"@{user.username}" if user.username else user.first_name or "User"
129143
response_text = f"{user_mention} {msg.content}"
130144

131-
await update.message.reply_text(response_text)
145+
await update.message.reply_text(response_text, parse_mode='Markdown')
132146
break
133147
else:
134148
logger.error("Message processor not initialized")

tests/test_telegram.py

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,11 @@ async def test_clear_command_without_context(self, telegram_bot):
124124

125125
@pytest.mark.asyncio
126126
async def test_handle_message_success(self, telegram_bot):
127-
"""Test successful message handling"""
127+
"""Test successful message handling with bot mention"""
128128
# Create mock update
129129
update = Mock()
130130
update.message = Mock()
131-
update.message.text = "Hello bot!"
131+
update.message.text = "Hello @testbot!" # Include bot mention
132132
update.effective_user = Mock()
133133
update.effective_user.first_name = "TestUser"
134134
update.effective_user.username = "testuser"
@@ -137,10 +137,13 @@ async def test_handle_message_success(self, telegram_bot):
137137
update.message.date.timestamp.return_value = 1234567890.0
138138
update.message.message_id = 456
139139
update.message.reply_text = AsyncMock()
140+
update.message.reply_to_message = None # No reply
140141

141142
# Create mock context
142143
context = Mock()
143144
context.bot.send_chat_action = AsyncMock()
145+
context.bot.username = "testbot" # Set bot username for mention detection
146+
context.bot.id = 999 # Bot ID
144147

145148
# Mock message processor
146149
telegram_bot.message_processor.add_message = AsyncMock()
@@ -162,7 +165,7 @@ async def test_handle_message_success(self, telegram_bot):
162165
assert isinstance(call_args[0][1], Message)
163166

164167
# Verify response was sent with user mention (since it's a group chat)
165-
update.message.reply_text.assert_called_once_with("@testuser Hi there!")
168+
update.message.reply_text.assert_called_once_with("@testuser Hi there!", parse_mode='Markdown')
166169

167170
# Verify typing action was sent
168171
context.bot.send_chat_action.assert_called_once_with(chat_id=123, action="typing")
@@ -201,7 +204,7 @@ async def test_handle_message_private_chat(self, telegram_bot):
201204
await telegram_bot._handle_message(update, context)
202205

203206
# Verify response was sent without user mention (since it's a private chat)
204-
update.message.reply_text.assert_called_once_with("Hi there!")
207+
update.message.reply_text.assert_called_once_with("Hi there!", parse_mode='Markdown')
205208

206209
@pytest.mark.asyncio
207210
async def test_handle_message_no_text(self, telegram_bot):
@@ -251,20 +254,24 @@ async def test_handle_message_no_processor(self, telegram_bot):
251254

252255
@pytest.mark.asyncio
253256
async def test_handle_message_user_name_fallback(self, telegram_bot):
254-
"""Test message handling with username fallback"""
257+
"""Test message handling with username fallback in private chat"""
255258
update = Mock()
256259
update.message = Mock()
257260
update.message.text = "Hello"
258261
update.effective_user = Mock()
259262
update.effective_user.first_name = None # No first name
260263
update.effective_user.username = "testuser"
261264
update.effective_chat.id = 123
265+
update.effective_chat.type = 'private' # Private chat - no mention needed
262266
update.message.date.timestamp.return_value = time.time()
263267
update.message.message_id = 456
264268
update.message.reply_text = AsyncMock()
269+
update.message.reply_to_message = None
265270

266271
context = Mock()
267272
context.bot.send_chat_action = AsyncMock()
273+
context.bot.username = "testbot"
274+
context.bot.id = 999
268275

269276
telegram_bot.message_processor.add_message = AsyncMock()
270277
telegram_bot.message_processor.contexts = {123: Mock()}
@@ -280,20 +287,24 @@ async def test_handle_message_user_name_fallback(self, telegram_bot):
280287

281288
@pytest.mark.asyncio
282289
async def test_handle_message_unknown_user_fallback(self, telegram_bot):
283-
"""Test message handling with 'Unknown' fallback"""
290+
"""Test message handling with 'Unknown' fallback in private chat"""
284291
update = Mock()
285292
update.message = Mock()
286293
update.message.text = "Hello"
287294
update.effective_user = Mock()
288295
update.effective_user.first_name = None
289296
update.effective_user.username = None
290297
update.effective_chat.id = 123
298+
update.effective_chat.type = 'private' # Private chat - no mention needed
291299
update.message.date.timestamp.return_value = time.time()
292300
update.message.message_id = 456
293301
update.message.reply_text = AsyncMock()
302+
update.message.reply_to_message = None
294303

295304
context = Mock()
296305
context.bot.send_chat_action = AsyncMock()
306+
context.bot.username = "testbot"
307+
context.bot.id = 999
297308

298309
telegram_bot.message_processor.add_message = AsyncMock()
299310
telegram_bot.message_processor.contexts = {123: Mock()}
@@ -307,6 +318,36 @@ async def test_handle_message_unknown_user_fallback(self, telegram_bot):
307318
message = call_args[0][1]
308319
assert message.author == "Unknown"
309320

321+
@pytest.mark.asyncio
322+
async def test_handle_message_ignores_non_triggered_messages(self, telegram_bot):
323+
"""Test that bot ignores messages in groups without mention/reply"""
324+
update = Mock()
325+
update.message = Mock()
326+
update.message.text = "Hello everyone!" # No bot mention
327+
update.effective_user = Mock()
328+
update.effective_user.first_name = "TestUser"
329+
update.effective_user.username = "testuser"
330+
update.effective_chat.id = 123
331+
update.effective_chat.type = 'group' # Group chat
332+
update.message.date.timestamp.return_value = time.time()
333+
update.message.message_id = 456
334+
update.message.reply_text = AsyncMock()
335+
update.message.reply_to_message = None # No reply
336+
337+
context = Mock()
338+
context.bot.send_chat_action = AsyncMock()
339+
context.bot.username = "testbot"
340+
context.bot.id = 999
341+
342+
telegram_bot.message_processor.add_message = AsyncMock()
343+
344+
await telegram_bot._handle_message(update, context)
345+
346+
# Verify message was NOT added to processor (bot should ignore it)
347+
telegram_bot.message_processor.add_message.assert_not_called()
348+
update.message.reply_text.assert_not_called()
349+
context.bot.send_chat_action.assert_not_called()
350+
310351
@pytest.mark.asyncio
311352
async def test_handle_message_waits_for_processing(self, telegram_bot):
312353
"""Test that message handling waits for processing to complete"""

0 commit comments

Comments
 (0)