def rename_group_command(client: BotIntegrationClient, menu): new_name = generate_name() menu.inline_keyboards[0].press_button_await(pattern=r'.*Rename group', min_wait_consecutive=5) response = client.send_message_await(new_name, num_expected=2) assert response[0].text.startswith('Saved') assert response[1].text.startswith('Choose an action') assert group_is_existing(client, new_name) return new_name
def create_group_command(client: BotIntegrationClient, generated_name: str = None): if not generated_name: generated_name = generate_name() client.send_command_await('/create', num_expected=1) response = client.send_message_await(generated_name) assert response.full_text.startswith('Saved'), \ "Correctly saved responses start with 'Saved.'" return generated_name
def test_categories(client: BotIntegrationClient): # Responses implement __eq__ assert (client.send_command_await("categories") == client.send_message_await(captions.CATEGORIES)) cat = client.send_command_await("categories", num_expected=1) social = cat.inline_keyboards[0].press_button_await(pattern=r'.*Social') ilkb = social.inline_keyboards[0] assert ilkb.num_buttons > 3 share_btn = ilkb.find_button(r'Share') assert 'Social' in share_btn.switch_inline_query
def test_explore_button(client: BotIntegrationClient): res = client.send_command_await("/start", num_expected=3) btn = next(x for x in res.keyboard_buttons if 'explore' in x.lower()) explore = client.send_message_await(btn) assert explore.num_messages == 1 count = 10 while "explored all the bots" not in explore.full_text: if count == 0: break # ok explore = explore.inline_keyboards[0].press_button_await( pattern=r'.*🔄') # emoji count -= 1
def test_search(client: BotIntegrationClient, bots): for username in bots: # First send the username in private chat to get target description of the bot res = client.send_message_await(username, num_expected=1) assert not res.empty, "Bot did not yield a response for username {}.".format( username) full_expected = res.full_text res = client.get_inline_bot_results(client.peer_id, username) results = res.find_results(title_pattern=re.compile( r'{}\b.*'.format(username), re.IGNORECASE)) assert len(results) == 1, "Not exactly one result for {}".format( username) # Description of bot should be the same in inline query message and private message assert full_expected in results.pop().result.send_message.message, \ "Message texts did not match."
def test_add_members_to_existing_group(client: BotIntegrationClient): client.send_message(text="test_add_members_to_existing_group", chat_id=config('BOT_NAME')) group_name = create_group_command(client) group_name = enter_group(client, group_name) button = group_name.inline_keyboards[0].press_button_await( pattern=r'.*Add members', min_wait_consecutive=5) assert not button.empty, 'Pressing "Add members" button had no effect.' assert button.full_text.startswith( 'Ok, send'), "Adding users' message has been changed." user_name = generate_name() response = client.send_message_await(user_name, num_expected=1) assert response.full_text.startswith("Added") response = client.send_command_await("/done", num_expected=2) assert response[0].text.startswith('Saved new members') members = response[1].text.split('\n')[3:] members = [item.split()[1] for item in members] assert user_name in members, "User hasn't been added"
# `service.max_wait_response` seconds. This is because we passed `raise_no_response = True` # in the service initialization. print("Expecting undefined command to raise InvalidResponseError...") client.send_command_await("ayylmao", raise_=True) except InvalidResponseError: print("Raised.") # Ok # The `BotController` is based off a regular Pyrogram Client, meaning that, in addition to # the `send_*_await` methods, all normal Pyro methods still work: print("Calling a normal `send_message` method...") client.send_message(client.bot_under_test, "Hello from Pyrogram") # Not waiting for response # `send_*_await` methods automatically use the `bot_under_test` as peer: res = client.send_message_await("Hello from TgIntegration", max_wait=2, raise_=False) # If `raise_` is explicitly set to False, no exception is raised: assert res.empty # Note that when no response is expected and no validation thereof is necessary, ... client.send_photo_await("_assets/photo.jpg", max_wait=0, raise_=False) client.send_voice_await("_assets/voice.ogg", max_wait=0, raise_=False) # ... it makes more sense to use the "unawaitable" methods: client.send_photo(client.bot_under_test, "_assets/photo.jpg") client.send_voice(client.bot_under_test, "_assets/voice.ogg") # Custom awaitable Actions from tgintegration import AwaitableAction, Response from pyrogram import Filters peer = '@BotListBot'
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: ReplyKeyboard self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(log_level) self.client = BotIntegrationClient(session_name=session_name, bot_under_test='@DinoParkBot', max_wait_response=20, min_wait_consecutive=2.0, global_action_delay=1.0, config_file=os.path.join( examples_dir, 'config.ini')) self.client.start() self._update_keyboard() self.update_balance() def _update_keyboard(self): start = self.client.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 = self.menu.press_button_await(r'.*Balance') values = self._extract_values(balance.full_text) self.purchase_balance = values['purchases'] self.withdrawal_balance = values['withdrawals'] self.diamonds = values['storehouse'] 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.client.delete_messages( self.client.peer_id, [bet.messages[0].message_id, bet.action_result.message_id]) return self.client.send_message_await(str(random.randint(1, 30))) self.logger.debug("Bet placed.")