Beispiel #1
0
def route_callback_query(plugins, get_me, config, http, callback_query):
    """
    Routes a callback query to the appropriate plugin. Callback data is stored in mysql.
    https://core.telegram.org/bots/api#callbackquery
    """
    database = MySQLdb.connect(**config['DATABASE'])
    data = callback_query['data']
    query = 'SELECT plugin_name, plugin_data FROM callback_queries WHERE callback_data="{}"'
    database.query(query.format(data))
    query = database.store_result()
    rows = query.fetch_row(how=1, maxrows=0)
    for db_result in rows:
        plugin_name = db_result['plugin_name']
        plugin_data = json.loads(
            db_result['plugin_data']) if db_result['plugin_data'] else None
        if 'message' in callback_query:
            api_object = TelegramApi(database,
                                     get_me,
                                     plugin_name,
                                     config,
                                     http,
                                     plugin_data=plugin_data,
                                     callback_query=callback_query)
        else:
            api_object = InlineCallbackQuery(database, config, http,
                                             callback_query)
        try:
            plugins[plugin_name].main(api_object)
        except Exception:
            api_object = TelegramApi(database, get_me, plugin_name, config,
                                     http)
            send_error_report(data, traceback.format_exc(), api_object)
        database.commit()
        database.close()
Beispiel #2
0
def check_time_args():
    """
    Continuously checks the MySQL database for time arguments and runs the relevant
    plugin. Creates a different api_object depending on whether it was initialized
    with a standard message or callback query.
    """
    database = MySQLdb.connect(**CONFIG['DATABASE'])
    cursor = database.cursor()
    flagged_time_http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',
                                            ca_certs=certifi.where())
    flagged_time_http.timeout = urllib3.Timeout(connect=1.0)
    flagged_time_http.retries = 3

    while RUNNING.value:
        database.query(
            "SELECT time_id, plugin_name,plugin_data,previous_message FROM flagged_time WHERE "
            "argument_time <= from_unixtime({})".format(int(time.time())))

        query = database.store_result()
        rows = query.fetch_row(how=1, maxrows=0)
        for result in rows:
            time_id = result['time_id']
            plugin_name = result['plugin_name']
            if result['plugin_data']:
                plugin_data = json.loads(result['plugin_data'])
            else:
                plugin_data = None
            previous_message = json.loads(result['previous_message'])
            previous_message['time_id'] = time_id
            if 'message_id' in previous_message:
                api_object = TelegramApi(database,
                                         GET_ME,
                                         plugin_name,
                                         CONFIG,
                                         flagged_time_http,
                                         message=previous_message,
                                         plugin_data=plugin_data)
            else:
                api_object = TelegramApi(database,
                                         GET_ME,
                                         plugin_name,
                                         CONFIG,
                                         flagged_time_http,
                                         callback_query=previous_message,
                                         plugin_data=plugin_data)
            cursor.execute('DELETE FROM `flagged_time` WHERE time_id=%s;',
                           (time_id, ))
            try:
                PLUGINS[plugin_name].main(api_object)
            except KeyError:
                continue
        database.commit()
        time.sleep(SLEEP_TIME)
    database.close()
Beispiel #3
0
 def run_plugin(self, plugin_name, plugin_module, message):
     """
     Inits a plugin with its own DB and commits/closes it after.
     Wrapped for concurrent.futures
     """
     database = MySQLdb.connect(**self.config['DATABASE'])
     api_object = TelegramApi(database, self.get_me, plugin_name, self.config, self.http, message)
     try:
         plugin_module.main(api_object)
     except Exception:
         message = "<code>{}</code>".format(clean_text(traceback.format_exc()))
         api_object.admin_alert(message, forward_message=True)
     database.commit()
     database.close()
Beispiel #4
0
 def check_db_reply(self):
     """
     Checks if the recieved message is a reply to a message flagged by a
     plugin. If not it then runs the standard handle_plugins check.
     """
     chat_id = self.message['chat']['id']
     message_id = self.message['reply_to_message']['message_id']
     self.database.query(
         "SELECT plugin_name, user_id, single_use, currently_active, plugin_data "
         "FROM flagged_messages WHERE message_id={} AND chat_id={};".format(
             message_id, chat_id))
     query = self.database.store_result()
     rows = query.fetch_row(how=1, maxrows=0)
     for result in rows:
         if result['user_id'] and result['user_id'] != self.message['from'][
                 'id']:
             return False
         if result['single_use']:
             self.cursor.execute(
                 "DELETE FROM flagged_messages WHERE message_id=%s",
                 (message_id, chat_id))
         self.message['flagged_message'] = True
         plugin_data = json.loads(
             result['plugin_data']) if result['plugin_data'] else None
         api_object = TelegramApi(self.database, self.get_me,
                                  result['plugin_name'], self.config,
                                  self.http, self.message, plugin_data)
         self.plugins[result['plugin_name']].main(api_object)
         self.database.commit()
     if not rows:
         self.handle_plugins()
Beispiel #5
0
 def check_db_pm(self):
     """
     Checks if there is a currently active flagged_message in the chat where
     the message was sent. In a private chat it is not necessary to reply to the
     flagged message for it to trigger.
     """
     chat_id = self.message['chat']['id']
     self.database.query(
         "SELECT plugin_name, single_use, message_id, plugin_data FROM flagged_messages WHERE "
         "chat_id={} AND currently_active=1".format(chat_id))
     query = self.database.store_result()
     rows = query.fetch_row(how=1, maxrows=0) if query else list()
     for result in rows:
         message_id = result["message_id"]
         if result['single_use']:
             self.cursor.execute(
                 "DELETE FROM flagged_messages WHERE message_id=%s AND chat_id=%s",
                 (chat_id, message_id))
         plugin_data = json.loads(
             result['plugin_data']) if result['plugin_data'] else None
         self.message['flagged_message'] = True
         self.cursor.execute(
             "UPDATE flagged_messages SET currently_active=FALSE WHERE chat_id=%s",
             (chat_id, ))
         self.database.commit()
         self.plugins[result['plugin_name']].main(
             TelegramApi(self.database, self.get_me, result['plugin_name'],
                         self.config, self.http, self.message, plugin_data))
Beispiel #6
0
 def run_plugin(self, plugin_name, plugin_module, message):
     """
     Inits a plugin with its own DB and commits/closes it after.
     Wrapped for concurrent.futures
     """
     database = MySQLdb.connect(**self.config['DATABASE'])
     api_object = TelegramApi(database, self.get_me, plugin_name,
                              self.config, self.http, message)
     try:
         plugin_module.main(api_object)
     except Exception:
         message = "<code>{}</code>".format(
             clean_text(traceback.format_exc()))
         api_object.admin_alert(message, forward_message=True)
     database.commit()
     database.close()
Beispiel #7
0
 def plugin_check(self):
     plugin_triggered = False
     for plugin in self.plugins:
         for key, value in plugin.arguments.items():
             if self.check_argument(key, value, self.message):
                 plugin_triggered = True
                 plugin.main(
                     TelegramApi(self.message, self.misc, self.plugins, self.database,
                                 plugin_id=self.plugins.index(plugin))
                 )
     return plugin_triggered
Beispiel #8
0
def route_callback_query(callback_query, database, plugins, misc):
    if int(time.time()) - int(callback_query['message']['date']) >= 30:
        return
    db_selection = database.select("callback_queries", ["DISTINCT plugin_id", "plugin_data", "data"],
                                   {"data": callback_query['data']})
    for db_result in db_selection:
        plugin_id = db_result['plugin_id']
        plugin_data = json.loads(db_result['plugin_data']) if db_result['plugin_data'] else None
        api_obj = TelegramApi(misc, database, plugin_id, plugin_data=plugin_data,
                              callback_query=callback_query)
        plugins[plugin_id].main(api_obj)
Beispiel #9
0
def route_inline_query(plugins, get_me, config, http, inline_query):
    """
    Routes inline arguments to the appropriate plugin. Only the first match runs.
    https://core.telegram.org/bots/api#inlinequery
    """
    default_plugin = config['BOT_CONFIG']['default_inline_plugin']
    query = str(inline_query['query'])
    for plugin_name, plugin in plugins.items():
        if hasattr(plugin, 'inline_arguments'):
            for argument in plugin.inline_arguments:
                match = re.findall(str(argument), query)
                if match:
                    database = MySQLdb.connect(**config['DATABASE'])
                    inline_query['matched_regex'] = argument
                    inline_query['match'] = match[0]
                    try:
                        plugin.main(
                            TelegramInlineAPI(database, get_me, plugin_name,
                                              config, http, inline_query))
                    except Exception:
                        api_object = TelegramApi(database, get_me, plugin_name,
                                                 config, http)
                        send_error_report(query, traceback.format_exc(),
                                          api_object)
                    database.commit()
                    database.close()
                    return
    if default_plugin:
        database = MySQLdb.connect(**config['DATABASE'])
        inline_query['matched_regex'] = None
        inline_query['match'] = inline_query['query']
        try:
            plugins[default_plugin].main(
                TelegramInlineAPI(database, get_me, plugin_name, config, http,
                                  inline_query))
        except Exception:
            api_object = TelegramApi(database, get_me, plugin_name, config,
                                     http)
            send_error_report(query, traceback.format_exc(), api_object)
        database.commit()
        database.close()
Beispiel #10
0
 def plugin_check(self):
     if int(time.time()) - int(self.message['date']) >= 180:
         return False
     plugin_triggered = False
     for plugin in self.plugins:
         for key, value in plugin.arguments.items():
             if self.check_argument(key, value, self.message):
                 plugin_triggered = True
                 plugin.main(
                     TelegramApi(self.misc, self.database, self.plugins.index(plugin), self.message)
                 )
     return plugin_triggered
Beispiel #11
0
 def check_db(self):
     chat_id = self.message['chat']['id']
     if 'text' in self.message:
         self.message['text'] = util.clean_message(self.message['text'], self.misc['bot_info']['username'])
     if 'reply_to_message' in self.message:
         message_id = self.message['reply_to_message']['message_id']
         db_selection = self.database.select("flagged_messages",
                                             ["plugin_id", "user_id", "single_use", "currently_active"],
                                             {"message_id": message_id, "chat_id": chat_id})
         if db_selection:
             for result in db_selection:
                 if result['user_id'] and result['user_id'] != self.message['from']['id']:
                     return True
                 if result['single_use']:
                     self.database.delete('flagged_messages', {'message_id': message_id, 'chat_id': chat_id})
                 self.message['flagged_message'] = True
                 self.plugins[result['plugin_id']].main(
                     TelegramApi(self.message, self.misc, self.plugins, self.database, result['plugin_id']))
             return False
     if self.message['chat']['type'] == 'private':
         if self.plugin_check():
             return False
         db_selection = self.database.select("flagged_messages",
                                             ["plugin_id", "single_use", "message_id"],
                                             {"chat_id": chat_id, "currently_active": True})
         if db_selection:
             for result in db_selection:
                 message_id = result["message_id"]
                 if result['single_use']:
                     self.database.delete('flagged_messages',
                                          {'message_id': message_id,
                                           'chat_id': chat_id})
                 self.message['flagged_message'] = True
                 self.plugins[result['plugin_id']].main(
                     TelegramApi(self.message, self.misc, self.plugins, self.database, result['plugin_id'])
                 )
                 self.database.update("flagged_messages", {"currently_active": False},
                                      {"chat_id": chat_id})
             return False
     return True
Beispiel #12
0
def check_time_args():
    global extensions
    time_args = database.select("flagged_time",
                                ["plugin_id", "time", "plugin_data"])
    for argument in time_args:  # See if any plugins want to be activated at this time
        if argument['time'] <= time.time():
            plugin_id = argument['plugin_id']
            plugin_data = json.loads(
                argument['plugin_data']) if argument['plugin_data'] else None
            tg = TelegramApi(misc,
                             database,
                             plugin_id,
                             plugin_data=plugin_data)
            plugins[plugin_id].main(tg)
            database.delete("flagged_time", argument)
Beispiel #13
0
 def check_pm_parameters(self):
     """
     Retrieves payload from pm_parameters and sends to relevant plugin
     https://core.telegram.org/bots/#deep-linking
     """
     if 'text' not in self.message:
         return
     match = re.findall("^/start (.*)", self.message['text'])
     if match:
         self.message['pm_parameter'] = match[0]
         self.database.query('SELECT plugin_name FROM pm_parameters WHERE parameter="{}"'.format(match[0]))
         query = self.database.store_result()
         result = query.fetch_row()
         for plugin in result:
             api_object = TelegramApi(self.database, self.get_me, plugin[0], self.config, self.http, self.message)
             self.plugins[plugin[0]].main(api_object)
         return True if result else False
Beispiel #14
0
 def check_db_reply(self):
     chat_id = self.message['chat']['id']
     message_id = self.message['reply_to_message']['message_id']
     db_selection = self.database.select("flagged_messages",
                                         ["DISTINCT plugin_id", "user_id", "single_use", "currently_active",
                                          "plugin_data"],
                                         {"message_id": message_id, "chat_id": chat_id})
     if db_selection:
         for result in db_selection:
             if result['user_id'] and result['user_id'] != self.message['from']['id']:
                 return True
             if result['single_use']:
                 self.database.delete('flagged_messages', {'message_id': message_id, 'chat_id': chat_id})
             self.message['flagged_message'] = True
             if result['plugin_data']:
                 plugin_data = json.loads(result['plugin_data'])
             else:
                 plugin_data = None
             self.plugins[result['plugin_id']].main(
                 TelegramApi(self.misc, self.database, result['plugin_id'], self.message, plugin_data))
         return True
Beispiel #15
0
 def get_update(self):  # Gets new messages and sends them to plugin_handler
     url = "{}{}getUpdates?offset={}".format(self.misc['base_url'], self.misc['token'], self.update_id)
     response = util.fetch(url, self.misc['session'])
     try:
         response = response.json()
     except AttributeError:
         time.sleep(5)
         return
     if response['ok']:
         try:
             self.update_id = response['result'][-1]['update_id'] + 1
         except IndexError:
             time.sleep(self.config.sleep)
             return
         with concurrent.futures.ThreadPoolExecutor(max_workers=5) as e:
             for i in response['result']:
                 if self.time - int(i['message']['date']) <= 180000:
                     e.submit(self.route_message, TelegramApi(i['message'], self.misc))
         time.sleep(self.config.sleep)
     else:
         print('Error fetching new messages:\nCode: {}'.format(response['error_code']))
         time.sleep(self.config.sleep)
Beispiel #16
0
 def run_plugin(self, plugin_name, plugin_module, message):
     """
     Inits a plugin with its own DB and commits/closes it after.
     Wrapped for concurrent.futures
     """
     database = MySQLdb.connect(**self.config['DATABASE'])
     api_object = TelegramApi(database, self.get_me, plugin_name, self.config, self.http, message)
     try:
         plugin_module.main(api_object)
     except Exception:
         admin_list = self.config['BOT_CONFIG']['admins'].split(',')
         for admin_id in admin_list:
             message = "<code>{}</code>".format(traceback.format_exc())
             api_object.forward_message(admin_id)
             api_object.send_message(message, chat_id=admin_id)
     database.commit()
     database.close()
Beispiel #17
0
 def check_db_pm(self):
     if self.plugin_check():
         return
     chat_id = self.message['chat']['id']
     db_selection = self.database.select("flagged_messages",
                                         ["DISTINCT plugin_id", "single_use", "message_id", "plugin_data"],
                                         {"chat_id": chat_id, "currently_active": True})
     if db_selection:
         for result in db_selection:
             message_id = result["message_id"]
             if result['single_use']:
                 self.database.delete('flagged_messages',
                                      {'message_id': message_id,
                                       'chat_id': chat_id})
             if result['plugin_data']:
                 plugin_data = json.loads(result['plugin_data'])
             else:
                 plugin_data = None
             self.message['flagged_message'] = True
             self.database.update("flagged_messages", {"currently_active": False},
                                  {"chat_id": chat_id})
             self.plugins[result['plugin_id']].main(
                 TelegramApi(self.misc, self.database, result['plugin_id'], self.message, plugin_data)
             )