async def test_block_commands(controller: BotController): # - create block, list blocks, remove block, list blocks async with controller.collect(count=1) as response: await controller.send_command("add_blocklisted_tag", ["test"]) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Added tag to blocklist: \"test\".") lines = response.messages[0].text.html.split("\n") assert "Current blocklist for this chat:" in lines assert "- test" in lines async with controller.collect(count=1) as response: await controller.send_command("list_blocklisted_tags") assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current blocklist for this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" in lines async with controller.collect(count=1) as response: await controller.send_command("remove_blocklisted_tag", ["test"]) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Removed tag from blocklist: \"test\".") lines = response.messages[0].text.html.split("\n") assert "Current blocklist for this chat:" in lines assert "- test" not in lines async with controller.collect(count=1) as response: await controller.send_command("list_blocklisted_tags") assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current blocklist for this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" not in lines
async def test_neaten_link_in_button_with_image(controller: BotController, bot: FASearchBot): # Creating an example message to forward to the bot client_user = await controller.client.get_me() user_id = client_user.id async with controller.collect(count=1) as test_msg: requests.post( f"https://api.telegram.org/bot{bot.bot_key}/sendPhoto", json={ "chat_id": user_id, "photo": "https://t.furaffinity.net/[email protected]", "reply_markup": { "inline_keyboard": [[{ "text": "View on FA", "url": "https://www.furaffinity.net/view/19925704/" }]] } }) msg_id = test_msg.messages[0].message_id # Run the test async with controller.collect(count=2) as response: await controller.client.forward_messages(controller.peer_id, controller.peer_id, msg_id) assert response.num_messages == 2 assert response.messages[0].text.startswith("⏳") assert "19925704" in response.messages[-1].caption assert response.messages[-1].photo
async def test_group_migration(controller: BotController, group_chat: Chat): # Create subscription async with controller.collect(count=1, peer=group_chat.id) as response: await controller.send_command("add_subscription", ["test"], peer=group_chat.id) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Added subscription: \"test\".") lines = response.messages[0].text.html.split("\n") assert len(lines) >= 3 assert "Current subscriptions in this chat:" in lines assert "- test" in lines # List subscriptions async with controller.collect(count=1, peer=group_chat.id) as response: await controller.send_command("list_subscriptions", peer=group_chat.id) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current subscriptions in this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" in lines # Migrate chat to supergroup updates = await controller.client.send( MigrateChat(chat_id=abs(group_chat.id))) new_chat_id = int( f"-100{[chat.id for chat in updates.chats if chat.id != abs(group_chat.id)][0]}" ) group_chat.id = new_chat_id # List subscriptions async with controller.collect(count=1, peer=new_chat_id) as response: await controller.send_command("list_subscriptions", peer=new_chat_id) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current subscriptions in this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" in lines # Delete subscription async with controller.collect(count=1, peer=new_chat_id) as response: await controller.send_command("remove_subscription", ["test"], peer=new_chat_id) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Removed subscription: \"test\".") lines = response.messages[0].text.html.split("\n") assert "- test" not in lines # List subscriptions async with controller.collect(count=1, peer=new_chat_id) as response: await controller.send_command("list_subscriptions", peer=new_chat_id) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current subscriptions in this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" not in lines
async def test_start(controller: BotController): # - Get start message async with controller.collect(count=1) as response: await controller.send_command("/start") assert response.num_messages == 1 assert "@deerspangle" in response.messages[0].text
async def test_commands(controller: BotController): # The BotController automatically loads the available commands and we test them all here for c in controller.command_list: async with controller.collect() as res: # type: Response await controller.send_command(c.command) assert not res.is_empty, "Bot did not respond to command /{}.".format( c.command)
async def test_neaten_link(controller: BotController): # - send link, get neatened pic async with controller.collect(count=2) as response: await controller.client.send_message( controller.peer_id, "https://www.furaffinity.net/view/19925704/") assert response.num_messages == 2 assert response.messages[0].text.startswith("⏳") assert "19925704" in response.messages[-1].caption assert response.messages[-1].photo
async def run_example(client: Client): controller = BotController( peer="@StatInfoTestBot", client=client, max_wait=8, # Maximum timeout for responses (optional) wait_consecutive= 2, # Minimum time to wait for more/consecutive messages (optional) raise_no_response= True, # Raise `InvalidResponseError` when no response received (defaults to True) global_action_delay= 2.5, # Choosing a rather high delay so we can follow along in realtime (optional) ) # expecting 2 messages in reply for /start command async with controller.collect(count=2) as response: # type: Response await controller.send_command("start") assert response.num_messages == 2 async with controller.collect(count=1) as response: # type: Response await controller.send_command("help") assert response.num_messages == 1 assert "The following commands are available" in response.full_text async with controller.collect(count=1) as response: # type: Response await controller.send_command("statistics") assert response.num_messages == 1 # expecting to get statistics for today current_date = str(date.today()) assert current_date in response.full_text async with controller.collect(count=1) as response: # type: Response await controller.send_command("country") assert response.num_messages == 1 assert "Please, enter country name." in response.full_text async with controller.collect(count=1) as response: # type: Response await client.send_message(controller.peer_id, "Russian Federation") assert response.num_messages == 1 assert "Russian Federation" in response.full_text async with controller.collect(count=1) as response: # type: Response await controller.send_command("contacts") assert response.num_messages == 1 assert "4 members" in response.full_text async with controller.collect(count=1) as response: # type: Response await client.send_message(controller.peer_id, "hi") assert response.num_messages == 1 assert "To get to know me better" in response.full_text
async def test_no_neaten_caption_in_group(controller: BotController, group_chat: Chat): # - in group neaten doesn't reply to image with caption link group_id = group_chat.id thumb_link = "https://t.furaffinity.net/[email protected]" async with controller.collect(peer=group_id, raise_=False) as response: await controller.client.send_photo( group_id, thumb_link, caption="https://www.furaffinity.net/view/19925704/") assert response.num_messages == 0
async def test_neaten_link_in_group(controller: BotController, group_chat: Chat): # - neaten link in group group_id = group_chat.id async with controller.collect(count=2, peer=group_id) as response: await controller.client.send_message( group_id, "https://www.furaffinity.net/view/19925704/") assert response.num_messages == 2 assert response.messages[0].text.startswith("⏳") assert "19925704" in response.messages[-1].caption assert response.messages[-1].photo
async def test_neaten_pdf_link(controller: BotController): # - send link, get neatened pic async with controller.collect(count=2) as response: await controller.client.send_message( controller.peer_id, "https://www.furaffinity.net/view/41734655/") assert response.num_messages == 2 assert response.messages[0].text.startswith("⏳") assert "41734655" in response.messages[-1].caption assert "Jaystoat" in response.messages[-1].caption assert "Lights In The Sky" in response.messages[-1].caption assert response.messages[-1].document
async def test_run_example(controller: BotController, client): await controller.clear_chat() async with controller.collect(count=1) as response: # type: Response await controller.send_command("start") assert response.num_messages == 1 async with controller.collect(count=1) as response: # type: Response await client.send_message(controller.peer_id, "1") assert response.num_messages == 1 inline_keyboard = response.reply_keyboard async with controller.collect(count=1) as response: # type: Response await inline_keyboard.click(pattern="1") assert response.num_messages == 1 async with controller.collect(count=2) as response: # type: Response await client.send_message(controller.peer_id, "Wrong message") assert response.num_messages == 2 assert "Введите число с клавиатуры" in response.full_text while r"Ваш результат" not in response.full_text: async with controller.collect(count=1) as response: # type: Response await inline_keyboard.click(pattern="1") async with controller.collect(count=1) as response: # type: Response await inline_keyboard.click(pattern="1") assert "Вы также можете создать свой собственный тест по команде /create" \ in response.full_text
async def test_neaten_gif(controller: BotController): # - send link, make pretty gif submission_id = "27408045" # Delete cache filename = f"{FASubmission.GIF_CACHE_DIR}/{submission_id}.mp4" if os.path.exists(filename): os.remove(filename) # Send neaten command async with controller.collect(count=2, max_wait=300) as response: await controller.client.send_message( controller.peer_id, f"https://www.furaffinity.net/view/{submission_id}/") assert response.num_messages == 2 assert response.messages[0].text.startswith("⏳") assert submission_id in response.messages[-1].caption assert response.messages[-1].animation
async def test_neaten_gif_from_cache(controller: BotController, bot: FASearchBot): # - send link, get pretty gif from cache submission_id = "27408045" # Populate cache submission = await bot.api.get_full_submission(submission_id) filename = submission._get_gif_from_cache() if filename is None: output_path = await submission._convert_gif(submission.download_url) submission._save_gif_to_cache(output_path) async with controller.collect(count=2) as response: await controller.client.send_message( controller.peer_id, "https://www.furaffinity.net/view/27408045/") assert response.num_messages == 2 assert response.messages[0].text.startswith("⏳") assert submission_id in response.messages[-1].caption assert response.messages[-1].animation
async def test_explore_button(controller: BotController): # Send /start to peer_user and wait for 3 messages async with controller.collect(count=3) as start: await controller.send_command("/start") # Click the "Explore" keyboard button explore = await start.reply_keyboard.click(pattern=r".*Explore") assert not explore.is_empty, 'Pressing the "Explore" button had no effect.' assert explore.inline_keyboards, 'The "Explore" message had no inline keyboard.' # Click the "Explore" inline keyboard button 10 times or until it says that # all bots have been explored count = 10 while "explored all the bots" not in explore.full_text: if count == 0: break # ok # Pressing an inline button also makes the BotController listen for edit events. explore = await explore.inline_keyboards[0].click(index=2) assert not explore.is_empty, 'Pressing the "Explore" button had no effect.' count -= 1
async def run_example(client: Client): controller = BotController( peer= "@BotListBot", # We are going to run tests on https://t.me/BotListBot client=client, max_wait=8, # Maximum timeout for responses (optional) wait_consecutive= 2, # Minimum time to wait for more/consecutive messages (optional) raise_no_response= True, # Raise `InvalidResponseError` when no response received (defaults to True) global_action_delay= 2.5, # Choosing a rather high delay so we can follow along in realtime (optional) ) print("Clearing chat to start with a blank screen...") await controller.clear_chat() print("Sending /start and waiting for exactly 3 messages...") async with controller.collect(count=3) as response: # type: Response await controller.send_command("start") assert response.num_messages == 3 print("Three messages received, bundled as a `Response`.") assert response.messages[0].sticker print("First message is a sticker.") print("Let's examine the buttons in the response...") inline_keyboard = response.inline_keyboards[0] assert len(inline_keyboard.rows[0]) == 3 print("Yep, there are three buttons in the first row.") # We can also press the inline keyboard buttons, in this case based on a pattern: print("Clicking the button matching the regex r'.*Examples'") examples = await inline_keyboard.click(pattern=r".*Examples") assert "Examples for contributing to the BotList" in examples.full_text # As the bot edits the message, `.click()` automatically listens for "message edited" # updates and returns the new state as `Response`. print( "So what happens when we send an invalid query or the peer fails to respond?" ) from tgintegration import InvalidResponseError try: # The following instruction will raise an `InvalidResponseError` after # `controller.max_wait` seconds. This is because we passed `raise_no_response=True` # during controller initialization. print("Expecting unhandled command to raise InvalidResponseError...") async with controller.collect(): await controller.send_command("ayylmao") except InvalidResponseError: print("Ok, raised as expected.") # If `raise_` is explicitly set to False, no exception is raised async with controller.collect(raise_=False) as response: # type: Response print("Sending a message but expecting no reply...") await client.send_message(controller.peer_id, "Henlo Fren") # In this case, tgintegration will simply emit a warning, but you can still assert # that no response has been received by using the `is_empty` property. assert response.is_empty print("Success!")
async def test_subscription_commands(controller: BotController): # - create subscription, list subscriptions, remove subscription, list subscriptions async with controller.collect(count=1) as response: await controller.send_command("add_subscription", ["test"]) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Added subscription: \"test\".") lines = response.messages[0].text.html.split("\n") assert len(lines) >= 3 assert "Current subscriptions in this chat:" in lines assert "- test" in lines async with controller.collect(count=1) as response: await controller.send_command("list_subscriptions") assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current subscriptions in this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" in lines async with controller.collect(count=1) as response: await controller.send_command("pause", ["test"]) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Paused subscription: \"test\".") lines = response.messages[0].text.html.split("\n") assert "- ⏸<s>test</s>" in lines async with controller.collect(count=1) as response: await controller.send_command("list_subscriptions") assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current subscriptions in this chat:") lines = response.messages[0].text.html.split("\n") assert "- ⏸<s>test</s>" in lines async with controller.collect(count=1) as response: await controller.send_command("resume", ["test"]) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Resumed subscription: \"test\".") lines = response.messages[0].text.html.split("\n") assert "- test" in lines async with controller.collect(count=1) as response: await controller.send_command("list_subscriptions") assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current subscriptions in this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" in lines async with controller.collect(count=1) as response: await controller.send_command("remove_subscription", ["test"]) assert response.num_messages == 1 assert response.messages[0].text.startswith( "Removed subscription: \"test\".") lines = response.messages[0].text.html.split("\n") assert "- test" not in lines async with controller.collect(count=1) as response: await controller.send_command("list_subscriptions") assert response.num_messages == 1 assert response.messages[0].text.startswith( "Current subscriptions in this chat:") lines = response.messages[0].text.html.split("\n") assert "- test" not in lines
async def perform_full_run(controller: BotController, max_upgrades_per_type: int = 5): # Setup await controller.clear_chat() await asyncio.sleep(2) async def restart() -> Response: async with controller.collect(f.text) as start: await controller.send_command("restart", add_bot_name=False) return start # Extract keyboard buttons of /start response main_menu = get_buttons(await restart()) async def click_button(menu: Dict[str, str], key: str) -> Dict[str, str]: async with controller.collect() as response: # type: Response await controller.client.send_message(controller.peer_id, menu[key]) return get_buttons(response) # Get World Exp if possible if "worldexp" in main_menu: worldexp_menu = await click_button(main_menu, "worldexp") confirm_menu = await click_button(worldexp_menu, "claimx1") await click_button(confirm_menu, "yes") # Construct buildings build_menu = await click_button(main_menu, "buildings") for building in ["lumbermill", "goldmine", "armory", "smithy"]: num_upgraded = 0 while num_upgraded < max_upgrades_per_type: async with controller.collect() as build_response: await controller.client.send_message( controller.peer_id, build_menu[building] ) if "you don't have enough" in build_response.full_text.lower(): break num_upgraded += 1 # Upgrade Hero Equipment hero_menu = await click_button(main_menu, "hero") equip_menu = await click_button(hero_menu, "equipment") # For every possible equipment, upgrade it until there are not enough resources left for equip_button in (k for k in equip_menu.keys() if k.startswith("up")): num_upgraded = 0 while num_upgraded < max_upgrades_per_type: async with controller.collect() as upgrade_response: await controller.client.send_message( controller.peer_id, equip_menu[equip_button] ) if "you don't have enough" in upgrade_response.full_text.lower(): break num_upgraded += 1 # Attack Player battle_menu = await click_button(main_menu, "battle") arena_menu = await click_button(battle_menu, "arena") normal_match_menu = await click_button(arena_menu, "normalmatch") if "fight" in normal_match_menu: await click_button(normal_match_menu, "fight") # Attack Boss bosses_menu = await click_button(battle_menu, "bosses") if "attackmax" in bosses_menu: await click_button(bosses_menu, "attackmax")