def event_alteration_start(update, context): """Starts the event alteration process.""" query = update.callback_query query.answer() altering_type = query.data.split("_")[-1:][0] user_id = query.from_user['id'] events = DatabaseController.load_user_events(user_id) user_language = DatabaseController.load_selected_language(user_id) message = None if altering_type == 'change': message = receive_translation("event_alteration_change_header", user_language) elif altering_type == 'delete': message = receive_translation("event_alteration_delete_header", user_language) if UserEventAlterationMachine.receive_state_of_user( user_id ) == 0 or UserEventAlterationMachine.receive_state_of_user( user_id) == -1: bot = BotControl.get_bot() bot.send_message( user_id, text=message, parse_mode=ParseMode.MARKDOWN_V2, reply_markup=Event.event_keyboard_alteration_action( events, user_language, mode=altering_type))
def list_all_events_of_user(update, context): """Lists all events of the user.""" user = User.resolve_user(update) message = "*{}:*\n\n".format( receive_translation("event_list_header", user.language)) event_data = DatabaseController.load_user_events(user.user_id) has_content = False for day in DayEnum: events = [event for event in event_data if event.day == day] if not events: continue has_content = True message += "*{}:*\n".format( day.receive_day_translation(user.language)) for event in events: message += event.pretty_print_formatting(user.language) message += "\n" if not has_content: message += "{}".format( receive_translation("no_events", user.language)) bot = BotControl.get_bot() bot.send_message(user.user_id, text=message, parse_mode=ParseMode.MARKDOWN_V2, reply_markup=Event.event_keyboard_alteration( user.language))
def _check_event_ping(self, user_id, events, today=True): """Check which events are not already passed and pings the user. Args: user_id (int): ID of the user. events (list of 'Event'): Contains all events of the user for a single day. today (bool, optional): Indicates whether the events of today or tomorrow are checked. Checking today by default. """ bot = BotControl.get_bot() ping_list = [] logger.info("Checking %s | %s", user_id, events) for event in events: ping_needed, event_delete = self.check_ping_needed(user_id, event, today) if ping_needed: event.deleted = event_delete ping_list.append(event) # Only ping if there are events to notify about if ping_list: for event in ping_list: message = self.build_ping_message(user_id, event) if event.deleted: bot.send_message(user_id, text=message, parse_mode=ParseMode.MARKDOWN_V2) else: language = DatabaseController.load_selected_language(user_id) postfix = "_{}".format(event.uuid) bot.send_message(user_id, text=message, parse_mode=ParseMode.MARKDOWN_V2, reply_markup=Event.event_keyboard_alteration(language, "event", postfix))
def main(): """Start the bot.""" # Get the dispatcher to register handlers updater = BotControl.setup_bot() dp = updater.dispatcher # on different commands - answer in Telegram dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("help", help_command)) dp.add_handler(CommandHandler("config", Configurator.start_configuration_dialog)) dp.add_handler(CommandHandler("new_event", EventHandler.add_new_event)) dp.add_handler(CommandHandler("list_events", EventHandler.list_all_events_of_user)) dp.add_handler(CallbackQueryHandler(Configurator.handle_configuration_dialog, pattern="config_start_[_a-zA-Z]*")) dp.add_handler(CallbackQueryHandler(Configurator.handle_configuration_change, pattern="config_select_[_a-zA-Z]*")) dp.add_handler(CallbackQueryHandler(EventHandler.event_alteration_start, pattern="event_alteration_[a-zA-Z]*")) dp.add_handler(CallbackQueryHandler(EventHandler.event_alteration_perform, pattern="event_(delete|change|silence)_[0-9a-zA-Z]+")) dp.add_handler(CallbackQueryHandler(EventHandler.add_new_event_query_handler)) # on noncommand i.e message - echo the message on Telegram dp.add_handler(MessageHandler(Filters.text & ~Filters.command, parse_input)) # Start the Bot updater.start_polling() event_checker = EventChecker() event_checker.check_events() # Run the bot until you press Ctrl-C or the process receives SIGINT, # SIGTERM or SIGABRT. This should be used most of the time, since # start_polling() is non-blocking and will stop the bot gracefully. updater.idle()
def handle_configuration_dialog(update, context): """Handles the configuration dialog.""" query = update.callback_query query.answer() user_id = query.from_user['id'] user_language = DatabaseController.load_selected_language(user_id) bot = BotControl.get_bot() if query.data == CONFIG_LANGUAGE: query.edit_message_text( text=receive_translation("config_language_which", user_language), reply_markup=Configurator.config_language_keyboard()) elif query.data == CONFIG_DAILY_PING: query.edit_message_text( text=receive_translation("config_daily_ping_decide", user_language), reply_markup=Configurator.config_daily_ping_keyboard( user_language))
def _daily_ping_users(self, user_ids, day): """Pings all users inside the user id list with all of their events of the given day. Args: user_ids (list of 'str'): Contains all users. day (int): Represents the day which should be pinged for. """ bot = BotControl.get_bot() for user_id in user_ids: user_events = DatabaseController.load_user_events(user_id) language = DatabaseController.load_selected_language(user_id) events_of_today = [event for event in user_events if event.day.value == day and event.in_daily_ping] message = "" if events_of_today: message += "*{}*\n\n".format(receive_translation("event_daily_ping_header", language)) for event in events_of_today: message_event = self.build_ping_message(user_id, event) postfix = "_{}".format(event.uuid) bot.send_message(user_id, text=message + message_event, parse_mode=ParseMode.MARKDOWN_V2, reply_markup=Event.event_keyboard_alteration(language, "event", postfix)) # Clear so that the header is only printed once message = ""
def event_alteration_handle_reply(update, context): """Handles the replies of the event alteration.""" user_id = update.message.from_user.id user_language = DatabaseController.load_selected_language(user_id) state = UserEventAlterationMachine.receive_state_of_user(user_id) bot = BotControl.get_bot() logging.info(EventHandler.events_in_alteration[user_id]['old']) event_suffix = "{}".format( EventHandler.events_in_alteration[user_id]['old']['id']) # State: Alter name if state == 11: title = replace_reserved_characters(update.message.text) EventHandler.events_in_alteration[user_id]['new']['title'] = title UserEventAlterationMachine.set_state_of_user(user_id, 99) bot.send_message( user_id, text=receive_translation("event_alteration_change_decision", user_language), reply_markup=Event.event_keyboard_alteration_change_start( user_language, "event_change_{}".format(event_suffix))) # State: Alter content elif state == 12: content = replace_reserved_characters(update.message.text) EventHandler.events_in_alteration[user_id]['new'][ 'content'] = content UserEventAlterationMachine.set_state_of_user(user_id, 99) bot.send_message( user_id, text=receive_translation("event_alteration_change_decision", user_language), reply_markup=Event.event_keyboard_alteration_change_start( user_language, "event_change_{}".format(event_suffix)))
def add_new_event_query_handler(update, context): """Creates a new event with help of the event creation state machine and keyboards.""" query = update.callback_query query.answer() if query.message.chat['type'] == "group": user_id = query.message.chat['id'] else: user_id = query.from_user['id'] user_language = DatabaseController.load_selected_language(user_id) bot = BotControl.get_bot() # State: Requesting event type if UserEventCreationMachine.receive_state_of_user(user_id) == 1: EventHandler.events_in_creation[user_id]["event_type"] = int( query.data) if query.data == "{}".format(EventType.SINGLE.value): message = receive_translation("event_creation_type_single", user_language) elif query.data == "{}".format(EventType.REGULARLY.value): message = receive_translation("event_creation_type_regularly", user_language) else: message = receive_translation("undefined_error_response", user_language) query.edit_message_text(text=message) UserEventCreationMachine.set_state_of_user(user_id, 2) # State: Requesting day of the event if UserEventCreationMachine.receive_state_of_user(user_id) == 2: logging.info(query.data) if query.data[0] == 'd': EventHandler.events_in_creation[user_id]["day"] = query.data[ 1:] UserEventCreationMachine.set_state_of_user(user_id, 3) bot.delete_message(user_id, query.message.message_id) else: bot.send_message( user_id, text=receive_translation("event_creation_day", user_language), reply_markup=Event.event_keyboard_day(user_language)) # State: Requesting start hours of the event if UserEventCreationMachine.receive_state_of_user(user_id) == 3: logging.info(query.data) if query.data[0] == 'h': EventHandler.events_in_creation[user_id]["hours"] = query.data[ 1:] UserEventCreationMachine.set_state_of_user(user_id, 4) bot.delete_message(user_id, query.message.message_id) else: bot.send_message(user_id, text=receive_translation( "event_creation_hours", user_language), reply_markup=Event.event_keyboard_hours()) # State: Requesting start minutes of the event if UserEventCreationMachine.receive_state_of_user(user_id) == 4: logging.info(query.data) if query.data[0] == 'm': EventHandler.events_in_creation[user_id]["event_time"] = \ "{}:{}".format(EventHandler.events_in_creation[user_id]["hours"], query.data[1:]) UserEventCreationMachine.set_state_of_user(user_id, 10) query.edit_message_text(text=receive_translation( "event_creation_finished", user_language)) else: bot.send_message(user_id, text=receive_translation( "event_creation_minutes", user_language), reply_markup=Event.event_keyboard_minutes()) # State: Start requesting ping times for the event - reset status. if UserEventCreationMachine.receive_state_of_user(user_id) == 10: ping_states = DEFAULT_PING_STATES.copy() EventHandler.events_in_creation[user_id][ "ping_times"] = ping_states query.edit_message_text( text=receive_translation("event_creation_ping_times_header", user_language), reply_markup=Event.event_keyboard_ping_times( user_language, "event_creation", ping_states)) UserEventCreationMachine.set_state_of_user(user_id, 11) elif UserEventCreationMachine.receive_state_of_user(user_id) == 11: if "ping_times" in query.data: suffix = query.data.split('_')[-1] if suffix == "done": UserEventCreationMachine.set_state_of_user(user_id, -1) bot.delete_message(user_id, query.message.message_id) else: EventHandler.events_in_creation[user_id]["ping_times"][suffix] = \ not EventHandler.events_in_creation[user_id]["ping_times"][suffix] query.edit_message_text( text=receive_translation( "event_creation_ping_times_header", user_language), reply_markup=Event.event_keyboard_ping_times( user_language, "event_creation", EventHandler.events_in_creation[user_id] ["ping_times"])) # State: All data collected - creating event if UserEventCreationMachine.receive_state_of_user(user_id) == -1: event_in_creation = EventHandler.events_in_creation[user_id] event = Event(event_in_creation["title"], DayEnum(int(event_in_creation["day"])), event_in_creation["content"], EventType(event_in_creation["event_type"]), event_in_creation["event_time"], event_in_creation["ping_times"]) DatabaseController.save_event_data_user(user_id, event) UserEventCreationMachine.set_state_of_user(user_id, 0) EventHandler.events_in_creation.pop(user_id) # Needed because when an event is created on the current day but has already passed there # would be pings for it. event_hour, event_minute = event.event_time.split(":") current_time = datetime.now() if int(event_in_creation["day"]) == current_time.weekday() and int(event_hour) < current_time.hour or \ (int(event_hour) == current_time.hour and int(event_minute) < current_time.minute): event.start_ping_done = True event.ping_times_to_refresh = {} for ping_time in event.ping_times: if event.ping_times[ping_time]: event.ping_times_to_refresh[ping_time] = True event.ping_times = DEFAULT_PING_STATES.copy() DatabaseController.save_event_data_user(user_id, event) message = receive_translation("event_creation_summary_header", user_language) message += event.pretty_print_formatting(user_language) bot.send_message(user_id, text=message, parse_mode=ParseMode.MARKDOWN_V2)