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
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
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
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)
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
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() })
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)