Esempio n. 1
0
    def delete(self, secret):
        '''Delete stream with specified key
            Args:
                secret(str):    Stream key (secret)
            Returns:
                bool:           Operation result
        '''
        # Удаляем поток даже если в кэше не было
        def deleteStreamSQL():
            with Database().getConnection().cursor() as cursor:
                sql = "DELETE FROM "+STREAMS_TABLE+" WHERE secret=%s"
                cursor.execute(sql, (secret,))
                Database().getConnection().commit()
                return cursor.rowcount > 0

        res = Database().execute(deleteStreamSQL)
        if res['status'] is False:
            log_main.error("Error deleting a stream")
            return None

        # Log operation
        user_id = None
        stream_name = "?"
        if secret in self.__streams:
            user_id = self.__streams[secret].user_id
            stream_name = self.__streams[secret].name
        log_main.info('Deleted stream "%s" for user %s with key: %s', stream_name, user_id, secret)

        # Remove from the cache
        del self.__streams[secret]
        return True
Esempio n. 2
0
    def __init__(self, host=None, user=None, password=None, database=None):
        if host is None or user is None or password is None or database is None:
            log_main.error("Error when initiating the database connection — not all connection parameters were specified")
            raise BotUnexpected

        self.__host = host
        self.__user = user
        self.__password = password
        self.__database = database
        self.__threadLocal = threading.local() # Thread-unique variable, initiated only once
        if self.connect():
            log_main.info("The connection to the database is established")
Esempio n. 3
0
 def connect(self): #, init=False):
     '''Establish a database connection'''
     log_main.debug('Connecting to the database in the stream "%s"…', threading.current_thread().name)
     try:
         self.__threadLocal.connection = MySQLdb.Connect(host=self.__host, user=self.__user, password=self.__password,
                                                         db=self.__database, charset=CHARSET)
         return True
     except MySQLdb.OperationalError:
         log_main.info("Failed to connect to the database")
         return False
     except Exception: # pylint: disable=broad-except
         log_main.exception("An unexpected error occurred while connecting to the database")
         return False
Esempio n. 4
0
    def add(self, user_id, name):
        '''Create new stream for given telegram user
            Args:
                user_id(str):   Telegram user ID (chat ID)
                name(str):      The name of the stream
            Returns:
                str:            Stream key (secret)
        '''
        # Generate a unique stream key
        alphabet = "0123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"
        converter = baseconv.BaseConverter(alphabet)
        codeLength = 32
        secret = converter.encode(uuid.uuid4().int)[0:codeLength]

        # Check the uniqueness
        if secret in self.__streams:
            log_main.error("Uniqueness error when adding a stream: %s", secret)
            return None

        # Add stream
        stream_status = int(StreamStatus.active)
        def addStreamSQL():
            '''Get all existing streams from database'''
            with Database().getConnection().cursor() as cursor:
                sql = "INSERT INTO " + STREAMS_TABLE + " (user_id, secret, name, status) VALUES (%s, %s, %s, %s)"
                cursor.execute(sql, (user_id, secret, name, stream_status))
                Database().getConnection().commit()
                return Database().getConnection().insert_id()

        res = Database().execute(addStreamSQL)
        if res['status'] is False:
            log_main.error("Error when adding a new stream")
            return None

        # Add to cache
        stream_id = res['result']
        if stream_id is not None:
            stream = Stream(stream_id, user_id, secret, name, stream_status)
            self.__streams[secret] = stream
            log_main.info('Added new stream "%s" for user %s with the key: %s', name, user_id, secret)
            return secret

        # If it was not added
        raise Exception("Couldn't add new stream")
Esempio n. 5
0
 def reconnect(self):
     '''(re)Try to establish a connection to the database until the connection is established'''
     attempt = 1
     max_delay = 60
     while True:
         log_main.info("Attempt #%s to connect to the database…", attempt)
         if self.connect():
             break
         timeout = min(attempt, max_delay) # Waiting time increases after every attempt
         log_main.info("Waiting %s sec until the next connection attempt", timeout)
         attempt += 1
         time.sleep(timeout) # Waiting until reconnect
     log_main.info("The connection to the database is established")
Esempio n. 6
0
 def _handle_send_get(secret, message):
     stream = Streams().get(secret)
     if stream is not None:
         fullname = "%s (%s)" % (secret,
                                 stream.name) if stream.name else secret
         if stream.status == StreamStatus.active:
             name = "%s: " % stream.name if stream.name else ""
             self._bot.send_message(stream.user_id,
                                    "%s%s" % (name, message))
             log_main.info("SEND to %s: %s", fullname, message)
         elif stream.status == StreamStatus.stopped:
             log_main.info("IGNORED (stopped) to %s: %s", fullname,
                           message)
         else:
             log_main.info("IGNORED (unknown) to %s: %s", fullname,
                           message)
     else:
         log_main.info("Attempt to send to a nonexistent stream: %s",
                       secret)
     return 'ok'  # Always return ok
Esempio n. 7
0
    def __init__(self, base_url, is_local=None):
        self.__base_url = base_url
        self.__webhook_path = Config().webhook_path
        self.__webhook_url = "%s%s" % (base_url, self.__webhook_path)
        self.__is_local = is_local
        self.__bot_token = Config().bot_token

        log_main.info("Starting BackendServer…")
        # Some debug info (for local dev mode )
        if is_local:
            print("Base URL: %s" % self.__base_url)
            print("Webhook URL: %s" % self.__webhook_url)
            print("Bot token: %s" % self.__bot_token)

        # Initializing Flask
        self.init_flask()

        # Checking and initializing the database connection
        status, description = Database.checkConnection(Config().db_host,
                                                       Config().db_user,
                                                       Config().db_password,
                                                       Config().db_database)
        if not status:
            msg = "Database connect failed\n%s" % description
            self._flask_app.logger.error(msg)  # pylint: disable=no-member
            log_main.error(msg)
            sys.exit()
        Database(Config().db_host,
                 Config().db_user,
                 Config().db_password,
                 Config().db_database)

        # Init streams
        log_main.info("Loading streams…")
        Streams()
        log_main.info("Streams loaded")

        # Init telebot
        self.init_telebot()
Esempio n. 8
0
"""The entry point"""
from core.botLogger import log_main
from config import Config
from server import BackendServer

url = Config().base_url
if __name__ == "__main__":
    log_main.info('The server starts directly (local/development mode)')
    is_local = True
else:
    log_main.info('The server starts in uWSGI worker mode (production)')
    is_local = False

server = BackendServer(url, is_local=is_local)
app = server.getApp()

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8443)