def exception_reporter_wrapper(*args, **kwargs): try: func(*args, **kwargs) except Exception: report_string = '❗️ Exception {}'.format( traceback.format_exc()) #.splitlines() logging.error(report_string) try: with client.context(): tell_admin(report_string) except Exception: report_string = '❗️ Exception {}'.format( traceback.format_exc()) logging.error(report_string)
def retry_on_network_error_wrapper(*args, **kwargs): for retry_num in range(1, 5): try: return func(*args, **kwargs) except telegram.error.NetworkError: sleep_secs = pow(2, retry_num) report_string = '⚠️️ Caught network error, on {} attemp. Retrying after {} secs...'.format( retry_num, sleep_secs) logging.warning(report_string) tell_admin(report_string) time.sleep(sleep_secs) report_string = '❗️ Exception: persistent network error' logging.error(report_string) tell_admin(report_string)
def get_exercise(userid, elevel=None, etype=None): import bot_telegram payload = { 'method': 'get_exercise', 'userid': userid, 'elevel': elevel, 'etype': etype } r = requests.get(API_URL, params=payload) logging.debug('get_exercise method. payload={} response={}'.format( payload, r.text)) try: return r.json() except json.decoder.JSONDecodeError: bot_telegram.tell_admin("JSON error in get_exercise:\n{}".format( r.content))
def deal_with_request(request_json): # retrieve the message in JSON and then transform it to Telegram object update_obj = telegram.Update.de_json(request_json, BOT) # if update_obj.callback_query: # deal_with_callback_query(update_obj.callback_query) # return message_obj = update_obj.message user_obj = message_obj.from_user chat_id = user_obj.id username = user_obj.username last_name = user_obj.last_name if user_obj.last_name else '' name = (user_obj.first_name + ' ' + last_name).strip() # language = user_obj.language_code p = ndb_person.get_person_by_id(user_obj.id) user_name = 'telegram_{}'.format(chat_id) if not api.is_user_registered(user_name): api.add_user(user_name, name) if p == None: p = ndb_person.add_person(chat_id, name, last_name, username) tell_admin('New user: {}'.format(p.get_name_last_name_username())) else: p.update_user(name, last_name, username) if message_obj.forward_from and not p.is_manager(): send_message(p, p.bot_ux().MSG_NO_FORWARDING_ALLOWED) return text = message_obj.text if text: text_input = message_obj.text logging.debug('Message from @{} in state {} with text {}'.format(chat_id, p.state, text_input)) if WORK_IN_PROGRESS and not p.is_manager(): send_message(p, p.bot_ux().MSG_WORK_IN_PROGRESS) return if deal_with_admin_commands(p, message_obj): return if deal_with_universal_command(p, message_obj): return if deal_with_manager_commands(p, message_obj): return logging.debug("Sending {} to state {} with input message_obj {}".format(p.get_name_last_name_username(), p.state, message_obj)) repeat_state(p, message_obj=message_obj)
def deal_with_admin_commands(p, message_obj): text_input = message_obj.text if p.is_manager(): if text_input.startswith('/textUser '): text_input_split = text_input.split(' ', 2) if len(text_input_split)!=3: msg = "Error: /textUser needs 2 arguments (/textUser <id_number> <text>)" send_message(p, msg, markdown=False) return True u_id, text = text_input.split(' ', 2)[1:] user = Person.get_by_id(u_id) if user == None: msg = 'Error: No user found with id: {}'.format(u_id) elif send_message(user, text): msg = 'Message sent successfully to {}'.format(user.get_name_last_name()) else: msg = 'Error: Problems sending message to {}'.format(user.get_name_last_name()) send_message(p, msg, markdown=False) return True elif p.is_admin(): if text_input == '/debug': #send_message(p, game.debugTmpVariables(p), markdown=False) send_text_document(p, 'tmp_vars.json', p.variables) return True # if text_input == '/testInlineKb': # send_message(p, "Test inline keypboard", kb=[[p.bot_ux().BUTTON_YES_CALLBACK('test'), p.bot_ux().BUTTON_NO_CALLBACK('test')]], inline_keyboard=True) # return True if text_input == '/random': from random import shuffle numbers = ['1','2','3','4','5'] shuffle(numbers) numbers_str = ', '.join(numbers) send_message(p, numbers_str) return True if text_input == '/exception': 1/0 return True if text_input == '/wait': import time for i in range(5): send_message(p, str(i+1)) time.sleep(i+1) send_message(p, "end") return True if text_input.startswith('/testText '): text = text_input.split(' ', 1)[1] msg = '🔔 *Messagge from LingoGame* 🔔\n\n' + text logging.debug("Test broadcast " + msg) send_message(p, msg) return True if text_input.startswith('/broadcast '): text = text_input.split(' ', 1)[1] msg = '🔔 *Messagge from LingoGame* 🔔\n\n' + text logging.debug("Starting to broadcast " + msg) broadcast(p, msg) return True if text_input.startswith('/restartUser '): u_id = ' '.join(text_input.split(' ')[1:]) user = Person.get_by_id(u_id) if user: restart(user) msg_admin = 'User restarted: {}'.format(user.get_name_last_name()) tell_admin(msg_admin) else: msg_admin = 'No user found: {}'.format(u_id) tell_admin(msg_admin) return True if text_input == '/reset_all_users': reset_all_users(message=None) #message=p.bot_ux().MSG_THANKS_FOR_PARTECIPATING return True return False
def state_CLOSE_EXERCISE(p, message_obj=None, **kwargs): pux = p.ux() give_instruction = message_obj is None user_telegram_id = p.user_telegram_id() if give_instruction: response = api.get_close_exercise(user_telegram_id) #elevel='', etype='RelatedTo' if response is None: error_msg = "⚠️ None response in get_close_exercise ({})".format(user_telegram_id) tell_admin(error_msg) return if response.get('success', True) == False: error_msg = '⚠️ Detected success false in get_close_exercise ({})'.format(user_telegram_id) tell_admin(error_msg) return r_eid = response['eid'] relation = response['relation'] subject = response['subject'] object = response['object'] # exercise = response['exercise'] # "exercise": "Is it true that sheep is related to herd?", relation_msg_mapping = { 'RelatedTo': 'MSG_CLOSE_EXERCISE_RELATEDTO_X', 'AtLocation': 'MSG_CLOSE_EXERCISE_LOCATEDAT_X', 'PartOf': 'MSG_CLOSE_EXERCISE_PARTOF_X', 'Synonym': 'MSG_CLOSE_EXERCISE_SYNONYMOF_X' } exercise = pux[relation_msg_mapping[relation]].format(subject, object) msg = exercise p.set_variable('eid',r_eid) p.set_variable('exercise',exercise) kb = [[pux.BUTTON_YES, pux.BUTTON_NO], [pux.BUTTON_DONT_KNOW], [pux.BUTTON_EXIT]] send_message(p, msg, kb) else: text_input = message_obj.text if text_input is None: send_message(p, pux.MSG_NOT_VALID_INPUT) return kb = p.get_keyboard() eid = p.get_variable('eid') msg_yes = pux.MSG_YES msg_no = pux.MSG_NO msg_y = msg_yes[0] msg_n = msg_no[0] if text_input in utility.flatten(kb): if text_input == pux.BUTTON_EXIT: restart(p) return elif text_input in [pux.BUTTON_YES, pux.BUTTON_NO, pux.BUTTON_DONT_KNOW]: pass # dealing with it below together with text else: send_message(p, p.ux().MSG_INTERFACE_CHANGED, sleep=2) restart(p) if text_input.upper() in [pux.BUTTON_YES, msg_yes, msg_y, pux.BUTTON_NO, msg_no, msg_n, pux.BUTTON_DONT_KNOW]: response = 1 if text_input.upper() in [pux.BUTTON_YES, msg_yes, msg_y] \ else -1 if text_input.upper() in [pux.BUTTON_NO, msg_no, msg_n] \ else 0 evalutaion_json = api.store_close_response(eid, user_telegram_id, response) if response==0: correct_response = pux.BUTTON_YES if evalutaion_json['correct_response'] == 1 else pux.BUTTON_NO msg = pux.MSG_DONT_WORRY_CORRECT_RESPONSE.format(correct_response) else: correct = evalutaion_json['points']==1 msg = pux.MSG_CORRECT if correct else pux.MSG_WRONG send_message(p, msg, sleepDelay=True, remove_keyboard=True) send_typing_action(p, sleep_time=1) redirect_to_exercise_type(p) else: send_message(p, pux.MSG_NOT_VALID_INPUT)
def state_OPEN_EXERCISE(p, message_obj=None, **kwargs): pux = p.ux() give_instruction = message_obj is None user_telegram_id = p.user_telegram_id() if give_instruction: kb = [[pux.BUTTON_DONT_KNOW],[pux.BUTTON_EXIT]] response = api.get_exercise(user_telegram_id) #elevel='', etype='' # send_message(key.FEDE_CHAT_ID, 'DEBUG:\n{}'.format(json.dumps(response)), markdown=False) if response is None: error_msg = "⚠️ None response in get_exercise ({})".format(user_telegram_id) tell_admin(error_msg) return if response.get('success', True) == False: error_msg = '⚠️ Detected success false in get_exercise ({})'.format(user_telegram_id) tell_admin(error_msg) return r_eid = response['eid'] relation = response['relation'] # exercise = response['exercise'] # "exercise": "Name a thing that is located at a desk", subject = response['subject'] wiki_url = response.get('hint_url', None) previous_responses = response["previous_responses"] relation_msg_mapping = { 'RelatedTo': 'MSG_OPEN_EXERCISE_RELATEDTO_X', 'AtLocation': 'MSG_OPEN_EXERCISE_LOCATEDAT_X', 'PartOf': 'MSG_OPEN_EXERCISE_PARTOF_X', 'Synonym': 'MSG_OPEN_EXERCISE_SYNONYMOF_X', } exercise = pux[relation_msg_mapping[relation]].format(subject) msg = exercise if previous_responses: msg += '\n' + pux.MSG_YOU_PREVIOUSLY_INSERTED.format( ', '.join('*{}*'.format(pr) for pr in previous_responses)) if wiki_url: msg += '\n\n' + pux.MSG_INSPIRATION_CHECK_OUT + '\n' + wiki_url p.set_variable('eid',r_eid) p.set_variable('exercise',exercise) p.set_variable('subject',subject) BUTTON_NUM_NOTIFICATIONS = get_notification_button(p, debug=False) if BUTTON_NUM_NOTIFICATIONS: kb.insert(1, [BUTTON_NUM_NOTIFICATIONS]) send_message(p, msg, kb) else: text_input = message_obj.text if text_input is None: send_message(p, pux.MSG_NOT_VALID_INPUT) return kb = p.get_keyboard() eid = p.get_variable('eid') if text_input in utility.flatten(kb): if text_input == pux.BUTTON_EXIT: restart(p) elif text_input == pux.BUTTON_DONT_KNOW: response_json = api.get_random_response(eid, user_telegram_id) msg = pux.MSG_POSSIBLE_SOLUTION.format(response_json['response']) send_message(p, msg, sleepDelay=True, remove_keyboard=True) send_typing_action(p, sleep_time=1) exercise = p.get_variable('exercise') send_message(p, exercise, kb) # repeat the same question and stay in current state elif text_input.startswith('🌟'): notifications = p.get_variable('notifications') logging.debug("New notifications: {}".format(notifications)) if len(notifications) > 0: notifications_str = '\n'.join(["{} {}: {}".format( # → {} '🏅' if r['badge'] else '•', r['exercise'], r['response']) for r in notifications] #r['exercise'] ) msg = pux.MSG_NEW_NOTIFICATIONS + '\n' + notifications_str send_message(p, msg, kb) p.set_variable('notifications', []) repeat_state(p) else: send_message(p, pux.MSG_NO_NEW_NOTIFICATION) send_typing_action(p, sleep_time=1) exercise = p.get_variable('exercise') send_message(p, exercise, kb) else: send_message(p, p.ux().MSG_INTERFACE_CHANGED, sleep=2) restart(p) else: subject = p.get_variable('subject') if text_input == subject: msg = pux.MSG_SAME_WORD.format(subject) send_message(p, msg, sleepDelay=True, remove_keyboard=True) send_typing_action(p, sleep_time=1) exercise = p.get_variable('exercise') send_message(p, exercise, kb) return response = api.store_response(eid, user_telegram_id, text_input) # send_message(key.FEDE_CHAT_ID, 'DEBUG:\n{}'.format(json.dumps(response)), markdown=False) logging.debug("Response from store_response eid={}, user_telegram_id={}, text_input={}: {}".format(eid, user_telegram_id, text_input, response)) if 'points' in response: r_points = response['points'] points_str = '*{} {}*'.format(r_points, pux.MSG_POINT_PLURAL) \ if r_points and r_points>1 \ else '*1 {}*'.format(pux.MSG_POINT_SINGULAR) msg_inserted = pux.MSG_YOU_HAVE_INSERTED_X.format(text_input) if r_points is None: msg_thanks = pux.MSG_THANKS_FOR_YOUR_ANSWER msg_double_point = pux.MSG_DOUBLE_POINT msg = msg_inserted + ' ' + msg_thanks + '\n' + msg_double_point elif r_points>0: msg_good_job = pux.MSG_GOOD_JOB_POINT.format(points_str) msg = msg_inserted + '\n' + msg_good_job elif r_points == 0: msg_no_points = pux.MSG_NO_POINTS msg = msg_inserted + '\n' + msg_no_points send_message(p, msg) else: # debugging error_msg = response['error'] msg = '⚠️ Backend found an error with user {}:\n{}.'.format( p.get_name_last_name_username(), error_msg) send_message(key.FEDE_CHAT_ID, msg) send_message(p, pux.MSG_AN_ERROR_HAS_OCCURED) send_typing_action(p, sleep_time=1) redirect_to_exercise_type(p)