Exemple #1
0
 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)
Exemple #2
0
 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)
Exemple #3
0
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))
Exemple #4
0
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)
Exemple #5
0
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
Exemple #6
0
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)
Exemple #7
0
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)