async def change_news_page(self, ans: Message): u = await UserState.get(uid=ans.from_id) if isinstance(u.context, str): u.context = ujson.loads(u.context) if 'page_num' not in u.context: u.context['page_num'] = 1 payload = ujson.loads(ans.payload) page_num = u.context['page_num'] if payload.get('page') == 'next': page_num += 1 elif page_num <= 1: page_num = 1 else: page_num -= 1 news = await NewsList() news.make_text_and_keyboard(page_num=page_num) msg = news.get_text() kbrd = news.get_keyboard() await ans('Загружаем новости....', keyboard=keyboard_gen(EMPTY_KEYBOARD)) await ans(message=msg, keyboard=keyboard_gen(kbrd)) u.context['page_num'] = page_num await u.save()
def __generate_choice_keyboard( self, array: List[str], color: str = "secondary" ) -> Union[Keyboard, bool]: """ Функция генерирует клавиатуру из массива выборов array. Если элементов 5 или меньше - отводит каждому по 1 строке. Если больше, отводит макс. 2 элемента на строку. Длинна массива не больше 10. :param array: массив с выбором :param color: цвет кнопок :return: Keyboard или False если len(array) > 10 """ if len(array) <= 5: # [1, 2, 3, 4, 5] => [[1], [2], [3], [4], [5]] return keyboard_gen([ [{"text": text, "payload": str(i+1), "color": color}] for i, text in enumerate(array)] ) elif len(array) <= 10: # [1, 2, 3, 4, 5, 6, 7] => [[1, 2], [3, 4], [5, 6], [7]] if len(array) % 2 != 0: # нечетное # Добавляем, чтобы массив делился на 2 array.append(None) return keyboard_gen( [ [ {"text": text, "payload": str(i+1), "color": color}, {"text": array[2*i+1], "payload": str(2*i+2), "color": color} ] # Если следующий элемент не добавлен искусственно выше, # добавляем его в список. if array[2*i+1] is not None else [ {"text": text, "payload": str(i+1), "color": color} ] for i, text in enumerate(array[::2]) ] ) else: return False
async def wrapper(ans: Message): await bp.branch.add(ans.from_id, 'mentors') await ans( 'Вы можете узнать о наставнике отправив мне его/её фамилию.\n' 'Если я смогу найти наставника с такой фамилией, я покажу вам информацию о нем' 'и его контактные данные.', keyboard=keyboard_gen([[EXIT_BUTTON]], one_time=True))
async def news_handler(ans: Message): await ans( 'Нажмите "Далее", чтобы увидеть последние новости Проектного офиса', keyboard=keyboard_gen([[{ 'text': 'Далее', 'color': 'positive' }]])) await bp.branch.add(ans.from_id, 'news')
async def start_command_wrapper(self, ans: Message): await ans( 'Здравствуйте! В этом чат-боте вы сможете найти ' 'информацию о наставниках, проектах, различных мероприятих ' 'и многом другом.\n' 'Если у вас возникнут какие-либо вопросы, нажмите кнопку "Помощь"', keyboard=keyboard_gen(MAIN_MENU_KEYBOARD)) await bp.branch.add(uid=ans.from_id, branch='main')
async def help_message(self, ans: Message): await ans(message=''' Управление чат-ботом осуществляется с помощью кнопок клавиатуры. В случае если клавиатура по какой-то причине не отображается, отправьте сообщение "выйти", чтобы вернуться в главное меню. Каждая кнопка в главном меню ведет в ветвь с соответствующим названию функционалом, управление в каждой ветви осуществляется также с помощью кнопок. Ветвь "Наставники" позволяет узнать информацию о наставниках Проектного офиса, ветвь "Расписание" позволяет узнать расписание аудиторий, учебных групп и преподователей, ветвь "Новости" отображает последние новости Проектного офиса, а в ветви "ЧаВо" можно найти ответы на самые часто задаваемые вопросы о проектной деятельности. ''', keyboard=keyboard_gen(MAIN_MENU_KEYBOARD))
async def branch(self, ans: Message): surname = ans.text.split()[0] try: data = await fetch_json(Config.BASE_API_URL + Config.URL_PATH['mentors']) card = MentorMessageCard(data, surname) except aiohttp.ClientResponseError as e: print('[ERROR] HTTP Client Response Error occured: {}, {}'.format( e.status, e.message)) await ans( 'Произошла ошибка при обработке запроса к API Проектного офиса, возможно, он временно недоступен.\n' 'Если эта ошибка возникает продолжительно в течение более чем нескольких часов, обратитесь к администрации сайта.', keyboard=keyboard_gen(EMPTY_KEYBOARD)) except MentorNotFoundException: await ans( 'Извините, я не могу найти наставника с такой фамилией.\n' 'Вы можете спросить меня еще раз, отправив фамилию наставника.\n\n' 'Чтобы закончить, нажмите кнопку "Выйти".', keyboard=keyboard_gen([[EXIT_BUTTON]], one_time=False)) return card_text, avatar_link, doc_link = card.as_tuple() photo_data = await photo_uploader.get_data_from_link(link=avatar_link) pic = await photo_uploader.upload_message_photo(photo_data) temp_kbrd = [[EXIT_BUTTON]] temp_kbrd.append([{ 'type': 'open_link', 'label': 'Больше информации о наставнике', 'link': doc_link }]) await ans(message=card_text, attachment=pic) await ans( 'Введите фамилию наставника, о котором хотели бы узнать или нажмите "Выйти", чтобы вернуться в главное меню', keyboard=keyboard_gen(temp_kbrd, one_time=True))
def __show_settings( self, message: Message, player: Dict[str, Any] ) -> Dict[str, Union[str, Keyboard, None]]: return { "text": "Настройки.", "keyboard": keyboard_gen( [[{ "text": "Меню", "color": "positive", "payload": '"menu"' }]] ) }
async def send_news(self, ans: Message): news_list = await NewsList() news_list.make_text_and_keyboard() msg = news_list.get_text() kbrd = news_list.get_keyboard() u = await UserState.get(uid=ans.from_id) if isinstance(u.context, str): u.context = ujson.loads(u.context) u.context['page_num'] = 1 await u.save() await ans(message=msg, keyboard=keyboard_gen(kbrd, one_time=True))
def __show_menu( self, message: Message, player: Dict[str, Any] ) -> Dict[str, Union[str, Keyboard, None]]: """ Возвращает интерфейс меню. :param message: Message :param player: element self.players :return: output message """ return { "text": "Меню.\n" + "Используйте клавиатуру " + "или текстовые команды:\n" + "!game - Играть.\n" + "!editor - Редактор новелл.\n" + "!settings - Настройки.", "keyboard": keyboard_gen([ [{ "text": "🎮 Играть!", "color": "positive", "payload": '"game"' }], [ { "text": "✏ Редактор", "color": "negative", "payload": '"editor"' }, { "text": "⚙ Настройки", "color": "secondary", "payload": '"settings"' } ] ]) }
async def exit_branch(self, ans: Message): await ans( 'Дополнительную информацию о наставниках вы всегда можете найти на сайте Проектного офиса.\n' '(https://proictis.sfedu.ru)', keyboard=keyboard_gen(EMPTY_KEYBOARD)) await return_to_main_menu(ans)
async def test(self, ans: Message): await ans(message='Выберите одну из опций:', keyboard=keyboard_gen(MAIN_MENU_KEYBOARD))
async def empty_keyboard(self, ans: Message): await ans('test', keyboard=keyboard_gen([]))
async def branch(self, ans: Message, *args): await ans(message='Главное меню', keyboard=keyboard_gen(MAIN_MENU_KEYBOARD, one_time=False))
async def faq_wrapper(self, ans: Message): await ans( 'Задавайте свои вопросы словно спрашиваете человека' 'и я попытаюсь найти на них ответ!', keyboard=keyboard_gen([[EXIT_BUTTON]])) await bp.branch.add(ans.from_id, 'faq')
def __game_step( self, message: Message, player: Dict[str, Any] ) -> Dict[str, Union[str, Keyboard, None]]: """ Шаг вперед в новелле для игрока player. :param message: Message :param player: element self.players :return: output message """ player = self.__get_player_info(message.from_id) # Не выбрана новелла if player['game_novel_id'] is None: # Перейти в каталог. player['game_novel_id'] = 0 novel_dict = self.novels[player['game_novel_id']] # Не создан объект новеллы if player['game_obj'] is None: player['game_obj'] = Novel( novel_dict['storyline'], player['game_slide_id'], novel_dict['is_input_username'] ) novel = player['game_obj'] # Добавляем все переменные в объект if isinstance(player['game_vars'], dict): for key, value in player['game_vars'].items(): if key == 'choice': player['game_obj'].player_choices = value elif key == 'username': player['game_obj'].username = value else: player['game_obj'].vars[key] = value novel = player['game_obj'] if novel.slide_id == 0 and novel.is_input_username: if player['game_is_input_username']: novel.username = message.text else: player['game_is_input_username'] = True return { "text": "Введи свое имя:", "keyboard": keyboard_gen([]) } if player['game_is_choice']: if message.payload is not None: choice = int(message.payload) - 1 else: # Проверять, является ли введенное # сообщение выбором. try: choice = int(message.text) except ValueError: return { "text": "Введите число или используйте клавиатуру!" } else: len_choice = len(novel.storyline[novel.slide_id]['choice']) if not len_choice >= choice > 0: return { "text": f"Введите число от 1 до {len_choice}" + "или используйте клавиатуру!" } choice -= 1 step = novel.step(choice) player['game_is_choice'] = False else: if message.payload == 'restart' or message.text == "!restart": novel.slide_id = 0 step = novel.step() if step: attachment = step.get('attachment') # Если есть выбор if 'choice' in step: answer = step['text']+'\n' for i, option in enumerate(step['choice']): answer += f"\n{i+1}. {option}" player['game_is_choice'] = True return { "text": answer, "keyboard": self.__generate_choice_keyboard(step['choice']), "attachment": attachment, "typing_delay": novel_dict['typing_delay'] } else: # Возвращаем текст и аттачи return { "text": step['text'], "keyboard": keyboard_gen( [[ {'text': "Дальше ➡", "color": "primary"} ]] ), "attachment": attachment, "typing_delay": novel_dict['typing_delay'] } else: return { "text": "Новелла закончена.\n" + "Используйте клавиатуру " + "или текстовые команды: \n" + "!restart - Перезапустить новеллу.\n" + "!menu - Выход в меню.", "keyboard": keyboard_gen( [ [{ "text": "Начать заново", "payload": '"restart"', "color": "positive" }], [{ "text": "В меню", "payload": '"menu"', "color": "negative" }] ] ) }
async def news_enter(self, ans: Message): await bp.branch.add(ans.from_id, 'news') await ans( 'Нажмите "Далее", чтобы увидеть последние новости с сайта Проектного офиса или ' '"Поиск" для интерактивного поиска по новостям Проектного офиса и группы ИКТИБ ВКонтакте', keyboard=keyboard_gen(NEWS_WELCOME_KEYBOARD, one_time=True))