def set_user_timezone(message, user_id): try: if get_user_data(user_id, 'updating') == 'updating_process': if not message and get_current_state( user_id) != constants.States.S_SET_TIMEZONE.value: bot_actions.send_message( user_id, 'Мне нужно определить ваш часовой пояс. ' 'Пожалуйста, напишите точное время в городе, где вы находитесь.' ) set_state(user_id, constants.States.S_SET_TIMEZONE.value) return if data_processing.check_correction_data(user_id, 'at_time', message): timezone = get_user_tz_delta(message) set_user_data(user_id, 'tz_delta', timezone) else: return if get_user_data(user_id, 'updating') == 'updating_process': bot_actions.send_message(user_id, 'Данные успешно изменены.') set_state(user_id, get_user_data(user_id, 'last_state')) set_user_data(user_id, 'updating', 'false') else: bot_actions.bot_send_keyboard( 'Выберите периодичность сбора данных', user_id, { key: value[0] for (key, value) in constants.choose_period.items() }) set_state(user_id, constants.States.S_SET_DATE.value) except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def user_asks_help(user_id): user = db_operator.get_user(user_id) if user: try: bot_actions.send_message( user_id, "<b>Ваши данные</b>:\n" f"<b>Текст письма</b>:\n {user['mail_text']}\n" f"<b>Получатель</b>: {user['mail_to']}\n" f"<b>Следующая дата отправки</b>: {user['next_date'].split('.')[0][:-3]}\n" "Комадны:\n" "/help - ее вы уже использовали и видите результат\n" "/update - изменить некоторые данные\n" "/delete - удалить свои данные\n" "/last - последние отправленные данные\n" "/info - чтобы узнать обо мне" "Чтобы сохранить шаблон, но отменить оправку данных, просто напишите 'отмена'", parse_mode='HTML') except Exception as e: print( f'Error while running "user_asks_help" 3 with args: {e.args}') return None else: bot_actions.send_message( user_id, 'Чтобы создать шаблон письма для отправи данных - воспользуйтесь командой /start\n' 'Чтобы узнать обо мне - /info')
def collect_values(message, user_id): user = db_operator.get_user(user_id) try: user['last_sending_date'] except KeyError: db_operator.set_user_last_date(user_id, str(datetime.today())) lens = db_operator.check_collect_progress(user_id) if lens[1] < lens[0] and db_operator.get_current_state( user_id) == constants.States.S_ENTER_DATA.value: if data_processing.msg_check(message, 'digit'): if db_operator.update_data_value(user_id, user['vars'][f'{lens[1] + 22}'], message): lens = db_operator.check_collect_progress(user_id) if lens[0] >= lens[1] + 1: text = f"Введите {user['vars'][f'{lens[1] + 22}']}" options = { 'later_hour': 'через час', 'later_day': 'завтра', } bot_actions.bot_send_keyboard(text, user_id, options) else: bot_actions.send_message( user_id, text="Нужно ввести цифры, попробуй ещё раз.") if lens[1] == lens[0]: send_data(user_id) db_operator.set_user_next_date(user_id) bot_actions.send_message( user_id, f'Ваши данные успешно отправлены на адрес {user["mail_to"]}.\n' f'Следующая дата отправки - ' f'{db_operator.get_user_data(user_id, "next_date").split(".")[0][:-3]}' ) db_operator.set_state(user_id, constants.States.S_USER_WAIT.value) time.sleep(1)
def delete_data(user_id): db_operator.delete_user_data(user_id) bot_actions.send_message(user_id, 'Ваши данные удалены.') try: if timers[str(user_id)]: timers[str(user_id)]['timer'].cancel() except KeyError: print(timers)
def user_asks_last(user_id): if db_operator.get_last_data(user_id): last_date = db_operator.get_user_data(user_id, 'last_sending_date') data_dict = db_operator.get_last_data(user_id) data = [f'<b>{key}</b>: {value}\n' for key, value in data_dict.items()] msg = f'<b>Дата отправки</b>: {last_date.split(".")[0][:-3]}\n{"".join(data)}' bot_actions.send_message(user_id, msg, parse_mode='HTML') else: bot_actions.send_message( user_id, 'В базе отсутствуют записи об отправляемых вами числовых данных.')
def user_doing_nothing(message, user_id): user = db_operator.get_user(user_id) if user: bot_actions.bot_send_keyboard( 'Нажмите на кнопку, чтобы возобновить отправку данных.\nЧтобы получить справку, введите /help', user_id, {'renew': 'Возобновить'}) else: bot_actions.send_message( user_id, 'Чтобы узнать обо мне, воспользуйтесь командой /info\n' 'Чтобы получить информацию о командах и ваших данных ' '(если вы их вносили) - /help')
def when_timer_stop(flag, user_id, in_progress=False): user = db_operator.get_user(user_id) db_operator.set_state(user_id, user['last_state']) print(f'state is {db_operator.get_current_state(user_id)}') text = '' options = { 'later_hour': 'через час', 'later_day': 'завтра', } try: if flag: text = "Введите ранее запрошенные показания:" else: try: if str(datetime.today() )[:10] == user['last_sending_date'][:10]: data_v = db_operator.get_last_data(user_id) us_vars = db_operator.get_user_data(user_id, 'vars').values() if all(x in data_v.keys() for x in us_vars): db_operator.set_user_last_date( user_id, str(datetime.today() + timedelta(days=1))) db_operator.set_user_next_date(user_id) bot_actions.send_message( user_id, 'Данные за сегодняшнее число уже были отправлены\n' '<b>Следующая дата отправки</b>: ' f'{db_operator.get_user_data(user_id, "next_date")}', parse_mode='HTML') user_set_timer(None, user_id) return elif not in_progress: lens = db_operator.check_collect_progress(user_id) text = f"Введите {user['vars'][f'{lens[1] + 22}']}" except Exception: if not in_progress: lens = db_operator.check_collect_progress(user_id) text = f"Введите {user['vars'][f'{lens[1] + 22}']}" except KeyError: try: print(user['last_sending_date']) except KeyError: db_operator.set_user_last_date(user_id, str(datetime.today())) text = "Подтвердите отправку" options = {'send': 'Отправить'} if text: bot_actions.bot_send_keyboard(text, user_id, options)
def user_asks_info(user_id): bot_actions.send_message( user_id, 'Я бот, который будет отправлять ваши численные данные по электронной ' 'почте и поможет вам автоматизировать сам процесс сбора и отправки данных.\n' 'Для этого нам изначально необходимо вместе сформировать <b>шаблон письма</b> ' '(в который я буду подставлять данные), определиться с <b>периодом отправки</b> ' 'этого письма и <b>электронными адресами</b> получателей.\n' 'Например у вас есть необходимость отправлять данные счетчиков холодной и ' 'горячей воды на электронную почту вашей коммунальной службы. Чтобы вы не ' 'забывали это делать, я буду это делать за вас - раз в месяц я буду спрашивать' ' у вас показания и самостоятельно отправлять их на нужный адрес :)\n' 'Чтобы начать создание шаблона - воспользуйтесь командой /start\n' 'Текст письма должен будет пройти модерацию ' '(никаких нигерийских писем и тому подобного!)\n' 'P.S.: можете меня использовать для отправки текста без данных.', parse_mode='HTML')
def correct_user_date(message, user_id): try: user = get_user(user_id) for item in constants.corQuests: item_key = list(item.keys())[0] period_details = constants.choose_period[get_user_data( user_id, 'send_period')] if all([item_key in period_details, item_key not in user.keys()]): if data_processing.check_correction_data( user_id, item_key, message): set_user_data(user_id, item_key, message) user = get_user(user_id) if item_key == period_details[-1]: continue for next_item in constants.corQuests: item_key = list(next_item.keys())[0] if all([ item_key in period_details, item_key not in user.keys() ]): bot_actions.send_message(user_id, next_item[item_key][0]) break return else: return set_state(user_id, constants.States.S_SET_TIMER.value) set_user_data(user_id, 'next_date', str(data_processing.count_timedelta(user))) if get_user_data(user_id, 'updating') != 'updating_process': set_user_data(user_id, 'collecting', 'true') append_user(user_id) else: bot_actions.send_message(user_id, 'Данные успешно изменены.') get_user(user_id, return_obj=False) set_user_data(user_id, 'updating', 'false') return 'collect' except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def set_user_mailto(message, user_id): try: if get_user_data(user_id, 'updating') == 'updating_process': if not message and get_current_state( user_id) != constants.States.S_SET_MAIL_TO.value: bot_actions.send_message( user_id, 'Введите e-mail получателя.\nМожете ввести несколько адресов через ' 'пробел.\nЕсли хотите проверять то, что приходит получателю, можете' 'ввести, в том числе, свой e-mail:') set_state(user_id, constants.States.S_SET_MAIL_TO.value) return check = data_processing.msg_check(message, 'mail_to') if not isinstance(check, bool): if check > 1: bot_actions.send_message( user_id, 'Один из отправленных вами адресов содержит ошибки, введите адреса еще' ' раз и проверьте корректность написанного.') else: bot_actions.send_message( user_id, 'Отправленный вами адрес содержит ошибки, введите адрес еще раз' ' и проверьте корректность написанного.') return else: set_user_data(user_id, 'mail_to', message) if get_user_data(user_id, 'updating') == 'updating_process': bot_actions.send_message(user_id, 'Данные успешно изменены.') set_state(user_id, get_user_data(user_id, 'last_state')) set_user_data(user_id, 'updating', 'false') else: bot_actions.send_message( user_id, 'Мне нужно определить ваш часовой пояс. ' 'Пожалуйста, напишите точное время в городе, где вы находитесь.' ) set_state(user_id, constants.States.S_SET_TIMEZONE.value) except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def get_user(user_id, return_obj=True): with Vedis(private_constants.db_users) as db: try: user = ast.literal_eval(db[user_id].decode('utf-8')) if return_obj: return user else: pprint(user) bot_actions.send_message( user_id, "<b>Ваши данные</b>:\n" f"<b>Текст письма</b>:\n{user['mail_text']}\n" f"<b>Получатель</b>: {user['mail_to']}\n" f"<b>Следующая дата отправки</b>: {user['next_date'].split('.')[0][:-3]}", parse_mode='HTML') except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def set_user_theme(message, user_id): try: if get_user_data(user_id, 'updating') == 'updating_process': if not message: bot_actions.send_message( user_id, 'Введите тему письма.\nПример:\n' '<i>Показания ИПУ по адресу ул. Пушкина, д. 1, кв. 2</i>', parse_mode='HTML') set_state(user_id, constants.States.S_SET_MAILTHEME.value) return set_user_data(user_id, 'mail_theme', message) if get_user_data(user_id, 'updating') == 'updating_process': bot_actions.send_message(user_id, 'Данные успешно изменены.') set_state(user_id, get_user_data(user_id, 'last_state')) set_user_data(user_id, 'updating', 'false') else: bot_actions.send_message( user_id, 'Введите e-mail получателя.\nМожете ввести несколько адресов через ' 'пробел.\nЕсли хотите проверять то, что приходит получателю, можете' 'ввести, в том числе, свой e-mail:') set_state(user_id, constants.States.S_SET_MAIL_TO.value) except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def set_moder_status(user_id, message, status='requires_confirmation'): try: set_user_data(user_id, 'moderation', status) if status == 'deny': bot_actions.send_message( user_id, 'Отправленный вами текст не прошел модерацию. В случае, если вас интересует ' 'функционал, предоставляемый мной, просьба отправить корректный текст, ' 'написанный в соответствии с показанным примером. Если имеете претензии ' 'к модерации, просьба связаться с создателем бота.') if status == 'confirm': bot_actions.send_message(user_id, 'Текст успешно прошел модерацию!') if get_user_data(user_id, 'updating') == 'updating_process': set_user_data(user_id, 'updating', 'updated') set_user_template(message, user_id) except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def user_wait(message, user_id): user_id = str(user_id) if timers[user_id]['in_progress'] or 'отмен' in message.lower(): timers[user_id]['timer'].cancel() if 'отмен' in message.lower(): bot_actions.send_message(user_id, 'Отправка данных отменена') db_operator.set_state(user_id, constants.States.S_START.value) db_operator.swap_collect(user_id) return elif message.isdigit(): when_timer_stop(False, user_id, in_progress=True) db_operator.set_state( user_id, db_operator.get_user_data(user_id, 'last_state')) actions[db_operator.get_user_data(user_id, 'last_state')](message, user_id) else: when_timer_stop(True, user_id) else: user = db_operator.get_user(user_id) bot_actions.send_message( user_id, 'Следующая отправка данных:\n' f'{user["next_date"].split(".")[0][:-3]}')
def update_data(user_id): try: user = db_operator.get_user(user_id) msg = f"<b>Ваши данные</b>:\n" \ f"<b>Текст письма</b>:\n{user['mail_text']}\n" \ f"<b>Тема письма</b>:\n{user['mail_theme']}\n" \ f"<b>Получатель</b>: {user['mail_to']}\n" \ f"<b>Временная разница с сервером</b>: {user['tz_delta']} ч\n" \ f"<b>Период отправки данных</b>: {constants.choose_period[(user['send_period'])][0]}\n" keys = [ key for key in constants.choose_period[data_processing.in_array( list(constants.choose_period.keys()), [user['send_period']])] [1:] ] send_period_info = [ f'<b>{value[key][1]}</b>{user[key]}\n' for value in constants.corQuests for key in keys if key in value.keys() ] msg = f'{msg}{"".join(send_period_info)}' bot_actions.send_message(user_id, msg, parse_mode='HTML') options = { 'update_template': 'Текст письма', 'update_mail_theme': 'Тема письма', 'update_mail_to': 'Получатель', 'update_send_period': 'Период отправки данных', 'update_timezone': 'Часовой пояс', } db_operator.set_user_data(user_id, 'updating', 'true') bot_actions.bot_send_keyboard( 'Укажите, какие данных вы хотели бы отредактировать: ', user_id, options) except TypeError: bot_actions.send_message( user_id, 'У меня нет ваших данных.\n' 'Чтобы узнать обо мне, воспользуйтесь командой /info\n' 'Чтобы начать создание шаблона - /start')
def callback_wait(user_id, option): user_id = str(user_id) user = db_operator.get_user(user_id) if option == 'day': time_obj = parse(parse_time(user['at_time'])) seconds_delta = datetime.today() + timedelta(days=1) seconds_delta = seconds_delta.replace(hour=time_obj.hour, minute=time_obj.minute, second=0) - datetime.today() bot_actions.send_message( user_id, text=f"Переспрошу завтра в {time_obj.hour}:{time_obj.minute}") else: seconds_delta = timedelta(hours=1) bot_actions.send_message(user_id, text="Переспрошу через час") timer = Timer(seconds_delta.total_seconds(), when_timer_stop, args=(True, user_id)) timers.update({user_id: {'timer': timer, 'in_progress': True}}) db_operator.set_user_last_state(user_id, constants.States.S_ENTER_DATA.value) db_operator.set_state(user_id, constants.States.S_USER_WAIT.value) timers[user_id]['timer'].start() print(timers[user_id]['timer'])
def set_user_date(message, user_id): try: if get_user_data(user_id, 'updating') == 'updating_process': if not message and get_current_state( user_id) != constants.States.S_SET_DATE.value: corquest_keys = [ list(x.keys())[0] for x in constants.corQuests ] print([ remove_user_data(user_id, item) for item in corquest_keys if get_user_data(user_id, item) ]) bot_actions.bot_send_keyboard( 'Выберите периодичность сбора данных', user_id, { key: value[0] for (key, value) in constants.choose_period.items() }) set_state(user_id, constants.States.S_SET_DATE.value) return set_user_data(user_id, 'send_period', message) user = get_user(user_id) for item in constants.corQuests: item_key = list(item.keys())[0] if all([ item_key in constants.choose_period[user['send_period']], item_key not in user.keys() ]): bot_actions.send_message(user_id, item[item_key][0]) break set_state(user_id, constants.States.S_CORRECT_DATE.value) except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def new_user_init(user_id): if db_operator.get_user(user_id): bot_actions.send_message( user_id, 'Я нашел ваши данные!\n' 'Если хотите проверить и изменить свои данные, используйте команду /update\n' 'Если хотите удалить свои данные - /delete') else: if db_operator.init_user(user_id=user_id): bot_actions.send_message( user_id, 'Начнем с формирования шаблона!\n<b>Если ' 'вдруг что-то пойдет не так - воспользуйтесь командой</b> /delete!\n' 'Введите текст письма. Следуйте примеру, выделяя места появления данных' ' и текущей даты фигурными скобками (если отметить место для текущей даты' ', при отправке письма она будет появляться в выбранном месте ' 'автоматически). Пример:\n\n' '<i>Добрый день!\n' 'Показания ИПУ по адресу ул. Пушкина, д. 1, кв. 2 на {дата}:\n\n' 'Электроэнергия: {показания счетчика электроэнергии}\n' 'Холодное водоснабжение: {показания счетчика холодной воды}\n' 'Горячее водоснабжение: {показания счетчика горячей воды}\n\n' 'С уважением, Петров А. А.</i>', parse_mode='HTML') db_operator.set_state(user_id, constants.States.S_SET_TEMPLATE.value)
def set_user_template(message, user_id): try: if get_user_data(user_id, 'updating') == 'updating_process': if not message: bot_actions.send_message( user_id, 'Введите текст письма. Следуйте примеру, выделяя места появления данных' ' и текущей даты фигурными скобками. Пример:\n\n' '<i>Добрый день!\n' 'Показания ИПУ по адресу ул. Пушкина, д. 1, кв. 2 на {дата}:\n\n' 'Электроэнергия: {показания счетчика электроэнергии}\n' 'Холодное водоснабжение: {показания счетчика холодной воды}\n' 'Горячее водоснабжение: {показания счетчика горячей воды}\n\n' 'С уважением, Петров А. А.</i>', parse_mode='HTML') set_state(user_id, constants.States.S_SET_TEMPLATE.value) set_moder_status(user_id, message, 'new') return print(str(get_user_data(user_id, 'moderation'))) if not get_user_data(user_id, 'moderation'): set_moder_status(user_id, message, 'new') if get_user_data(user_id, 'moderation') == 'confirm': if get_user_data(user_id, 'updating') != 'updated': bot_actions.send_message( user_id, 'Введите тему письма.\nПример:\n' '<i>Показания ИПУ по адресу ул. Пушкина, д. 1, кв. 2</i>', parse_mode='HTML') set_state(user_id, constants.States.S_SET_MAILTHEME.value) else: set_user_data(user_id, 'updating', 'false') bot_actions.send_message(user_id, 'Данные успешно изменены.') set_state(user_id, get_user_data(user_id, 'last_state')) elif get_user_data(user_id, 'moderation') == 'requires_confirmation': bot_actions.send_message( user_id, 'Ваше сообщение находится на модерации. Оформление шаблона продолжится позже.' ) elif get_user_data(user_id, 'moderation') in ('deny', 'new'): if not message.count('{') == message.count('}'): bot_actions.send_message( user_id, 'Некорректно выделены переменные. Каждая из них должна ' 'быть заключена в две фигурные скобки - ' 'на пример {переменная раз} и {переменная два}') return variables = { str(i + 20): segment.split('}')[0] for (i, segment) in enumerate(message.split('{')) if '}' in segment and 'дата' not in segment } set_user_data(user_id, 'mail_text', message) set_user_data(user_id, 'vars', variables) bot_actions.send_message( user_id, 'Ваше сообщение отправлено на модерацию.' '\nПосле подтверждения, оформление шаблона продолжится позже.') set_moder_status(user_id, message=message) print(message) bot_actions.bot_send_keyboard(message, private_constants.moder_id, { f'confirm {user_id}': 'Одобрить', f'deny {user_id}': 'Отклонить' }) except Exception as e: func_name = _getframe().f_code.co_name print( f'{e.__class__.__name__} while running "{func_name}" with args: {e.args}' ) return False
def check_correction_data(user_id, item_key, message): if item_key in ('days', 'weeks', 'months', 'day_of_month'): try: message = int(message) except ValueError: bot_actions.send_message( user_id, f'{message} - содержит недопустимые символы. Введите цифры, пожалуйста.' ) return False if message < 0: bot_actions.send_message( user_id, f'{message} - значение не должно быть меньше нуля. Введите корректное значение.' ) return False if item_key == 'day_of_week': if not parse_dow(message): bot_actions.send_message( user_id, f'{message} - некорректный ввод. Введите, пожалуйста, наименование дня недели.' ) return False if item_key == 'at_time': print(parse_time(message)) if not parse_time(message): bot_actions.send_message( user_id, f'{message} - некорректный ввод. Вы можете написать,' f' к примеру "в 18 30" или просто "18".') return False elif parse_time(message) == 'minute': bot_actions.send_message( user_id, 'Минуты должны быть в диапазоне 0..59. Попробуйте еще раз.') return False elif parse_time(message) == 'hour': bot_actions.send_message( user_id, 'Часы должны быть в диапазоне 0..23. Попробуйте еще раз.') return False return True
def user_resume(user_id): db_operator.swap_collect(user_id) bot_actions.send_message(user_id, 'Отправка данных возобновлена') user_set_timer(None, user_id)