Exemplo n.º 1
0
def validate_edited_registries(update: Update, context: CallbackContext):
    try:
        chat_id = update.effective_chat.id
        user_info = get_user_info(chat_id)
        editing_day = datetime.fromisoformat(user_info['editing_day'])
        offset = user_info['utc_delta_seconds']
        _now = datetime.utcnow() + timedelta(seconds=int(offset))

        split_message = (update.effective_message.text + '\n').split('\n')
        i = (list(g) for _, g in groupby(split_message, key=''.__ne__))
        chunks = [a + b for a, b in zip(i, i)]
        last_clock_out = editing_day - timedelta(microseconds=1)
        entries = []
        for chunk in chunks:
            _e, last_clock_out = parse_and_validate_chunk(chunk, last_clock_out, editing_day, chat_id)
            entries = [*entries, *_e]

        # delete before inserting new ones of that day
        delete_that_day_entries(chat_id, editing_day)
        list(map(lambda _e: create_full_entry(**_e), entries))
        send_markdown_msg(update, strings()['edit:done'])
        _cancel_edit(chat_id)
        raise DispatcherHandlerStop
    except DispatcherHandlerStop:
        raise
    except Exception as e:
        logger.error(f"User sent data in wrong format {e}")
        msg = "\n".join([
            strings()['edit:request:entry:wrong_format'],
            strings()['edit:request:model'],
            strings()['edit:suggest:cancel'],
        ])
        send_markdown_msg(update, msg)
    finally:
        raise DispatcherHandlerStop
Exemplo n.º 2
0
def request_language_setup(update: Update, context: CallbackContext) -> None:
    setup_state, _ = get_user_states(str(update.effective_chat.id))
    if setup_state is not SetupState.LANGUAGE_NOT_SET:
        logger.error('request_language_setup being called when state is not LANGUAGE_NOT_SET')
        return None

    if update.callback_query is None or update.callback_query.data not in _callback_query_options:
        reply_markup = InlineKeyboardMarkup(_lang_inline_keyboard_buttons)
        send_markup_msg(update, strings()["language:choose"], reply_markup)
    else:
        query = update.callback_query

        lang = Language(query.data.split("#")[1])
        if lang is Language.ENGLISH:
            set_strings(force_lang=Language.ENGLISH)
        else:
            set_strings(force_lang=Language.PORTUGUESE)

        set_language(chat_id=str(update.callback_query.message.chat.id),
                     lang=lang,
                     next_state=SetupState.TIMEZONE_NOT_SET)

        try:
            set_timezone(str(update.effective_chat.id), int(os.environ.get('TIMEZONE_SECONDS_OFFSET', None)),
                         SetupState.NONE)
            send_markup_msg(update, strings()['setup:complete'], options_kbd(strings()))
        except Exception as e:
            logger.warn(e)
            logger.warn('TIMEZONE_SECONDS_OFFSET not present or in wrong format.\n'
                        'Switching to fallback mode with google maps api.')
            edit_message(update, strings()['language:set'])
            send_message(update, strings()['timezone:request'])

    raise DispatcherHandlerStop
def ensure_valid_clocked_in(update: Update, context: CallbackContext):
    # if the chat_state is clocked_in but there are no records today, this means that
    # the user forgot to clock out the other day.
    chat_id = update.effective_chat.id
    if len(today_entries(chat_id)) == 0:
        user_info = get_user_info(chat_id)
        clocked_in_date = datetime.fromisoformat(user_info['clocked_in_date'])

        # we are in an inconsistent state
        # check if there's any msg waiting for a reply
        # if not, create one
        try:
            msg_id = int(user_info['msg_reply_id'])
            if not update.effective_message.reply_to_message \
                    or update.effective_message.reply_to_message.message_id != msg_id:
                try:
                    update.effective_message.bot.delete_message(chat_id=chat_id, message_id=msg_id)
                except BadRequest:
                    logger.warn('The message to be replied has been deleted by the user, but we\'ll try again')
                generate_reply(update, context, clocked_in_date.isoformat())
                raise DispatcherHandlerStop

            else:
                msg = update.effective_message.text
                time = msg.split('\n')[0]
                if len(time) != 5:  # hh:mm
                    raise ValueError('It should be in format hh:mm')

                hour, minute = int(time.split(':')[0]), int(time.split(':')[1])
                clock_out_date = clocked_in_date.replace(hour=hour, minute=minute,
                                                         microsecond=clocked_in_date.microsecond + 1).isoformat()
                description = msg.split('\n')[0].strip()

                if len(description) == 0:
                    raise ValueError('Description should not be empty')

                if clock_out_date < clocked_in_date.isoformat():
                    raise ValueError('Clock out date must be greater than the clock in date')

                create_full_entry(chat_id, clock_out_date, description)
                remove_msg_reply_id(chat_id)
                send_markup_msg(update, strings()['request:acknowledgment'], options_kbd(strings()))
                raise DispatcherHandlerStop
        except DispatcherHandlerStop:
            raise DispatcherHandlerStop
        except Exception as e:
            logger.error(e)
            generate_reply(update, context, clocked_in_date.isoformat())
            raise DispatcherHandlerStop
        finally:
            raise DispatcherHandlerStop
Exemplo n.º 4
0
def request_timezone_setup(update: Update, context: CallbackContext) -> None:
    state, _ = get_user_states(str(update.effective_chat.id))
    if state is not SetupState.TIMEZONE_NOT_SET:
        logger.error(
            'request_timezone_setup being called when state is not TIMEZONE_NOT_SET'
        )
        return

    if update.message is not None:
        try:
            tz = get_address_and_timezone_by_name(update.message.text)
            is_negative = "-" if tz['offset'] < 0 else ""
            pretty_offset = is_negative + str(
                timedelta(seconds=abs(tz['offset'])))[:-3]
            _inline_keyboard_buttons = [[
                InlineKeyboardButton(
                    strings()['button:yes'],
                    callback_data=f"timezone#yes#{pretty_offset}"),
                InlineKeyboardButton(strings()['button:no'],
                                     callback_data='timezone#no'),
            ]]
            reply_markup = InlineKeyboardMarkup(_inline_keyboard_buttons)
            tz_msg = f"regx*x{tz['timezone_id']}regx*x \nregx*xUTC{pretty_offset}regx*x\n"
            full_msg = strings()["timezone:location:confirm"].format(tz_msg)
            send_markup_msg(update, full_msg, reply_markup, True)
        except LocationNotFoundException:
            send_message(update, strings()['timezone:location:not_found'])
    else:
        query = update.callback_query
        if not any(cb_option in query.data
                   for cb_option in _callback_query_options):
            send_message(update, strings()['timezone:request'])
        else:
            if 'timezone#no' in query.data:
                send_message(update, strings()['timezone:request'])
            else:
                pretty_offset = query.data.split('#')[-1]
                hours, minutes = map(int, pretty_offset.split(':'))
                minutes = minutes if hours >= 0 else minutes * (-1)
                offset = (hours * 60 * 60) + (minutes * 60)
                set_timezone(str(update.effective_chat.id), offset,
                             SetupState.NONE)
                send_markup_msg(update,
                                strings()['setup:complete'],
                                options_kbd(strings()))
    raise DispatcherHandlerStop
Exemplo n.º 5
0
def validate_picked_day(update: Update, context: CallbackContext):
    try:
        chat_id = update.effective_chat.id
        day, month, year = map(int, update.effective_message.text.split('/'))
        _date = datetime.combine(date(year=year, month=month, day=day), time())
        entries = that_day_entries(chat_id, _date.isoformat())
        set_edit_day(chat_id, _date.isoformat())
        edit_entry_request(update, context, entries)
    except DispatcherHandlerStop:
        raise
    except Exception as e:
        logger.error(e)
        msg = "\n".join([
            strings()['edit:request:date:wrong_format'],
            strings()['edit:request:date_model'],
            strings()['edit:suggest:cancel'],
        ])
        send_markdown_msg(update, msg)
    finally:
        raise DispatcherHandlerStop
Exemplo n.º 6
0
def error_handler(update: object, context: CallbackContext):
    logger.error(context.error)
    pprint(update)
    raise context.error