Пример #1
0
class TelegramBotWrapper:
    def __init__(self, token) -> None:
        self.chat_ids = set()
        self.bot = TeleBot(token)

        for handler_dict in self.__build_handler_dicts():
            self.bot.add_message_handler(handler_dict)

    def __build_handler_dicts(self):
        defaults = {
            'commands': None,
            'regexp': None,
            'func': None,
            'content_types': ['text']
        }
        handlers_info_list = [{
            'handler': self._subscribe,
            'commands': ['subscribe']
        }, {
            'handler': self._unsubscribe,
            'commands': ['unsubscribe']
        }]
        handler_dicts = []

        for h_info in handlers_info_list:
            handler_dicts.append(
                TeleBot._build_handler_dict(
                    h_info['handler'], **{
                        **defaults, 'commands': h_info['commands']
                    }))
        return handler_dicts

    def _subscribe(self, message):
        self.chat_ids.add(message.chat.id)
        self.bot.send_message(message.chat.id,
                              'Successfully subscribed on updates.')

    def _unsubscribe(self, message):
        self.chat_ids.remove(message.chat.id)
        self.bot.send_message(message.chat.id,
                              'Successfully unsubscribed from updates.')

    def start(self):
        self.bot.polling()

    def stop(self):
        self.bot.stop_bot()

    def notify(self, message):
        for chat_id in self.chat_ids:
            self.bot.send_message(chat_id, message)
class TelegramBot:
    def __init__(self, token: str, mongo: MongoDB):
        self._mongo = mongo
        self._bot = TeleBot(token)

        @self._bot.message_handler(commands=['start', 'help'])
        def send_welcome(message):
            try:
                self._mongo.update_telegram_id(message.chat.username,
                                               message.chat.id)
                self._bot.reply_to(message, "Howdy, how are you doing?")
            except Exception as e:
                self._bot.reply_to(message, str(e))

    def set_bot(self, bot: TeleBot):
        self._bot = bot

        @self._bot.message_handler(commands=['start', 'help'])
        def send_welcome(message):
            try:
                self._mongo.update_telegram_id(message.chat.username,
                                               message.chat.id)
                self._bot.reply_to(message, "Howdy, how are you doing?")
            except Exception as e:
                self._bot.reply_to(message, str(e))

    def get_bot(self):
        return self._bot

    def close(self):
        self._bot.stop_polling()
        self._bot.stop_bot()

    def start(self):
        self._bot.polling()

    def send_message(self, recipient: int, message: str):
        self._bot.send_message(recipient, message)
Пример #3
0
class TgBot(threading.Thread):
    def loadCommandConfig(self):
        pass

    def loadPersonConfig(self):
        persons = {}
        return persons

    def __init__(self, config, admins, tunnels, loopDelay=0.1, debug=False):
        super(TgBot, self).__init__()
        self.debug = debug
        self.stopped = Event()
        self.loopDelay = loopDelay

        self.admins = admins
        self.tunnels = tunnels
        self.config = config
        self.botUserName = config['botUserName']
        self.bot = TeleBot(config['token'])

        self.commands = [
            # AddAdmin(bot=self, cmd=['add-admin']),
            # Alarm('alarm', time.time())
            Bind(bot=self, cmd=['b', 'bind']),
            ListBind(bot=self, cmd=['lb', 'listbind', 'list-bind']),
            Toggle(bot=self, cmd=['t', 'toggle']),
            ListToggle(bot=self, cmd=['lt', 'listtoggle', 'list-toggle']),
            UnBind(bot=self, cmd=['ub', 'unbind', 'un-bind'])
        ]
        self.persons = self.loadPersonConfig()

    def sendMessage(self, _id, _msg, parse_mode=None):
        self.bot.send_message(chat_id=_id, text=_msg, parse_mode=parse_mode)

    def replyTo(self, msg, _msg):
        self.bot.reply_to(msg, _msg)

    def listbind_handler(self, message):
        print(message)

    def handler(self, msg):
        for each in msg:
            try:
                _from = each.from_user
                _chat = each.chat
                if each.text and each.text.startswith('#'):
                    _text = each.text
                    for tunnel in getMatchTunnels(self.tunnels, tgId=_chat.id):
                        if tunnel.tg['toggle']:
                            name = _from.username or _from.first_name or _from.last_name
                            message = '[Anonymous]: {0}'.format(
                                _text[2:]) if _text.startswith(
                                    '##') else '[{0}]: {1}'.format(
                                        name, _text[1:])
                            tunnel.tk['queue'].put(message)
                if self.debug:
                    print(each)
            except Exception as e:
                if self.debug:
                    traceback.print_exc()

    def queueHandler(self):
        while not self.stopped.wait(self.loopDelay):
            for each in self.tunnels:
                tg = each.tg
                while not tg['queue'].empty() and tg['toggle']:
                    chatId = tg['id']
                    msg = tg['queue'].get()
                    try:
                        if '<img' in msg:
                            link = re.search('src=\".*?\"', msg).group(0)[5:-1]
                            if '.gif' in msg:
                                self.bot.send_document(chatId, link)
                            else:
                                self.bot.send_photo(chatId, link)
                        elif '</' in msg:
                            self.bot.send_message(chatId,
                                                  msg,
                                                  parse_mode='HTML')
                        else:
                            self.bot.send_message(chatId,
                                                  msg,
                                                  parse_mode='Markdown')
                    except Exception as e:
                        self.bot.send_message(chatId, msg)
                        if self.debug:
                            traceback.print_exc()

    def start(self):
        super(TgBot, self).start()
        for cmd in self.commands:
            cmd.register()
        self.bot.set_update_listener(self.handler)
        thread = threading.Thread(target=self.queueHandler)
        thread.start()

    def run(self):
        while not self.stopped.wait(self.loopDelay):
            try:
                self.bot.polling(none_stop=False)
            except:
                if self.debug:
                    traceback.print_exc()

    def stop(self):
        self.bot.stop_bot()
        self.stopped.set()
Пример #4
0
class BaseTelegram:
    """Telegram is an alternative UI to the web API for the project. It works via telegram commands.
    If you need just to send a message to the project channel / group, use core.send_telegram_message()"""
    def __init__(self, app: App):
        self.app = app
        self.bot: Optional[TeleBot] = None
        self.is_started = False
        self.admins: list[int] = []

    @synchronized
    def start(self) -> Optional[str]:
        """
        Telegram bot can be started only if these bot settings are set:
        - telegram_token
        - telegram_admins
        - telegram_polling
        """
        telegram_token = self.app.dconfig.get("telegram_token")
        telegram_polling = self.app.dconfig.get("telegram_polling")

        try:
            self.admins = []
            for admin in self.app.dconfig.get("telegram_admins",
                                              "").split(","):
                admin = admin.strip()
                if admin:
                    self.admins.append(int(admin))
        except Exception as e:
            self.app.dlog("telegram_parse_admins", {"error": str(e)})
            return f"telegram_parse_admins: {str(e)}"

        if telegram_token and telegram_polling and self.admins:
            Thread(target=self._start, args=(telegram_token, )).start()
            return None
        else:
            return "there are some unset configs: telegram_token or telegram_polling or telegram_admins"

    def _start(self, token: str):
        try:
            self.bot = TeleBot(token, skip_pending=True)
            self._init_base_commands()
            self.init_commands()
            self.is_started = True
            self.app.logger.debug("telegram started")
            self.bot.polling(none_stop=True)

        except Exception as e:
            self.is_started = False
            self.app.dlog("telegram_polling", {"error": str(e)})
            self.app.logger.error(f"telegram polling: {str(e)}")

    @synchronized
    def stop(self):
        self.is_started = False
        if self.bot:
            self.bot.stop_bot()
        self.app.logger.debug("telegram stopped")

    def _init_base_commands(self):
        @self.bot.message_handler(commands=["start", "help"])
        @self.auth(admins=self.admins, bot=self.bot)
        def help_handler(message: Message):
            self._send_message(message.chat.id,
                               self.app.app_config.telegram_bot_help)

        @self.bot.message_handler(commands=["ping"])
        @self.auth(admins=self.admins, bot=self.bot)
        def ping_handler(message: Message):
            text = message.text.replace("/ping", "").strip()
            self._send_message(message.chat.id, f"pong {text}")

    def init_commands(self):
        pass

    def _send_message(self, chat_id: int, message: str):
        for text in split_string(message, 4096):
            self.bot.send_message(chat_id, text)  # type:ignore

    @staticmethod
    def auth(*, admins: list[int], bot: TeleBot):
        def outer(func):
            @functools.wraps(func)
            def wrapper(message: Message):
                if message.chat.id in admins:
                    return func(message)
                else:
                    bot.send_message(message.chat.id, "Who are you?")

            return wrapper

        return outer
Пример #5
0
class Telegram:
    """Telegram is an alternative UI to the web API for the project. It works via telegram commands.
    If you need just to send a message to the project channel / group, use system_service.send_telegram_message()"""

    def __init__(self, core: Core):
        self.core = core
        self.bot: Optional[TeleBot] = None
        self.is_started = False

    @synchronized
    def start(self):
        """
        Telegram bot can be started only if these bot settings are set:
        - telegram_token
        - telegram_admins
        - telegram_polling
        """
        app_bot = self.core.system_service.get_bot()
        if app_bot.telegram_token and app_bot.telegram_admins and app_bot.telegram_polling:
            Thread(target=self._start).start()
            return True

    def _start(self):
        try:
            self.bot = TeleBot(self.core.system_service.get_bot().telegram_token, skip_pending=True)
            self._init_commands()
            self.is_started = True
            self.core.log.debug("telegram started")
            self.bot.polling(none_stop=True)
        except Exception as e:
            self.is_started = False
            self.core.log.error(f"telegram polling: {str(e)}")

    @synchronized
    def stop(self):
        self.is_started = False
        if self.bot:
            self.bot.stop_bot()
        self.core.log.debug("telegram stopped")

    def _init_commands(self):
        @self.bot.message_handler(commands=["start", "help"])
        @auth(admins=self.core.system_service.get_bot().telegram_admins, bot=self.bot)
        def help_handler(message: Message):
            result = """
/workers - List all workers
/start_worker ${worker_name} - Start the worker
/stop_worker ${worker_name} - Start the worker
            """
            self._send_message(message.chat.id, result)

        @self.bot.message_handler(commands=["ping"])
        @auth(admins=self.core.system_service.get_bot().telegram_admins, bot=self.bot)
        def ping_handler(message: Message):
            text = message.text.replace("/ping", "").strip()
            self._send_message(message.chat.id, f"pong {text}")

        @self.bot.message_handler(commands=["workers"])
        @auth(admins=self.core.system_service.get_bot().telegram_admins, bot=self.bot)
        def workers_handler(message: Message):
            result = ""
            for w in self.core.db.worker.find({}, "name"):
                result += f"{w.name}, source={w.source}, started={w.started}\n"
            self._send_message(message.chat.id, result)

        @self.bot.message_handler(commands=["start_worker"])
        @auth(admins=self.core.system_service.get_bot().telegram_admins, bot=self.bot)
        def start_handler(message: Message):
            chat_id = message.chat.id
            worker_name = message.text.replace("/start_worker", "").strip()
            if not worker_name:
                return self._send_message(chat_id, "usage: /start_worker ${worker_name}")

            worker = self.core.db.worker.find_one({"name": worker_name})
            if worker:
                self.core.worker_service.start_worker(worker.id)
                return self._send_message(chat_id, "worker was started")
            else:
                self._send_message(message.chat.id, "worker was not found")

        @self.bot.message_handler(commands=["stop_worker"])
        @auth(admins=self.core.system_service.get_bot().telegram_admins, bot=self.bot)
        def stop_handler(message: Message):
            chat_id = message.chat.id
            worker_name = message.text.replace("/stop_worker", "").strip()
            if not worker_name:
                return self._send_message(chat_id, "usage: /stop_worker ${worker_name}")

            worker = self.core.db.worker.find_one({"name": worker_name})
            if worker:
                self.core.worker_service.stop_worker(worker.id)
                return self._send_message(chat_id, "worker was stopped")
            else:
                return self._send_message(chat_id, "worker was not found")

    def _send_message(self, chat_id: int, message: str):
        for text in split_string(message, 4096):
            self.bot.send_message(chat_id, text)  # type:ignore