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))
Example #3
0
    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))
Example #4
0
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()
Example #5
0
    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))
Example #6
0
    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)