Пример #1
0
 def map(question_queue_item):
     item = UnprocessedQuestion()
     item.id = question_queue_item.id
     item.question = question_queue_item.text
     item.author = question_queue_item.added_by_name
     item.scheduled_time = DatetimeUtils.to_ddmmyyyy_hhmm(question_queue_item.time_planned, timedelta(hours=3))
     item.time_left = DatetimeUtils.timedelta_to_string(question_queue_item.time_planned - datetime.utcnow(), '{days}d {hours}h {minutes}m')
     return item
Пример #2
0
 def __statistic_to_string(statistic: WeekStatistic) -> str:
     result = emojize(':fire: СТАТИСТИКА :fire:\n\n', use_aliases=True)
     result += WeekStatisticNotifier.__get_summary_message(
         statistic.total_post_count,
         DatetimeUtils.to_ddmmyyyy(statistic.week_start_utc),
         DatetimeUtils.to_ddmmyyyy(statistic.week_end_utc))
     if statistic.total_post_count > 0:
         result += '\n\n'
         for day_of_week in range(7):
             result += f'{WeekStatisticNotifier.__day_of_week_str[day_of_week]}: {statistic.post_count_by_day_of_week[day_of_week]}\n'
     return result
Пример #3
0
 def map(question_queue_item):
     item = ProcessedQuestion()
     item.question = question_queue_item.text
     item.author = question_queue_item.added_by_name
     item.sent_time = DatetimeUtils.to_ddmmyyyy_hhmm(question_queue_item.time_sent, timedelta(hours=3))
     item.has_answer = question_queue_item.has_answer
     return item
Пример #4
0
def process_ask_question_callback(query):
    try:
        if query.data in ['instant_cancel', 'scheduled_cancel']:
            bot.delete_message(query.message.chat.id, query.message.message_id)
            return

        edited_text = 'Спрашиваем...' if query.data == 'instant_question' else 'Планируем...'
        bot.edit_message_text(chat_id=query.message.chat.id,
                              message_id=query.message.message_id,
                              text=edited_text)
        message_parts = query.message.text.split('\n', maxsplit=1)
        text = message_parts[1].strip()
        full_name, username = UserNamesExtractor.get_fullname_and_username(
            query.message.chat)
        added_by_name = full_name if full_name else (
            username if username else query.message.chat.id)
        now = datetime.utcnow()

        if query.data == 'instant_question':
            try:
                QuestionAsker.ask(text)
                questions_queue_repository.add(
                    QuestionQueueItem(
                        text=text,
                        time_created=now,
                        time_planned=now,
                        time_sent=now,
                        status=QuestionQueueItemStatus.InstantlyInserted,
                        added_by_id=query.message.chat.id,
                        added_by_name=added_by_name,
                        has_answer=False))
            except:
                bot.edit_message_text(chat_id=query.message.chat.id,
                                      message_id=query.message.message_id,
                                      text='К сожалению, что-то сгнило!')
        else:
            regex = re.compile(
                r'^.+(?P<datetime>\d\d\.\d\d\.\d\d\d\d\s+\d\d\:\d\d).+$')
            match = regex.match(message_parts[0])
            planned_time = DatetimeUtils.parse_dmy_hm(match.group('datetime'),
                                                      timedelta(hours=-3))
            questions_queue_repository.add(
                QuestionQueueItem(text=text,
                                  time_created=now,
                                  time_planned=planned_time,
                                  time_sent=None,
                                  status=QuestionQueueItemStatus.Unprocessed,
                                  added_by_id=query.message.chat.id,
                                  added_by_name=added_by_name,
                                  has_answer=False))

        bot.delete_message(query.message.chat.id, query.message.message_id)
        bot.send_sticker(query.message.chat.id, StickerIds.done)
    finally:
        requests_notifier.notify(query.message.chat.id, query.data)
Пример #5
0
    def parse(text: str) -> MessageParsingResult:
        text = text.strip()
        result = MessageParsingResult()

        if text.startswith('-q'):
            pattern = re.compile(
                r'^-q\s+(?P<datetime>\d{1,2}\.\d{1,2}\.\d\d\d\d\s+\d{1,2}\:\d{1,2})(?P<text>[\s\S]+)$'
            )
            match = pattern.match(text)
            if match:
                result.type = MessageType.ScheduledQuestion
                try:
                    planned_time = DatetimeUtils.parse_dmy_hm(
                        match.group('datetime'))
                    planned_time_str = DatetimeUtils.to_ddmmyyyy_hhmm(
                        planned_time)
                    now = datetime.utcnow() + timedelta(hours=3)
                    if planned_time < now:
                        result.is_valid = False
                        now_str = DatetimeUtils.to_ddmmyyyy_hhmm(now)
                        result.comment = f'Необходимо указать время из будущего! Время на сервере {now_str}, а вы ' \
                                         f'указали {planned_time_str}. '
                    else:
                        result.is_valid = True
                        result.planned_time = planned_time
                        result.planned_time_str = planned_time_str
                        result.question = match.group('text').strip()
                except:
                    result.is_valid = False
                    result.comment = 'Вы указали невалидную дату и/или время!'
            else:
                result.is_valid = True
                result.type = MessageType.InstantQuestion
                result.question = text[2:].strip()
            if result.is_valid:
                question_len = len(result.question)
                max_question_len = 300
                if question_len > max_question_len:
                    result.is_valid = False
                    result.comment = f'Максимальная длина вопроса - {max_question_len} символов. В вашем вопросе {question_len} символов. '
                if question_len <= 0:
                    result.is_valid = False
                    result.comment = 'Вопрос должен содержать хотя бы один символ.'
            return result

        if text.startswith('-vk'):
            result.type = MessageType.VkStatusRequest
            pattern = re.compile(
                r'^-vk\s+(?P<time_from>\d{1,2}\.\d{1,2}\.\d\d\d\d\s+\d{1,2}\:\d{1,2})\s+(?P<time_to>\d{1,2}\.\d{1,2}\.\d\d\d\d\s+\d{1,2}\:\d{1,2})$'
            )
            match = pattern.match(text)
            result.is_valid = True
            if match:
                time_utc_from = DatetimeUtils.parse_dmy_hm(
                    match.group('time_from'), timedelta(hours=-3))
                time_utc_to = DatetimeUtils.parse_dmy_hm(
                    match.group('time_to'), timedelta(hours=-3))
                if (time_utc_from > time_utc_to):
                    time_utc_from, time_utc_to = time_utc_to, time_utc_from
                diff_in_hours = int(
                    (time_utc_to - time_utc_from).total_seconds() // (60 * 60))
                min_hours = 2
                max_hours = 7 * 24
                if min_hours <= diff_in_hours <= max_hours:
                    result.time_utc_from = time_utc_from
                    result.time_utc_to = time_utc_to
                else:
                    result.is_valid = False
                    result.comment = f'Длина интервала должна быть в диапозоне от {min_hours} до {max_hours} часов (вы запросили {diff_in_hours} часов).'
            else:
                result.is_valid = False
                result.comment = 'Не удалось распарсить запрос.'
            return result

        if any(
                word in text.lower() for word in
            ['закружился', 'закружилась', 'кружусь', 'кружимся', 'кружится']):
            result.type = MessageType.ZakruzhilasCommand
            return result

        result.type = MessageType.UnsupportedCommand
        return result
Пример #6
0
def handle_text(message):
    try:
        parsing_result = IncomingMessageParser.parse(message.text)

        if parsing_result.type == MessageType.UnsupportedCommand:
            bot.send_message(message.chat.id, 'Неподдерживаемая команда!!')
            bot.send_sticker(message.chat.id, StickerIds.loh)
            return

        if parsing_result.type == MessageType.ZakruzhilasCommand:
            bot.send_animation(message.chat.id,
                               open('files/zakruzhilas.mp4', 'rb'))
            return

        if parsing_result.type == MessageType.InstantQuestion:
            if parsing_result.is_valid:
                markup = types.InlineKeyboardMarkup(row_width=2)
                confirm_button = types.InlineKeyboardButton(
                    'Задать!!', callback_data='instant_question')
                cancel_button = types.InlineKeyboardButton(
                    'Отмена', callback_data='instant_cancel')
                markup.add(confirm_button, cancel_button)
                text = 'Подтвердите, что хотите задать вопрос прямо сейчас:\n\n' + parsing_result.question
                bot.send_message(message.chat.id, text, reply_markup=markup)
            else:
                bot.send_message(message.chat.id, parsing_result.comment)
            return

        if parsing_result.type == MessageType.ScheduledQuestion:
            if parsing_result.is_valid:
                markup = types.InlineKeyboardMarkup(row_width=2)
                confirm_button = types.InlineKeyboardButton(
                    'Запланировать!!', callback_data='scheduled_question')
                cancel_button = types.InlineKeyboardButton(
                    'Отмена', callback_data='scheduled_cancel')
                markup.add(confirm_button, cancel_button)
                time_left = DatetimeUtils.timedelta_to_string(
                    parsing_result.planned_time -
                    (datetime.utcnow() + timedelta(hours=3)),
                    '{days}д {hours}ч {minutes}м')
                text = f'Подтвердите, что хотите запланировать вопрос на {parsing_result.planned_time_str} (осталось {time_left}):\n\n' + parsing_result.question
                bot.send_message(message.chat.id, text, reply_markup=markup)
            else:
                bot.send_message(message.chat.id, parsing_result.comment)
            return

        if parsing_result.type == MessageType.VkStatusRequest:
            if parsing_result.is_valid:
                plot_sender = VkStatusPlotSender(
                    bot, VkStatusPlotBuilder(vk_online_status_repository))
                plot_sender.send(parsing_result.time_utc_from,
                                 parsing_result.time_utc_to, message.chat.id)
            else:
                bot.send_message(message.chat.id, parsing_result.comment)
            return
    finally:
        requests_notifier.notify(message.chat.id, message.text)
        logs_repository.add({
            'source': 'User message',
            'from_id': message.chat.id,
            'text': message.text,
            'time': datetime.utcnow()
        })
Пример #7
0
 def map(question_queue_item):
     item = ErrorMessage()
     item.question = question_queue_item.text
     item.author = question_queue_item.added_by_name
     item.scheduled_time = DatetimeUtils.to_ddmmyyyy_hhmm(question_queue_item.time_planned, timedelta(hours=3))
     return item
 def time_to_str(time):
     return DatetimeUtils.to_ddmmyyyy_hhmm(time)