diff options
| -rw-r--r-- | backend_api.py | 5 | ||||
| -rw-r--r-- | bot.py | 17 | ||||
| -rw-r--r-- | keyboards.py | 4 | ||||
| -rw-r--r-- | states.py | 114 | ||||
| -rw-r--r-- | utils.py | 1 |
5 files changed, 139 insertions, 2 deletions
diff --git a/backend_api.py b/backend_api.py index 951c570..491560f 100644 --- a/backend_api.py +++ b/backend_api.py @@ -55,6 +55,11 @@ def register_user(tg_id: int, username: str, fullname: str) -> Tuple[int, Dict]: }) +def get_profiles(): + logger.debug(f"Trying to retrieve all profiles") + return get_request(f"{BACKEND_URL}/profiles/") + + def get_tasks(): logger.debug(f"Trying to retrieve all tasks") return get_request(f"{BACKEND_URL}/tasks/") @@ -12,7 +12,7 @@ from config import TG_TOKEN, REQUEST_KWARGS import backend_api from keyboards import ( MenuKeyboard, TasksKeyboard, TaskChosenKeyboard, ContinueKeyboard, - AnsweringKeyboard, AdminKeyboard + AnsweringKeyboard, AdminKeyboard, BackToMenuKeyboard ) from utils import * from states import States, AdminStates @@ -21,6 +21,8 @@ logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(leve logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) +raiseExceptions = True + def start(bot: Bot, update: Update, user_data: dict): user_data.update({"chosen_task": None}) @@ -115,10 +117,23 @@ conversation_handler = ConversationHandler( ANSWER_RIGHT: [MessageHandler(Filters.text, States.main_menu, pass_user_data=True)], ANSWER_WRONG: [MessageHandler(Filters.text, States.show_task, pass_user_data=True)], + # ADMIN PANEL + ADMIN_MENU: [ MessageHandler(Filters.regex(AdminKeyboard.CANCEL), States.main_menu, pass_user_data=True), MessageHandler(Filters.regex(AdminKeyboard.PUBLISH_TASK), AdminStates.choose_task_publish, pass_user_data=True), MessageHandler(Filters.regex(AdminKeyboard.HIDE_TASK), AdminStates.choose_task_hide, pass_user_data=True), + MessageHandler(Filters.regex(AdminKeyboard.ANNOUNCE), AdminStates.wait_for_announcement, pass_user_data=True), + MessageHandler(Filters.regex(AdminKeyboard.MESSAGE_PLAYER), AdminStates.wait_for_message, pass_user_data=True), + ], + + ADMIN_WAIT_FOR_ANNOUNCEMENT: [ + MessageHandler(Filters.regex(BackToMenuKeyboard.CANCEL), AdminStates.admin_panel, pass_user_data=True), + MessageHandler(Filters.text, AdminStates.announce_message, pass_user_data=True), + ], + ADMIN_WAIT_FOR_MESSAGE: [ + MessageHandler(Filters.regex(BackToMenuKeyboard.CANCEL), AdminStates.admin_panel, pass_user_data=True), + MessageHandler(Filters.text, AdminStates.message_plr, pass_user_data=True), ], ADMIN_TASK_CHOOSE_HIDE: [ diff --git a/keyboards.py b/keyboards.py index d544059..1d815f4 100644 --- a/keyboards.py +++ b/keyboards.py @@ -97,6 +97,8 @@ class AdminKeyboard(Keyboard): CANCEL = "Вернуться в меню↩️" PUBLISH_TASK = "Опубликовать задачу" HIDE_TASK = "Скрыть задачу" + ANNOUNCE = "Сделать объявление" + MESSAGE_PLAYER = "Написать сообщение от имени бота" @classmethod def get_keyboard(cls, telegram_id=None): @@ -104,4 +106,6 @@ class AdminKeyboard(Keyboard): [cls.CANCEL], [cls.PUBLISH_TASK], [cls.HIDE_TASK], + [cls.ANNOUNCE], + [cls.MESSAGE_PLAYER], ] @@ -2,13 +2,21 @@ from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove from keyboards import ( MenuKeyboard, TasksKeyboard, TaskChosenKeyboard, ContinueKeyboard, - AnsweringKeyboard, AdminKeyboard, PublishTasksKeyboard + AnsweringKeyboard, AdminKeyboard, PublishTasksKeyboard, BackToMenuKeyboard ) from utils import * import backend_api +from time import sleep +import logging # Typing from telegram import Update, User, Bot +from typing import List + + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +raiseExceptions = True def save_state(func): @@ -288,3 +296,107 @@ class AdminStates: ) return ADMIN_TASK_PUBLISHED + + @staticmethod + @save_state + def wait_for_announcement(bot: Bot, update: Update, user_data: dict): + update.message.reply_text( + "Введите объявление (Отправка сообщений может занять несколько секунд)", + reply_markup=ReplyKeyboardMarkup(BackToMenuKeyboard.get_keyboard()) + ) + + return ADMIN_WAIT_FOR_ANNOUNCEMENT + + @staticmethod + @save_state + def wait_for_message(bot: Bot, update: Update, user_data: dict): + update.message.reply_text( + "Введите сообщение (Отправка сообщений может занять несколько секунд)", + reply_markup=ReplyKeyboardMarkup(BackToMenuKeyboard.get_keyboard()) + ) + + return ADMIN_WAIT_FOR_MESSAGE + + @staticmethod + @save_state + def announce_message(bot: Bot, update: Update, user_data: dict): + status, profiles = backend_api.get_profiles() + if status != 200: + pass + else: + ids = [] + for profile in profiles: + ids.append(int(profile["tg_id"])) + + return AdminStates.send_to_ids(ids, update.message.text, bot, update) + + @staticmethod + @save_state + def message_plr(bot: Bot, update: Update, user_data: dict): + text = update.message.text + _ = text.split(maxsplit=1) + + if len(_) != 2: + update.message.reply_text( + "Ошибка в сообщении, попробуйте еще раз", + reply_markup=ReplyKeyboardMarkup(ContinueKeyboard.get_keyboard()) + ) + return ADMIN_TASK_PUBLISHED + + ids_text, msg = _ + ids_split = filter(lambda s: len(s) > 0 and s.isnumeric(), ids_text.split(',')) + ids = list(map(int, ids_split)) + + if len(ids) == 0: + update.message.reply_text( + "Все id пользователей неверно введены", + reply_markup=ReplyKeyboardMarkup(ContinueKeyboard.get_keyboard()) + ) + + return ADMIN_TASK_PUBLISHED + + else: + return AdminStates.send_to_ids(ids, msg, bot, update) + + @staticmethod + def send_to_ids(ids: List[int], message: str, bot: Bot, update: Update): + errors = [] + for tg_id in ids: + try: + bot.send_message(tg_id, message) + print(tg_id) + except Exception as e: + logger.debug(f"Got exception while announcing message: {e}") + errors.append((tg_id, str(e))) + sleep(0.3) + + sleep(0.05) + + if len(errors) == 0: + update.message.reply_text( + "Сообщение успешно отправлено всем пользователям", + reply_markup=ReplyKeyboardMarkup(ContinueKeyboard.get_keyboard()), + ) + + # OKAY + return ADMIN_TASK_PUBLISHED + + else: + error_msg = [] + user_ids = [] + + for err in errors: + user_ids.append(str(err[0])) + error_msg.append(f"{err[0]}. Reason: {err[1]}") + + msg = "\n".join(error_msg) + user_ids = ",".join(user_ids) + + update.message.reply_text( + "Во время отправки сообщений возникли следующие ошибки:\n" + f"{msg}\n\n{user_ids}", + reply_markup=ReplyKeyboardMarkup(ContinueKeyboard.get_keyboard()) + ) + + # OKAY + return ADMIN_TASK_PUBLISHED @@ -5,6 +5,7 @@ ANSWER_RIGHT, ANSWER_WRONG, ADMIN_MENU, ADMIN_TASK_CHOOSE_PUBLISH, ADMIN_TASK_CHOOSE_HIDE, + ADMIN_WAIT_FOR_ANNOUNCEMENT, ADMIN_WAIT_FOR_MESSAGE, ADMIN_TASK_PUBLISHED, ADMIN_ACCESS_DENIED, *_ |