Beispiel #1
0
class AssisBot:
    def __init__(self):
        config = ConfigObj(fileInit)
        self.Listen = False
        self.IA = AssisIA()
        self.apikey = config['bot']['apikey']
        self.name = config['bot']['name']
        self.adminChatId = config['bot']['adminChatId']
        self.updatesDelay = float(config['bot']['delay'])
        self.Telegram = TelegramBot(self.apikey)
        self.Telegram.update_bot_info().wait()
        self.ListenerUsers = threading.Thread(target=self.listeningUser,
                                              daemon=True)

    def changeApiKey(self, apikey):
        self.Telegram = TelegramBot(apikey)
        self.Telegram.update_bot_info().wait()

    def startToListen(self):
        self.Listen = True
        if (not self.ListenerUsers.is_alive()):
            self.ListenerUsers.start()
        logging.info('Corriendo programa: ' +
                     str(self.ListenerUsers.is_alive()))

    def stopToListen(self):
        if self.ListenerUsers.is_alive():
            self.Listen = False
            logging.info('Deja de escuchar')
        else:
            logging.info("No hay programa que detener")

    def listeningUser(self):
        logging.info("Inicio subproceso de escucha")
        updates = self.Telegram.get_updates().wait()
        last_updateId = (updates[-1].update_id) if (len(updates) > 0) else 0
        while True:
            try:
                updates = self.Telegram.get_updates(offset=last_updateId + 1,
                                                    timeout=100).wait()
                logging.info("Updates: " + str(len(updates)))
                if len(updates) > 0:
                    if self.Listen:  #debería responder? (Es una bandera)
                        res = self.IA.getResponse(updates[0])
                        if (res['Options'] == False):
                            self.Telegram.send_message(
                                updates[0].message.chat.id,
                                res['Text']).wait()
                            if (res['Image']):
                                fp = open(res['ImagePath'], 'rb')
                                file_info = InputFileInfo(
                                    'NOCData.png', fp, 'image/png')
                                chart = InputFile('photo', file_info)
                                self.Telegram.send_photo(
                                    updates[0].message.chat.id,
                                    photo=chart).wait()
                            if (res['Document']):
                                doc = open(res['DocumentPath'], 'rb')
                                file_info = InputFileInfo(
                                    'Details.csv', doc, 'csv')
                                document = InputFile('document', file_info)
                                self.Telegram.send_document(
                                    updates[0].message.chat.id,
                                    document=document).wait()

                        else:
                            keyboard = res['Options']
                            reply_markup = ReplyKeyboardMarkup.create(keyboard)
                            msg = 'Seleccione el grupo para ver los detalles'
                            self.Telegram.send_message(
                                updates[0].message.chat.id,
                                msg,
                                reply_markup=reply_markup).wait()

                        dataLoadDelta = (datetime.now() - datetime.strptime(
                            res['UpdateTime'], '%a %b %d %H:%M:%S %Y'))
                        dataLoadTimeHours = dataLoadDelta.seconds / 3600
                        maxHours = 3
                        if (dataLoadTimeHours >= maxHours):
                            msg = "Carga de Datos igual a " + str(
                                dataLoadDelta
                            ) + " horas. Revisar BD desactualizada"
                            self.Telegram.send_message(self.adminChatId,
                                                       msg).wait()
                            msg = "Última actualización mayor a 02:30 horas. BD desactualizada, contactar a Administrador"
                            self.Telegram.send_message(
                                updates[0].message.chat.id, msg).wait()

                    logging.info('Nuevo mensaje: ' + updates[0].message.text)
                    last_updateId = updates[0].update_id
            except Exception as ex:
                template = "Un error del tipo {0} ha ocurrido, por favor contactar Administrador. Detalles:\n{1!r}"
                excepMsg = template.format(type(ex).__name__, ex.args)
                logging.error("Error generado en el Bot")
                logging.error(excepMsg)
                if (
                        type(ex).__name__ == "FileNotFoundError"
                ):  #Error no se ha encontrado el archivo, contestar con el error
                    self.Telegram.send_message(updates[0].message.chat.id,
                                               excepMsg).wait()
                    self.Telegram.send_message(self.adminChatId,
                                               excepMsg).wait()
                    last_updateId = updates[0].update_id
                time.sleep(10)
Beispiel #2
0
class CloudLog(object):
    """
    Lets you duplicate console logs in a locally stored file, folder on Dropbox and
    receive updates in a Telegram chat.
    """

    def __init__(self, root_path, dropbox_token=None, telegram_token=None, telegram_chat_id=None):
        """
        Initialises a new logger instance.

        Parameters
        ----------
        root_path           :
                              Local log root path.
        dropbox_token       :
                              Dropbox access token.
        telegram_token      :
                              Telegram Bot API access token.
        telegram_chat_id    :
                              Telegram chat ID.
        """
        self.telegram_chat_id = int(telegram_chat_id) if telegram_chat_id is not None else None
        self.cloud_log_writer = dropbox.Dropbox(dropbox_token) if dropbox_token is not None else None
        self.notification_bot = TelegramBot(telegram_token) if telegram_token is not None else None

        self.log_file = time.strftime('%Y-%m-%d_%H-%M-%S') + '_log.txt'
        self.root = root_path
        os.makedirs(root_path, exist_ok=True)

    def __call__(self, string):
        """
        Logs the value to console and appends the same string to the log file.

        Parameters
        ----------
        string  : string
                  Value to be logged.
        """
        print(string)
        with open(os.path.join(self.root, self.log_file), 'a') as file:
            file.write(string + '\n')

    def add_plot(self, notify=False, caption=None):
        """
        Saves current `pyplot` plot as a .png, uploads it to Dropbox and optionally notifies via Telegram chat.

        Parameters
        ----------
        notify  :
                  Flag indicating if we need to send a Telegram notification.
        caption :
                  Optional plot caption.
        """
        plot_file = time.strftime('%Y-%m-%d_%H-%M-%S') + '.png'
        plot_path = os.path.join(self.root, plot_file)
        pyplot.savefig(plot_path)

        self.cloud_upload_plot(plot_file)
        if notify:
            self.bot_send_plot(plot_file, caption)

    def sync(self, notify=False, message=None):
        """
        Synchronises local log with Dropbox.

        Parameters
        ----------
        notify  :
                  Flag indicating if we need to send a Telegram notification.
        message :
                  Optional notification message.
        """
        self.cloud_sync_log()
        if notify:
            self.bot_send_message(message)
            self.bot_send_log()

    # Dropbox routines

    def cloud_sync_log(self):
        """
        Syncs local log with the one in Dropbox App's folder (e.g. overwrtites it).
        """
        if self.cloud_log_writer is None: return

        with open(os.path.join(self.root, self.log_file), 'rb') as file:
            try:
                self.cloud_log_writer.files_upload(
                    file.read(),
                    '/' + self.log_file,
                    mode=dropbox.files.WriteMode('overwrite', None)
                )
            except Exception as e:
                self('Failed to sync log: ' + str(e))
                pass

    def cloud_upload_plot(self, filename):
        """
        Uploads plot to Dropbox app's folder.

        Parameters
        ----------
        filename    :
                      Plot filename or relative path.
        """
        if self.cloud_log_writer is None: return

        plot_path = os.path.join(self.root, filename)
        with open(plot_path, 'rb') as file:
            try:
                self.cloud_log_writer.files_upload(
                    file.read(),
                    '/' + filename,
                    mode=dropbox.files.WriteMode('overwrite', None)
                )
            except Exception as e:
                self('Failed to upload plot: ' + str(e))
                pass

    # Telegram routines

    def bot_send_message(self, message, mode="Markdown"):
        """
        Sends a text message to default Telegram chat.

        Parameters
        ----------
        message :
                  Message to send.
        mode    :
                  Message parsing mode. Defaults to `Markdown`.
        """
        if self.notification_bot is None or self.telegram_chat_id is None: return

        try:
            self.notification_bot.send_message(
                self.telegram_chat_id,
                message,
                parse_mode=mode
            ).wait()
        except Exception as e:
            self('Failed to send notification: ' + str(e))
            pass

    def bot_send_plot(self, filename, caption=None):
        """
        Sends plot saved as `filename` to default Telegram chat with optional caption.

        Parameters
        ----------
        filename  :
                    Plot filename or path relative to current directory.
        caption   :
                    Optional plot caption.
        """
        if self.notification_bot is None or self.telegram_chat_id is None: return

        plot_path = os.path.join(self.root, filename)
        with open(plot_path, 'rb') as file:
            try:
                self.notification_bot.send_photo(
                    self.telegram_chat_id,
                    InputFile('photo', InputFileInfo(filename, file, 'image/png')),
                    caption=caption,
                    disable_notification=True
                ).wait()
            except Exception as e:
                self('Failed to send plot: ' + str(e))
                pass

    def bot_send_log(self):
        """
        Sends current log file to default Telegram chat. Does not notify the user about this message, send a separate
        message if you want the notification to hit user's device.
        """
        if self.notification_bot is None or self.telegram_chat_id is None: return

        with open(os.path.join(self.root, self.log_file), 'rb') as file:
            try:
                self.notification_bot.send_document(
                    self.telegram_chat_id,
                    InputFile('document', InputFileInfo(self.log_file, file, 'text/plain')),
                    disable_notification=True
                ).wait()
            except Exception as e:
                self('Failed to send log: ' + str(e))
                pass