From adcea72b7243de08659dbb5b90d4586792885cb7 Mon Sep 17 00:00:00 2001 From: Aapo Laakkio Date: Wed, 2 Oct 2024 08:30:01 +0300 Subject: [PATCH] Format and remove unused imports --- vaalilakanabot2024.py | 369 +++++++++++++++++++++--------------------- 1 file changed, 187 insertions(+), 182 deletions(-) diff --git a/vaalilakanabot2024.py b/vaalilakanabot2024.py index 759e2b9..372235e 100644 --- a/vaalilakanabot2024.py +++ b/vaalilakanabot2024.py @@ -1,25 +1,30 @@ import json import os import time -import random -from glob import glob import logging import requests from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup -from telegram.ext import Updater, MessageHandler, CommandHandler, \ - Filters, ConversationHandler, CallbackContext, CallbackQueryHandler - -TOKEN = os.environ['VAALILAKANABOT_TOKEN'] -ADMIN_CHAT_ID = os.environ['ADMIN_CHAT_ID'] -BASE_URL = os.environ['BASE_URL'] - -TOPIC_LIST_URL = os.environ['TOPIC_LIST_URL'] -QUESTION_LIST_URL = os.environ['QUESTION_LIST_URL'] - -BOARD = os.environ['BOARD'].split(',') -OFFICIALS = os.environ['OFFICIALS'].split(',') +from telegram.ext import ( + Updater, + MessageHandler, + CommandHandler, + Filters, + ConversationHandler, + CallbackContext, + CallbackQueryHandler, +) + +TOKEN = os.environ["VAALILAKANABOT_TOKEN"] +ADMIN_CHAT_ID = os.environ["ADMIN_CHAT_ID"] +BASE_URL = os.environ["BASE_URL"] + +TOPIC_LIST_URL = os.environ["TOPIC_LIST_URL"] +QUESTION_LIST_URL = os.environ["QUESTION_LIST_URL"] + +BOARD = os.environ["BOARD"].split(",") +OFFICIALS = os.environ["OFFICIALS"].split(",") SELECTING_POSITION_CLASS, SELECTING_POSITION, TYPING_NAME, CONFIRMING = range(4) @@ -29,58 +34,58 @@ fiirumi_posts = [] question_posts = [] -logger = logging.getLogger('vaalilakanabot') +logger = logging.getLogger("vaalilakanabot") logger.setLevel(logging.INFO) -log_path = os.path.join('logs', 'vaalilakanabot.log') +log_path = os.path.join("logs", "vaalilakanabot.log") fh = logging.FileHandler(log_path) fh.setLevel(logging.INFO) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") fh.setFormatter(formatter) logger.addHandler(fh) -with open('data/vaalilakana.json', 'r') as f: +with open("data/vaalilakana.json", "r") as f: data = f.read() vaalilakana = json.loads(data) -logger.info('Loaded vaalilakana: %s', vaalilakana) +logger.info("Loaded vaalilakana: %s", vaalilakana) -with open('data/channels.json', 'r') as f: +with open("data/channels.json", "r") as f: data = f.read() channels = json.loads(data) -logger.info('Loaded channels: %s', channels) +logger.info("Loaded channels: %s", channels) -with open('data/fiirumi_posts.json', 'r') as f: +with open("data/fiirumi_posts.json", "r") as f: data = f.read() fiirumi_posts = json.loads(data) -logger.info('Loaded fiirumi posts: %s', fiirumi_posts) +logger.info("Loaded fiirumi posts: %s", fiirumi_posts) -with open('data/question_posts.json', 'r') as f: +with open("data/question_posts.json", "r") as f: data = f.read() question_posts = json.loads(data) -logger.info('Loaded question posts: %s', fiirumi_posts) +logger.info("Loaded question posts: %s", fiirumi_posts) updater = Updater(TOKEN, use_context=True) def _save_data(filename, content): - with open(filename, 'w') as fp: + with open(filename, "w") as fp: fp.write(json.dumps(content)) def _vaalilakana_to_string(lakana): - output = '' - output += '---------------Raati---------------\n' + output = "" + output += "---------------Raati---------------\n" # Hardcoded to maintain order instead using dict keys for position in BOARD: - output += f'{position}:\n' + output += f"{position}:\n" for applicant in lakana[position]: - link = applicant['fiirumi'] - selected = applicant['valittu'] + link = applicant["fiirumi"] + selected = applicant["valittu"] if selected: if link: output += f'- {applicant["name"]} (valittu)\n' @@ -92,13 +97,13 @@ def _vaalilakana_to_string(lakana): else: output += f'- {applicant["name"]}\n' - output += '\n' - output += '----------Toimihenkilöt----------\n' + output += "\n" + output += "----------Toimihenkilöt----------\n" for position in OFFICIALS: - output += f'{position}:\n' + output += f"{position}:\n" for applicant in lakana[position]: - link = applicant['fiirumi'] - selected = applicant['valittu'] + link = applicant["fiirumi"] + selected = applicant["valittu"] if selected: if link: output += f'- {applicant["name"]} (valittu)\n' @@ -110,7 +115,7 @@ def _vaalilakana_to_string(lakana): else: output += f'- {applicant["name"]}\n' - output += '\n' + output += "\n" return output @@ -122,54 +127,56 @@ def parse_fiirumi_posts(context=updater.bot): topic_list_raw = page_fiirumi.json() logger.debug(str(topic_list_raw)) question_list_raw = page_question.json() - topic_list = topic_list_raw['topic_list']['topics'] - question_list = question_list_raw['topic_list']['topics'] + topic_list = topic_list_raw["topic_list"]["topics"] + question_list = question_list_raw["topic_list"]["topics"] logger.debug(topic_list) except KeyError as e: - logger.error("The topic and question lists cannot be found. Check URLs. Got error %s", e) + logger.error( + "The topic and question lists cannot be found. Check URLs. Got error %s", e + ) return except Exception as e: logger.error(e) return for topic in topic_list: - t_id = topic['id'] - title = topic['title'] - slug = topic['slug'] + t_id = topic["id"] + title = topic["title"] + slug = topic["slug"] if str(t_id) not in fiirumi_posts: new_post = { - 'id': t_id, - 'title': title, - 'slug': slug, + "id": t_id, + "title": title, + "slug": slug, } fiirumi_posts[str(t_id)] = new_post - _save_data('data/fiirumi_posts.json', fiirumi_posts) + _save_data("data/fiirumi_posts.json", fiirumi_posts) _announce_to_channels( - f'Uusi postaus Vaalipeli-palstalla!\n{title}\n{BASE_URL}/t/{slug}/{t_id}' + f"Uusi postaus Vaalipeli-palstalla!\n{title}\n{BASE_URL}/t/{slug}/{t_id}" ) for question in question_list: - t_id = question['id'] - title = question['title'] - slug = question['slug'] + t_id = question["id"] + title = question["title"] + slug = question["slug"] if str(t_id) not in question_posts: new_question = { - 'id': t_id, - 'title': title, - 'slug': slug, + "id": t_id, + "title": title, + "slug": slug, } question_posts[str(t_id)] = new_question - _save_data('data/question_posts.json', question_posts) + _save_data("data/question_posts.json", question_posts) _announce_to_channels( - f'Uusi kysymys Fiirumilla!\n{title}\n{BASE_URL}/t/{slug}/{t_id}' + f"Uusi kysymys Fiirumilla!\n{title}\n{BASE_URL}/t/{slug}/{t_id}" ) def _announce_to_channels(message): for cid in channels: try: - updater.bot.send_message(cid, message, parse_mode='HTML') + updater.bot.send_message(cid, message, parse_mode="HTML") time.sleep(0.5) except Exception as e: logger.error(e) @@ -180,52 +187,45 @@ def remove_applicant(update, context): try: chat_id = update.message.chat.id if str(chat_id) == str(ADMIN_CHAT_ID): - text = update.message.text.replace('/poista', '').strip() - params = text.split(',') + text = update.message.text.replace("/poista", "").strip() + params = text.split(",") try: position = params[0].strip() name = params[1].strip() except Exception as e: updater.bot.send_message( - chat_id, - 'Virheelliset parametrit - /poista , ' + chat_id, "Virheelliset parametrit - /poista , " ) - raise Exception('Invalid parameters') from e + raise Exception("Invalid parameters") from e if position not in vaalilakana: updater.bot.send_message( - chat_id, - f'Tunnistamaton virka: {position}', - parse_mode='HTML' + chat_id, f"Tunnistamaton virka: {position}", parse_mode="HTML" ) - raise Exception(f'Unknown position {position}') + raise Exception(f"Unknown position {position}") found = None for applicant in vaalilakana[position]: - if name == applicant['name']: + if name == applicant["name"]: found = applicant break if not found: updater.bot.send_message( - chat_id, - f'Hakijaa ei löydy {name}', - parse_mode='HTML' + chat_id, f"Hakijaa ei löydy {name}", parse_mode="HTML" ) - raise Exception(f'Applicant not found: {name}') + raise Exception(f"Applicant not found: {name}") vaalilakana[position].remove(found) - _save_data('data/vaalilakana.json', vaalilakana) + _save_data("data/vaalilakana.json", vaalilakana) global last_applicant last_applicant = None updater.bot.send_message( chat_id, - 'Poistettu:\n{position}: {name}'.format( - **found - ), - parse_mode='HTML' + "Poistettu:\n{position}: {name}".format(**found), + parse_mode="HTML", ) except Exception as e: logger.error(e) @@ -235,8 +235,8 @@ def add_fiirumi_to_applicant(update, context): try: chat_id = update.message.chat.id if str(chat_id) == str(ADMIN_CHAT_ID): - text = update.message.text.replace('/lisaa_fiirumi', '').strip() - params = text.split(',') + text = update.message.text.replace("/lisaa_fiirumi", "").strip() + params = text.split(",") try: position = params[0].strip() @@ -245,53 +245,48 @@ def add_fiirumi_to_applicant(update, context): except Exception as e: updater.bot.send_message( chat_id, - 'Virheelliset parametrit - /lisaa_fiirumi , , ' + "Virheelliset parametrit - /lisaa_fiirumi , , ", ) - raise Exception('Invalid parameters') from e + raise Exception("Invalid parameters") from e if position not in vaalilakana: updater.bot.send_message( - chat_id, - f'Tunnistamaton virka: {position}', - parse_mode='HTML' + chat_id, f"Tunnistamaton virka: {position}", parse_mode="HTML" ) - raise Exception(f'Unknown position {position}') + raise Exception(f"Unknown position {position}") if thread_id not in fiirumi_posts: updater.bot.send_message( chat_id, - f'Fiirumi-postausta ei löytynyt annetulla id:llä: {thread_id}', - parse_mode='HTML' + f"Fiirumi-postausta ei löytynyt annetulla id:llä: {thread_id}", + parse_mode="HTML", ) - raise Exception(f'Unknown thread {thread_id}') + raise Exception(f"Unknown thread {thread_id}") found = None for applicant in vaalilakana[position]: - if name == applicant['name']: + if name == applicant["name"]: found = applicant fiirumi = f'{BASE_URL}/t/{fiirumi_posts[thread_id]["slug"]}/{fiirumi_posts[thread_id]["id"]}' - applicant['fiirumi'] = fiirumi + applicant["fiirumi"] = fiirumi break if not found: updater.bot.send_message( - chat_id, - f'Hakijaa ei löydy {name}', - parse_mode='HTML' + chat_id, f"Hakijaa ei löydy {name}", parse_mode="HTML" ) - raise Exception(f'Applicant not found: {name}') + raise Exception(f"Applicant not found: {name}") - _save_data('data/vaalilakana.json', vaalilakana) + _save_data("data/vaalilakana.json", vaalilakana) global last_applicant last_applicant = None updater.bot.send_message( chat_id, 'Lisätty Fiirumi:\n{position}: {name}'.format( - fiirumi, - **found + fiirumi, **found ), - parse_mode='HTML' + parse_mode="HTML", ) except Exception as e: logger.error(e) @@ -299,28 +294,30 @@ def add_fiirumi_to_applicant(update, context): def add_applicant(update: Update, context: CallbackContext) -> None: """Add an applicant. This command is for admin use.""" - keyboard = [[ - InlineKeyboardButton("Raatiin", callback_data='board'), - InlineKeyboardButton("Toimihenkilöksi", callback_data='official'), - ]] + keyboard = [ + [ + InlineKeyboardButton("Raatiin", callback_data="board"), + InlineKeyboardButton("Toimihenkilöksi", callback_data="official"), + ] + ] reply_markup = InlineKeyboardMarkup(keyboard) chat_id = update.message.chat.id if str(chat_id) == str(ADMIN_CHAT_ID): - update.message.reply_text('Mihin rooliin henkilö lisätään?', reply_markup=reply_markup) + update.message.reply_text( + "Mihin rooliin henkilö lisätään?", reply_markup=reply_markup + ) return SELECTING_POSITION_CLASS else: - update.message.reply_text('Et oo admin :(((') + update.message.reply_text("Et oo admin :(((") return None def generate_positions(position_class): keyboard = [] for position in position_class: - keyboard.append( - [InlineKeyboardButton(position, callback_data=position)] - ) + keyboard.append([InlineKeyboardButton(position, callback_data=position)]) return keyboard @@ -333,13 +330,13 @@ def select_position_class(update: Update, context: CallbackContext) -> int: # CallbackQueries need to be answered, even if no notification to the user is needed # Some clients may have trouble otherwise. See https://core.telegram.org/bots/api#callbackquery - if query.data == '1': - logger.debug('Raati') + if query.data == "1": + logger.debug("Raati") keyboard = InlineKeyboardMarkup(generate_positions(BOARD)) query.edit_message_reply_markup(keyboard) return SELECTING_POSITION - elif query.data == '2': - logger.debug('Toimihenkilö') + elif query.data == "2": + logger.debug("Toimihenkilö") keyboard = InlineKeyboardMarkup(generate_positions(OFFICIALS)) query.edit_message_reply_markup(keyboard) return SELECTING_POSITION @@ -371,8 +368,10 @@ def register_position(update: Update, context: CallbackContext) -> int: # CallbackQueries need to be answered, even if no notification to the user is needed # Some clients may have trouble otherwise. See https://core.telegram.org/bots/api#callbackquery query.answer() - query.edit_message_text(text=f"Hakija rooliin: {query.data}\nKirjoita hakijan nimi vastauksena tähän viestiin") - chat_data['new_applicant_position'] = query.data + query.edit_message_text( + text=f"Hakija rooliin: {query.data}\nKirjoita hakijan nimi vastauksena tähän viestiin" + ) + chat_data["new_applicant_position"] = query.data return TYPING_NAME @@ -384,28 +383,34 @@ def enter_applicant_name(update: Update, context: CallbackContext) -> int: logger.debug(name) try: chat_id = update.message.chat.id - position = chat_data['new_applicant_position'] - chat_data['new_applicant_name'] = name + position = chat_data["new_applicant_position"] + chat_data["new_applicant_name"] = name - new_applicant = {'name': name, 'position': position, 'fiirumi': '', 'valittu': False} + new_applicant = { + "name": name, + "position": position, + "fiirumi": "", + "valittu": False, + } vaalilakana[position].append(new_applicant) - _save_data('data/vaalilakana.json', vaalilakana) + _save_data("data/vaalilakana.json", vaalilakana) global last_applicant last_applicant = new_applicant updater.bot.send_message( chat_id, - 'Lisätty:\n{position}: {name}.\n\nLähetä tiedote komennolla /tiedota'.format( + "Lisätty:\n{position}: {name}.\n\nLähetä tiedote komennolla /tiedota".format( **new_applicant ), - parse_mode='HTML' + parse_mode="HTML", ) except Exception as e: # TODO: Return to role selection logger.error(e) return ConversationHandler.END + def unassociate_fiirumi(update, context): try: chat_id = update.message.chat.id @@ -414,35 +419,41 @@ def unassociate_fiirumi(update, context): # to ["Puheenjohtaja", "Fysisti kiltalainen"] params = [ arg.strip() - for arg in update.message.text.replace('/poista_fiirumi','').strip().split(',') + for arg in update.message.text.replace("/poista_fiirumi", "") + .strip() + .split(",") ] # Try find role try: role, applicant = params except Exception as e: - updater.bot.send_message(chat_id, 'Virheelliset parametrit - /poista_fiirumi , ') + updater.bot.send_message( + chat_id, "Virheelliset parametrit - /poista_fiirumi , " + ) return if role not in vaalilakana: - updater.bot.send_message(chat_id, 'Virheelliset parametrit, roolia ei löytynyt') + updater.bot.send_message( + chat_id, "Virheelliset parametrit, roolia ei löytynyt" + ) return # Try finding the dict with matching applicant name from vaalilakana for app_info in vaalilakana[role]: - if app_info['name'] == applicant: - app_info['fiirumi'] = "" + if app_info["name"] == applicant: + app_info["fiirumi"] = "" break else: # If the loop didn't break - updater.bot.send_message(chat_id, 'Virheelliset parametrit, hakijaa ei löytynyt roolille') + updater.bot.send_message( + chat_id, "Virheelliset parametrit, hakijaa ei löytynyt roolille" + ) return - _save_data('data/vaalilakana.json', vaalilakana) + _save_data("data/vaalilakana.json", vaalilakana) updater.bot.send_message( chat_id, - 'Fiirumi linkki poistettu:\n{name}'.format( - name=applicant - ), - parse_mode='HTML' + "Fiirumi linkki poistettu:\n{name}".format(name=applicant), + parse_mode="HTML", ) else: # Not admin chat @@ -450,58 +461,51 @@ def unassociate_fiirumi(update, context): except Exception as e: # Unknown error :/ logger.error(e) - + def add_selected_tag(update, context): try: chat_id = update.message.chat.id if str(chat_id) == str(ADMIN_CHAT_ID): - text = update.message.text.replace('/valittu', '').strip() - params = text.split(',') + text = update.message.text.replace("/valittu", "").strip() + params = text.split(",") try: position = params[0].strip() name = params[1].strip() except Exception as e: updater.bot.send_message( - chat_id, - 'Virheelliset parametrit - /valittu , ' + chat_id, "Virheelliset parametrit - /valittu , " ) raise Exception from e if position not in vaalilakana: updater.bot.send_message( - chat_id, - f'Tunnistamaton virka: {position}', - parse_mode='HTML' + chat_id, f"Tunnistamaton virka: {position}", parse_mode="HTML" ) - raise Exception(f'Unknown position {position}') + raise Exception(f"Unknown position {position}") found = None for applicant in vaalilakana[position]: - if name == applicant['name']: + if name == applicant["name"]: found = applicant - applicant['valittu'] = True + applicant["valittu"] = True break if not found: updater.bot.send_message( - chat_id, - f'Hakijaa ei löydy {name}', - parse_mode='HTML' + chat_id, f"Hakijaa ei löydy {name}", parse_mode="HTML" ) - raise Exception(f'Applicant not found: {name}') + raise Exception(f"Applicant not found: {name}") - _save_data('data/vaalilakana.json', vaalilakana) + _save_data("data/vaalilakana.json", vaalilakana) global last_applicant last_applicant = None updater.bot.send_message( chat_id, - 'Hakija valittu:\n{position}: {name}'.format( - **found - ), - parse_mode='HTML' + "Hakija valittu:\n{position}: {name}".format(**found), + parse_mode="HTML", ) except Exception as e: logger.error(e) @@ -513,7 +517,8 @@ def show_vaalilakana(update, context): updater.bot.send_message( chat_id, _vaalilakana_to_string(vaalilakana), - parse_mode='HTML', disable_web_page_preview=True + parse_mode="HTML", + disable_web_page_preview=True, ) except Exception as e: logger.error(e) @@ -524,11 +529,10 @@ def register_channel(update, context): chat_id = update.message.chat.id if chat_id not in channels: channels.append(chat_id) - _save_data('data/channels.json', channels) - print(f'New channel added {chat_id}', update.message) + _save_data("data/channels.json", channels) + print(f"New channel added {chat_id}", update.message) updater.bot.send_message( - chat_id, - 'Rekisteröity Vaalilakanabotin tiedotuskanavaksi!' + chat_id, "Rekisteröity Vaalilakanabotin tiedotuskanavaksi!" ) except Exception as e: logger.error(e) @@ -541,7 +545,7 @@ def announce_new_applicant(update, context): global last_applicant if last_applicant: _announce_to_channels( - 'Uusi nimi vaalilakanassa!\n{position}: {name}'.format( + "Uusi nimi vaalilakanassa!\n{position}: {name}".format( **last_applicant ) ) @@ -553,7 +557,7 @@ def announce_new_applicant(update, context): def jauhis(update, context): try: chat_id = update.message.chat.id - with open('assets/jauhis.png', 'rb') as photo: + with open("assets/jauhis.png", "rb") as photo: updater.bot.send_sticker(chat_id, photo) except Exception as e: logger.warning("Error in sending Jauhis %s", e) @@ -562,16 +566,16 @@ def jauhis(update, context): def jauh(update, context): try: chat_id = update.message.chat.id - with open('assets/jauh.png', 'rb') as photo: + with open("assets/jauh.png", "rb") as photo: updater.bot.send_sticker(chat_id, photo) except Exception as e: logger.warning("Error in sending Jauh %s", e) - - + + def lauh(update, context): try: chat_id = update.message.chat.id - with open('assets/lauh.png', 'rb') as photo: + with open("assets/lauh.png", "rb") as photo: updater.bot.send_sticker(chat_id, photo) except Exception as e: logger.warning("Error in sending Lauh %s", e) @@ -580,10 +584,10 @@ def lauh(update, context): def mauh(update, context): try: chat_id = update.message.chat.id - with open('assets/mauh.png', 'rb') as photo: + with open("assets/mauh.png", "rb") as photo: updater.bot.send_sticker(chat_id, photo) except Exception as e: - logger.warning("Error in sending Mauh %s", e) + logger.warning("Error in sending Mauh %s", e) def error(update, context): @@ -596,39 +600,40 @@ def cancel(update, context): chat_data.clear() - - def main(): jq = updater.job_queue jq.run_repeating(parse_fiirumi_posts, interval=60, first=0, context=updater.bot) dp = updater.dispatcher - dp.add_handler(CommandHandler('valittu', add_selected_tag)) - dp.add_handler(CommandHandler('lisaa_fiirumi', add_fiirumi_to_applicant)) - dp.add_handler(CommandHandler('poista_fiirumi', unassociate_fiirumi)) - dp.add_handler(CommandHandler('poista', remove_applicant)) - dp.add_handler(CommandHandler('lakana', show_vaalilakana)) - dp.add_handler(CommandHandler('tiedota', announce_new_applicant)) - dp.add_handler(CommandHandler('start', register_channel)) - dp.add_handler(CommandHandler('jauhis', jauhis)) - dp.add_handler(CommandHandler('jauh', jauh)) - dp.add_handler(CommandHandler('lauh', lauh)) - dp.add_handler(CommandHandler('mauh', mauh)) + dp.add_handler(CommandHandler("valittu", add_selected_tag)) + dp.add_handler(CommandHandler("lisaa_fiirumi", add_fiirumi_to_applicant)) + dp.add_handler(CommandHandler("poista_fiirumi", unassociate_fiirumi)) + dp.add_handler(CommandHandler("poista", remove_applicant)) + dp.add_handler(CommandHandler("lakana", show_vaalilakana)) + dp.add_handler(CommandHandler("tiedota", announce_new_applicant)) + dp.add_handler(CommandHandler("start", register_channel)) + dp.add_handler(CommandHandler("jauhis", jauhis)) + dp.add_handler(CommandHandler("jauh", jauh)) + dp.add_handler(CommandHandler("lauh", lauh)) + dp.add_handler(CommandHandler("mauh", mauh)) conv_handler = ConversationHandler( - entry_points=[CommandHandler('lisaa', add_applicant)], + entry_points=[CommandHandler("lisaa", add_applicant)], states={ SELECTING_POSITION_CLASS: [ - CallbackQueryHandler(select_board_position, pattern='^board$'), - CallbackQueryHandler(select_official_position, pattern='^official$') + CallbackQueryHandler(select_board_position, pattern="^board$"), + CallbackQueryHandler(select_official_position, pattern="^official$"), ], - SELECTING_POSITION: [ - CallbackQueryHandler(register_position) + SELECTING_POSITION: [CallbackQueryHandler(register_position)], + TYPING_NAME: [ + MessageHandler(Filters.text & (~Filters.command), enter_applicant_name) ], - TYPING_NAME: [MessageHandler(Filters.text & (~Filters.command), enter_applicant_name)], }, - fallbacks=[CommandHandler('cancel', cancel), CommandHandler('lisaa', add_applicant)], + fallbacks=[ + CommandHandler("cancel", cancel), + CommandHandler("lisaa", add_applicant), + ], ) dp.add_handler(conv_handler)