async def test_react_errors(helper, client, bot_group, slave, channel): chat = slave.group with link_chats(channel, (chat, ), bot_group): efb_msg = slave.send_text_message(chat=chat, reactions=True) tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) # Entire slave channel doesn’t support reactions with patch.multiple(slave, suggested_reactions=None): await tg_msg.reply("/react FullChannelFail") await helper.wait_for_message_text(in_chats(bot_group)) # Arbitrary error message # Reaction value is invalid with slave.set_react_to_message("reject_one"): await tg_msg.reply("/react ReactionValueFail") text = await helper.wait_for_message_text(in_chats(bot_group)) # Error message with suggestions for i in slave.suggested_reactions: assert i in text # Reaction target (chat/message) is invalid with slave.set_react_to_message("reject_all"): await tg_msg.reply("/react ReactionTargetFail") await helper.wait_for_message_text(in_chats(bot_group))
async def test_slave_message_name(helper, client, bot_group, slave, channel): chat = slave.group member = chat.members[2] assert "&" in member.name with link_chats(channel, (chat, ), bot_group): efb_msg = slave.send_text_message(chat=chat, author=member) tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) assert member.name in tg_msg.raw_text
async def test_slave_message_notification_your_silent(helper, client, bot_group, slave, channel, chat_caller, mention): chat = chat_caller(slave) with link_chats(channel, (chat,), bot_group), \ patch.dict(channel.flag.config, your_message_on_slave="silent"): efb_msg = slave.send_text_message(chat=chat, substitution=mention) tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) assert tg_msg.silent
async def test_slave_message_notification_your_mute(helper, client, bot_group, slave, channel, chat_caller, mention): chat = chat_caller(slave) with link_chats(channel, (chat,), bot_group), \ patch.dict(channel.flag.config, your_message_on_slave="mute"): efb_msg = slave.send_text_message(chat=chat, substitution=mention) with raises(asyncio.TimeoutError): await helper.wait_for_message(in_chats(bot_group) & regex(efb_msg.text), timeout=3)
async def test_slave_message_reactions(helper, client, bot_group, slave, channel): chat = slave.group with link_chats(channel, (chat, ), bot_group): efb_msg = slave.send_text_message(chat=chat, reactions=True) tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) reactions_status = slave.send_reactions_update(efb_msg) tg_msg = await helper.wait_for_message( in_chats(bot_group) & edited(tg_msg.id)) for reaction, members in reactions_status.reactions.items(): assert reaction in tg_msg.text
async def test_rm_edit(helper, client, bot_group, slave, channel): chat = slave.chat_with_alias with link_chats(channel, (chat,), bot_group): content = "test_rm_edit message to be removed" tg_msg = await client.send_message(bot_group, content) message = slave.messages.get(timeout=5) await tg_msg.edit(text=f"rm`{tg_msg.text}") # wait for message removal prompt await helper.wait_for_message(in_chats(bot_group)) removal_status = slave.statuses.get(timeout=5) assert isinstance(removal_status, MessageRemoval) assert removal_status.message.chat == message.chat assert removal_status.message.uid == message.uid
async def test_react_get_reactors_list(helper, client, bot_group, slave, channel): chat = slave.group with link_chats(channel, (chat, ), bot_group): efb_msg = slave.send_text_message(chat=chat, reactions=True) tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) await tg_msg.reply("/react") tg_msg_listing = await helper.wait_for_message(in_chats(bot_group)) for reaction, members in efb_msg.reactions.items(): assert reaction in tg_msg.text assert reaction in tg_msg_listing.text for member in members: assert member.display_name in tg_msg_listing.text
async def test_slave_message_author_external(helper, client, bot_group, slave, channel): chat = slave.chat_with_alias author = chat.make_system_member(uid="member_from_middleware", name="Middleware Member") author.module_id = "unknown.middleware" author.module_name = "Unknown middleware" author.channel_emoji = "" with link_chats(channel, (chat, ), bot_group): # Ping / Pong efb_msg = slave.send_text_message(chat=chat, author=author, commands=True) tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) assert author.name in tg_msg.text
async def test_slave_message_command(helper, client, bot_group, slave, channel): chat = slave.chat_with_alias with link_chats(channel, (chat,), bot_group): # Ping / Pong efb_msg = slave.send_text_message(chat=chat, author=chat.other, commands=True) tg_msg = await helper.wait_for_message(in_chats(bot_group) & regex(efb_msg.text)) assert tg_msg.button_count == len(efb_msg.commands) assert tg_msg.buttons[0][0].text == "Ping!" assert tg_msg.buttons[1][0].text == "Bam" response: BotCallbackAnswer = await tg_msg.click(0) assert slave.command_ping() in response.message # Bam (None return value) efb_msg = slave.send_text_message(chat=chat, commands=True) tg_msg = await helper.wait_for_message(in_chats(bot_group) & regex(efb_msg.text)) response = await tg_msg.click(1) assert response.message is None
async def test_rm_command_removal(helper, client, bot_group, slave, channel): chat = slave.chat_with_alias with link_chats(channel, (chat,), bot_group): message = slave.send_text_message(chat, chat.other) with slave.set_message_removal(False): tg_msg = await helper.wait_for_message(in_chats(bot_group) & regex(message.text)) await tg_msg.reply("/rm") # wait for error message await helper.wait_for_message(in_chats(bot_group)) assert slave.statuses.empty(), "Message removal should be failed." await tg_msg.reply("/rm") # wait for message removal prompt await helper.wait_for_message(in_chats(bot_group)) removal_status = slave.statuses.get(timeout=5) assert isinstance(removal_status, MessageRemoval) assert removal_status.message.chat == message.chat assert removal_status.message.uid == message.uid
async def test_slave_message_notification(helper, client, bot_group, slave, channel, notification_state, mentioned): chat = slave.get_chat_by_criteria(chat_type="PrivateChat", notification=notification_state) with link_chats(channel, (chat,), bot_group), \ patch.dict(channel.flag.config, message_muted_on_slave="silent"): efb_msg = slave.send_text_message(chat=chat, author=chat.other, substitution=mentioned) tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) if notification_state == ChatNotificationState.NONE: should_be_silent = True elif notification_state == ChatNotificationState.MENTIONS: should_be_silent = not mentioned else: # ChatNotificationState.ALL should_be_silent = False assert tg_msg.silent == should_be_silent
async def test_react_send_and_retract_reaction(helper, client, bot_group, slave, channel): chat = slave.group reaction = "ETM" with link_chats(channel, (chat, ), bot_group): tg_msg: Message = await client.send_message( bot_group, "test_react_send_and_retract_reaction outgoing message to react on." ) slave.messages.get(timeout=5) # Send reaction await tg_msg.reply(f"/react {reaction}") edited_tg_msg = await helper.wait_for_message( in_chats(bot_group) & reply_to(tg_msg.id)) assert reaction in edited_tg_msg.text # Retract reaction await tg_msg.reply(f"/react -") edited_tg_msg = await helper.wait_for_message( in_chats(bot_group) & edited(edited_tg_msg.id)) assert reaction not in edited_tg_msg.text
async def test_slave_message_file_oversize(helper, client, bot_group, slave, channel): chat = slave.chat_with_alias with link_chats(channel, (chat,), bot_group),\ NamedTemporaryFile(suffix=".bin") as f: # Write a large enough file f.truncate(MAX_FILESIZE_UPLOAD + 1024 * 10) f.seek(0) # Send it efb_msg = slave.send_file_like_message(MsgType.File, Path(f.name), mime="application/octet-stream", chat=chat, author=chat.other, commands=True) # Expect a text message and an error message tg_msg = await helper.wait_for_message( in_chats(bot_group) & regex(efb_msg.text)) assert not tg_msg.file await helper.wait_for_message( in_chats(bot_group) & reply_to(tg_msg.id))
async def test_rm_command_delete(helper, client, bot_id, bot_group, slave, channel): chat = slave.chat_with_alias with patch.dict(channel.flag.config, prevent_message_removal=False): # successful case: send to private chat # get chat head await client.send_message(bot_id, f"/chat {chat.uid}") tg_msg = await helper.wait_for_message(in_chats(bot_id) & has_button) await tg_msg.click(0) tg_msg = await helper.wait_for_message(in_chats(bot_id) & ~has_button) content = "test_rm_command_delete message to be removed from Telegram in private chat" tg_msg = await tg_msg.reply(content) assert slave.messages.get(timeout=5) await tg_msg.edit(text=f"rm`{tg_msg.text}") await helper.wait_for_event(deleted(tg_msg)) # Failure case: send prompt with link_chats(channel, (chat,), bot_group): content = "test_rm_command_delete message to be removed from Telegram but failed" tg_msg = await client.send_message(bot_group, content) assert slave.messages.get(timeout=5) await tg_msg.edit(text=f"rm`{tg_msg.text}") await helper.wait_for_message(in_chats(bot_group))
async def test_slave_message(helper, client, bot_group, slave, channel, factory: MessageFactory): chat = slave.group with link_chats(channel, (chat, ), bot_group): message_ids = [] efb_msg = factory.send_message(slave, chat) tg_msg = await helper.wait_for_message(in_chats(bot_group)) message_ids.append(tg_msg.id) factory.compare_message(tg_msg, efb_msg) edited_efb_msg = factory.edit_message(slave, efb_msg) if edited_efb_msg is not None: filters = in_chats(bot_group) if factory.content_editable: filters &= edited(*message_ids) tg_msg = await helper.wait_for_message(filters) if not factory.content_editable: message_ids.append(tg_msg.id) factory.compare_message(tg_msg, edited_efb_msg) edited_media_efb_msg = factory.edit_message_media(slave, efb_msg) if edited_media_efb_msg is not None: filters = in_chats(bot_group) if factory.media_editable: filters &= edited(*message_ids) await helper.wait_for_message(filters) # Get only the second message as editing media with caption takes 2 steps tg_msg = await helper.wait_for_message(filters) if not factory.media_editable: message_ids.append(tg_msg.id) factory.compare_message(tg_msg, edited_media_efb_msg) targeted_message = factory.send_message(slave, chat, target=efb_msg) targeted_tg_msg = await helper.wait_for_message( in_chats(bot_group) & reply_to(*message_ids)) factory.compare_message(targeted_tg_msg, targeted_message)