def start_state(bot, update, context): chat = update.effective_chat chat_id = chat.id user = user_service.create_or_get_user(chat) if is_callback(update): deserialized = deserialize_data(update.callback_query.data) action = deserialized[CallbackData.ACTION] if action is Action.SELECTED_LANG: lang = deserialized[CallbackData.DATA] context[CONTEXT_LANG] = Language(lang) lang = context[CONTEXT_LANG] welcome_text = concat_username( emoji_rocket + '*', user, ', ' + message_source[lang]['state.start_state.welcome']) num_all, num_upcoming, num_completed = task_service.find_stats_for_user( chat_id) bot_ver = 19 # because why not? :) completed_percent = 0 if 0 == num_all else int(num_completed / num_all * 100) num_completed = f'{num_completed} ({completed_percent} %)' num_upcoming = f'{num_upcoming} ({0 if 0 == num_all else (100 - completed_percent)} %)' welcome_text = welcome_text.format(num_upcoming, num_completed, num_all, bot_ver) bot.send_message(chat_id=chat_id, text=emojize(welcome_text, use_aliases=True), parse_mode=ParseMode.MARKDOWN, reply_markup=kb.StartStateKb(lang).build())
def select_lang_state(bot, update, context): chat = update.effective_chat chat_id = chat.id user = user_service.create_or_get_user(chat) action = None if is_callback(update): deserialized = deserialize_data(update.callback_query.data) action = deserialized[CallbackData.ACTION] # find out what are we doing now? selecting lang or just showing available langs text = None if action is Action.SELECTED_LANG: deserialized = deserialize_data(update.callback_query.data) lang_string = deserialized[CallbackData.DATA] lang = Language(lang_string) context[CONTEXT_LANG] = lang text = message_source[lang]['btn.select_lang.' + lang_string + '.result'] buttons = kb.StartStateKb(lang).build() elif action is Action.VIEW_LANG: # It's callback. nevertheless just show available langs lang = context[CONTEXT_LANG] text = concat_username( emoji_globe + '*', user, ', ' + message_source[lang]['state.select_lang']) buttons = kb.SelectLangKb(lang).build() else: # It's not callback. just show available langs lang = context[CONTEXT_LANG] text = concat_username( emoji_globe + '*', user, ', ' + message_source[lang]['state.select_lang']) buttons = kb.SelectLangKb(lang).build() bot.send_message(chat_id=chat_id, text=emojize(text, use_aliases=True), parse_mode=ParseMode.MARKDOWN, reply_markup=buttons)
def all_tasks_state(bot, update, context): chat = update.effective_chat chat_id = chat.id lang = context[CONTEXT_LANG] user = user_service.create_or_get_user(chat) user_id = chat_id action = None if is_callback(update): deserialized = deserialize_data(update.callback_query.data) action = deserialized[CallbackData.ACTION] tasks = [] text = None if not is_callback(update) or action is Action.LIST_ALL: tasks = task_service.find_tasks_by_user_id(user_id) text = concat_username( emoji_all + '*', user, ', ' + message_source[lang]['state.all_tasks.tasks.all']) elif action is Action.LIST_UPCOMING: tasks = task_service.find_upcoming_tasks_by_user_id(user_id) text = concat_username( emoji_upcoming + '*', user, ', ' + message_source[lang]['state.all_tasks.tasks.upcoming']) elif action is Action.LIST_COMPLETED: tasks = task_service.find_completed_tasks_by_user_id(user_id) text = concat_username( emoji_completed + '*', user, ', ' + message_source[lang]['state.all_tasks.tasks.completed']) if 0 == len(tasks): text_no_tasks = message_source[lang]['state.all_tasks.no_tasks_yet'] notes = message_source[lang]['state.all_tasks.notes.no_tasks_yet'] text = concat_username(emoji_search + '*', user, ', ' + text_no_tasks + notes) else: text += message_source[lang]['state.all_tasks.notes'] tasks = sorted(tasks, key=lambda t: t.get_create_date()) bot.send_message(chat_id=chat_id, text=emojize(text, use_aliases=True), parse_mode=ParseMode.MARKDOWN, reply_markup=kb.TasksAsButtons(tasks, lang).build())
def view_task_state(bot, update, context): chat = update.effective_chat chat_id = chat.id lang = context[CONTEXT_LANG] task_id = None action = None if is_callback(update): deserialized = deserialize_data(update.callback_query.data) task_id = deserialized[CallbackData.DATA] action = deserialized[CallbackData.ACTION] if action is Action.TASK_PROJECT_SELECTED: task = context[CONTEXT_TASK] # if bot was restarted then it has not tasks in context. then get latest task if task is None: task = task_service.find_latest_task_by_user_id(chat_id) task_id = task.get_id() else: args = update.message.text.split() task_id = args[1] user = user_service.create_or_get_user(chat) task = task_service.find_task_by_id_and_user_id(task_id, user.get_id()) # if task was removed do not show anything if task and task.is_flag_active(): reply_text, reply_markup = view_task_template_and_markup( lang, task, State.VIEW_TASK) if action is Action.TASK_MARK_AS_DONE: reply_markup = None if task.is_task_completed(): task.mark_as_not_completed() reply_text = message_source[lang][ 'btn.view_task.mark_undone.result'] else: task.mark_as_completed() reply_text = message_source[lang][ 'btn.view_task.mark_as_done.result'] text_on_edit, markup_on_edit = view_task_template_and_markup( lang, task, State.VIEW_TASK) bot.edit_message_text( chat_id=chat_id, message_id=update.effective_message.message_id, text=emojize(text_on_edit, use_aliases=True), parse_mode=ParseMode.MARKDOWN, reply_markup=markup_on_edit) elif action is Action.TASK_DISABLE: reply_markup = None if task.is_task_enabled(): task.mark_as_disabled() reply_text = message_source[lang][ 'btn.view_task.disable_notify.result'].format( task.get_description()) else: task.mark_as_enabled() reply_text = message_source[lang][ 'btn.view_task.enable_notify.result'].format( task.get_description()) text_on_edit, markup_on_edit = view_task_template_and_markup( lang, task, State.VIEW_TASK) bot.edit_message_text( chat_id=chat_id, message_id=update.effective_message.message_id, text=emojize(text_on_edit, use_aliases=True), parse_mode=ParseMode.MARKDOWN, reply_markup=markup_on_edit) elif action is Action.TASK_DELETE: task.mark_as_inactive() reply_text = message_source[lang][ 'btn.view_task.delete_task.result'].format(task.get_id()) reply_markup = None bot.delete_message( chat_id=chat_id, message_id=update.callback_query.message.message_id) elif action is Action.TASK_VIEW: # It's not callback, then just render the state reply_text, reply_markup = view_task_template_and_markup( lang, task, State.VIEW_TASK) # set project id by editing current TASK_VIEW elif action is Action.TASK_PROJECT_SELECTED: deserialized = deserialize_data(update.callback_query.data) project_value = deserialized[CallbackData.DATA] project_selected = project_service.create_or_get_project( user.get_id(), project_value) task.set_project_id(project_selected.get_id()) task_service.update_task(task) context[CONTEXT_TASK] = task text_on_edit, markup_on_edit = view_task_template_and_markup( lang, task, State.VIEW_TASK) bot.edit_message_text( chat_id=chat_id, message_id=update.callback_query.message.message_id, text=emojize(text_on_edit, use_aliases=True), parse_mode=ParseMode.MARKDOWN, reply_markup=markup_on_edit) return # update task task_service.update_task(task) # set updated task to context context[CONTEXT_TASK] = task bot.send_message(chat_id=chat_id, text=emojize(reply_text, use_aliases=True), parse_mode=ParseMode.MARKDOWN, reply_markup=reply_markup) else: task_inactive = message_source[lang]['state.view_task.inactive'] bot.send_message(chat_id=chat_id, text=emojize(task_inactive, use_aliases=True))
def handle(bot, update): chat = update.effective_chat chat_id = chat.id curr_context = None try: curr_command = None curr_action = None if is_callback(update): # Callback handling log.info(f'--> Callback from {chat.username} ({chat.id})') data = update.callback_query.data deserialized = deserialize_data(update.callback_query.data) curr_command = deserialized[CallbackData.COMMAND] curr_action = deserialized[CallbackData.ACTION] else: # Regular message/command handling log.info(f'--> Message from {chat.username} ({chat.id})') text = update.message.text if command_filter.known_command(text) is False: # check if user is admin if chat_id in ADMINS: if '/stats' == text: bot.send_message(chat_id=chat_id, text=json.dumps(ERR_COUNTER, indent=2)) return elif text.startswith('/notify_all'): cmd = text.split(' ') text_to_send = ' '.join(cmd[1:]) welcome_back(bot, text_to_send) return else: if text.startswith('/suggest'): cmd = text.split(' ') text_to_send = ' '.join(cmd[1:]) log.warning( f'-->--> Suggest from {chat.username} ({chat_id}): {text}' ) bot.send_message(chat_id=ADMINS[0], text=text_to_send) bot.send_message(chat_id=chat_id, text='Thanks for feedback :)') return reply_on_unknown(bot, chat_id) return curr_command = get_command_type(text) # get all params needed to render state curr_state = g.automata.get_state(chat_id) curr_context = g.automata.get_context(chat_id) log.info(f'curr_state: {curr_state}, curr_command: {curr_command}') # find out state to be rendered next_state = g.automata.get_transition(curr_state, curr_command) if g.dev_mode: bot.send_message( chat_id=chat_id, text=f'prev state: {curr_state.name} ({curr_state.value})\n' f'cmd: {curr_command.name} ({curr_command.value})\n' f'new state: {next_state.name} ({next_state.value})') # get state from service and render handler = state_service.states()[next_state] log.info(f'rendering state: {handler.__name__}') handler(bot, update, curr_context) # update params log.info(f'Updating state to: {next_state.name}') g.automata.set_state(chat.id, next_state) curr_context[CONTEXT_COMMANDS].append(curr_command) curr_context[CONTEXT_ACTION].append(curr_action) if g.dev_mode: print_dev_info(bot, chat_id, curr_context) except Exception as e: try: ERR_COUNTER[str(len(ERR_COUNTER.values()) + 1)] = { 'datetime': str(datetime.datetime.now()), 'chat': chat_id, 'error': str(e), 'context': str(curr_context) } except Exception: pass log.error('Error has been caught in handler: ', e) lang = curr_context[ CONTEXT_LANG] if curr_context is not None else Language.ENG.value text = message_source[lang]['error'] bot.send_message(chat_id=chat_id, text=emojize(text, use_aliases=True), parse_mode=ParseMode.MARKDOWN) else: log.info('<-- Successfully handled')