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_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_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 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 controller(event_loop): """ Session-scoped fixture that all tests use to receive their BotController instance """ print("Initializing...") examples_dir = Path(__file__).parent.parent # Using the configuration of `config.ini` (see examples/README) client = InteractionClient( session_name="my_account", global_action_delay=1.8, # Space out all messages by 1.8 seconds workdir=examples_dir, # Load configuration from parent folder config_file=os.path.join(examples_dir, "config.ini"), ) controller = BotController( bot_under_test="@BotListBot", client=client, min_wait_consecutive= 2.0, # Wait at least 2 seconds to collect more than one message max_wait_response=10, # Wait a max of 10 seconds for responses, ... raise_no_response= False, # ... then check for response.empty instead of raising ) print("Starting integration test service...") await controller.start() # event_loop.run_until_complete(controller.start()) print("Client ready.") yield controller # py.test sugar to separate setup from teardown # Teardown await controller.stop()
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_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
def create_game_controller(client: Client = None) -> BotController: return BotController( peer="@IdleTownBot", client=client or create_client(), global_action_delay=2.0, # The @IdleTownBot has a spam limit of about 1.9s max_wait=8, # Maximum time in seconds to wait for a response from the bot wait_consecutive=None, # Do not wait for more than one message )
async def controller(client): c = BotController( client=client, peer="@WtfTicketsBot", max_wait=8.0, wait_consecutive=0.8, ) await c.initialize(start_client=False) yield c
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 controller(client): c = BotController( client=client, peer=bot_name, #peer="@BotListBot", max_wait=10.0, wait_consecutive=0.8, ) await c.initialize(start_client=False) yield c
def __init__(self, session_name, log_level=logging.INFO): self.purchase_balance = None self.withdrawal_balance = None self.diamonds = None self.menu = None # type: Optional[ReplyKeyboard] self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(log_level) client = InteractionClient(session_name=session_name, global_action_delay=1.0, config_file=os.path.join( examples_dir, 'config.ini')) self.controller = BotController(bot_under_test='@DinoParkNextBot', client=client) self.controller.start() self._update_keyboard() self.update_balance()
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_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_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_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 controller(client): c = BotController( client=client, peer= "@CovidReportsBot", # We are going to run tests on https://t.me/CovidReportsBot max_wait=10.0, # Maximum timeout for responses (optional) wait_consecutive= 0.8, # Minimum time to wait for more/consecutive messages (optional) ) await c.clear_chat() await c.initialize(start_client=False) yield c
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 controller(client, bot) -> BotController: bot_user = await bot.client.get_me() controller = BotController(peer=bot_user.username, client=client) await controller.initialize(start_client=False) return controller
from pyrogram import filters as f from tgintegration import BotController examples_dir = Path(__file__).parent print(examples_dir) # This example uses the configuration of `config.ini` (see examples/README) client = Client( "tgintegration_examples", config_file=str(examples_dir / "config.ini"), workdir=str(examples_dir), ) controller = BotController(peer="@deerspangle", client=client, raise_no_response=False) async def main(): await controller.initialize() while True: async with controller.collect( f.chat("@TgIntegration"), max_wait=30 ) as response: await client.send_message( "@TgIntegration", "Hi @deerspangle! Please say something in the next 30 seconds...", ) await client.send_message(
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!")
""" Full version of the GitHub README. """ import asyncio from tgintegration import BotController, InteractionClient print("Initializing service...") # This example uses the configuration of `config.ini` (see examples/README) client = InteractionClient( session_name="tgintegration_examples" # Arbitrary file path to the Pyrogram session file ) controller = BotController( bot_under_test="@BotListBot", client=client, max_wait_response=8, # Maximum timeout for bot responses min_wait_consecutive=2, # Minimum time to wait for consecutive messages raise_no_response=True, # Raise `InvalidResponseError` when no response received ) async def main(): print("Starting...") await controller.start() print("Clearing chat to start with a blank screen...") await controller.clear_chat() print("Send the /start command to the bot_under_test and 'await' exactly three messages...") response = await controller.send_command_await("start", num_expected=3)
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")
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
class DinoParkGame: VALUE_PATTERN = re.compile(r'^.*?\s*(\w+): ([\d ]+).*$', re.MULTILINE) NUMBERS_ONLY_PATTERN = re.compile(r'\b(\d[\d ]+)\b') def __init__(self, session_name, log_level=logging.INFO): self.purchase_balance = None self.withdrawal_balance = None self.diamonds = None self.menu = None # type: Optional[ReplyKeyboard] self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(log_level) client = InteractionClient(session_name=session_name, global_action_delay=1.0, config_file=os.path.join( examples_dir, 'config.ini')) self.controller = BotController(bot_under_test='@DinoParkNextBot', client=client) self.controller.start() self._update_keyboard() self.update_balance() def _update_keyboard(self): start = self.controller.send_command_await("start") self.menu = start.reply_keyboard def _extract_values(self, text): groups = self.VALUE_PATTERN.findall(text) try: return {g[0].lower(): str_to_int(g[1]) for g in groups} except KeyError: return {} def update_balance(self): balance_menu = self.menu.press_button_await(r'.*Balance') values = self._extract_values(balance_menu.full_text) self.purchase_balance = values['purchases'] self.withdrawal_balance = values['withdrawals'] diamonds_menu = self.menu.press_button_await(r'.*Farm') diamonds_values = self._extract_values(diamonds_menu.full_text) self.diamonds = diamonds_values['total'] self.logger.debug( "Balance updated: +{} for purchases, +{} for withdrawals, +{} diamonds." .format(self.purchase_balance, self.withdrawal_balance, self.diamonds)) def collect_diamonds(self): farm = self.menu.press_button_await(".*Farm") collected = farm.inline_keyboards[0].press_button_await( ".*Collect diamonds") num_collected = self._extract_values(collected.full_text).get( 'collected', 0) self.diamonds += num_collected self.logger.info("{} diamonds collected.".format( num_collected if num_collected > 0 else 'No')) def sell_diamonds(self): market = self.menu.press_button_await(r'.*Marketplace') if not market.inline_keyboards: self.logger.debug("No selling available at the moment.") return sold_msg = market.inline_keyboards[0].press_button_await( r'Sell diamonds.*') values = self.VALUE_PATTERN.findall(sold_msg.full_text) sold = str_to_int(values[0][1]) plus_purchase = str_to_int(values[1][1]) plus_withdrawal = str_to_int(values[2][1]) self.diamonds -= sold self.purchase_balance += plus_purchase self.withdrawal_balance += plus_withdrawal self.logger.info( "{} diamonds sold, +{} to purchase balance, +{} to withdrawal balance." .format(sold, plus_purchase, plus_withdrawal)) def buy_dinosaurs(self): """ Buy the best affordable dinosaurs """ dinos = self.menu.press_button_await(r'.*Dinosaurs').inline_keyboards[ 0].press_button_await(r'.*Buy dinosaurs') # Build up a list of cost per dino dino_cost_sequence = [] for msg in dinos.messages: # "Worth" in the message has no colon (:) before the number, therefore we use a numbers # only pattern values = self.NUMBERS_ONLY_PATTERN.findall(msg.caption) cost = str_to_int(values[0]) dino_cost_sequence.append(cost) while True: try: can_afford_id = next( x[0] for x in reversed(list(enumerate(dino_cost_sequence))) if x[1] <= self.purchase_balance) except StopIteration: self.logger.debug("Can't afford any dinosaurs.") # Can not afford any break bought = dinos.inline_keyboards[can_afford_id].press_button_await( r'.*Buy') self.logger.info("Bought dinosaur: " + bought.full_text) def play_lucky_number(self): lucky_number = self.menu.press_button_await( r'.*Games').reply_keyboard.press_button_await(r'.*Lucky number') bet = lucky_number.reply_keyboard.press_button_await( r'.*Place your bet') if 'only place one bet per' in bet.full_text.lower(): self.logger.debug("Already betted in this round") # Clean up self.controller.delete_messages( self.controller.peer_id, [bet.messages[0].message_id, bet.action_result.message_id]) return self.controller.send_message_await(str(random.randint(1, 30))) self.logger.debug("Bet placed.")
async def main(): # This example uses the configuration of `config.ini` (see examples/README) client = InteractionClient( session_name=SESSION_NAME, global_action_delay= 2.3, # The @IdleTownBot has a spam limit of about 1.9s workdir=examples_dir, # Load configuration from parent folder config_file=os.path.join(examples_dir, "config.ini"), ) controller = BotController( bot_under_test="@IdleTownBot", client=client, max_wait_response= 15, # Maximum time in seconds to wait for a response from the bot min_wait_consecutive=None, # Do not wait for more than one message ) client.load_config() await controller.start() for _ in range(MAX_RUNS or 999999): try: # Setup await controller.clear_chat() await asyncio.sleep(2) start = await controller.send_command_await("start") # Extract keyboard buttons of /start response main_buttons = get_buttons(start) # Get World Exp if possible if "worldexp" in main_buttons: worldexp = await controller.send_message_await( main_buttons["worldexp"]) confirm_buttons = get_buttons( await controller.send_message_await( get_buttons(worldexp)["claimx1"])) await controller.send_message_await(confirm_buttons["yes"]) # Construct buildings build_buttons = get_buttons(await controller.send_message_await( main_buttons["buildings"])) for building in ["lumbermill", "goldmine", "armory", "smithy"]: response_text = "" while "you don't have enough" not in response_text.lower(): response_text = (await controller.send_message_await( build_buttons[building])).full_text # Upgrade Hero Equipment hero = get_buttons(await controller.send_message_await( main_buttons["hero"])) equip_buttons = get_buttons(await controller.send_message_await( hero["equipment"])) # For every possible equipment, upgrade it until there are not enough resources left for equip in (b for k, b in equip_buttons.items() if "up" in k): while True: response_text = ( await controller.send_message_await(equip)).full_text if "you don't have enough" in response_text.lower(): break # Attack Player battle = get_buttons(await controller.send_message_await( main_buttons["battle"])) arena = get_buttons(await controller.send_message_await(battle["arena"])) normal_match = get_buttons(await controller.send_message_await( arena["normalmatch"])) if "fight" in normal_match: fight = get_buttons(await controller.send_message_await( normal_match["fight"])) # Attack Boss bosses = get_buttons(await controller.send_message_await(battle["bosses"] )) if "attackmax" in bosses: await controller.send_message_await(bosses["attackmax"]) except KeyboardInterrupt: print("Done.") break except: traceback.print_exc() pass await client.stop()
import os import asyncio from tgintegration import BotController, InteractionClient loop = asyncio.get_event_loop() client = InteractionClient( session_name='test_bot', # Arbitrary file path to the Pyrogram session file api_id=os.environ.get('BOT_API_ID'), # See "Requirements" above, ... api_hash=os.environ.get( 'BOT_API_HASH'), # alternatively use a `config.ini` file ) client = BotController( bot_under_test='@Shop_final_task_bot', client=client, max_wait_response=15, # Maximum timeout for bot re_sponses min_wait_consecutive=2 # Minimum time to wait for consecutive messages ) async def test(): await client.start() await client.clear_chat() response = await client.send_command_await('start', num_expected=1) assert response.num_messages == 1 assert 'Dear customer!' in response.messages[0].text inline_keyboard = response.inline_keyboards[0] assert len(inline_keyboard.rows[0]) == 2