コード例 #1
0
ファイル: bot.py プロジェクト: KaikyuLotus/kitsu-ultimate
    def _update_elaborator(self, update: dict):
        self.offset = update["update_id"] + 1
        infos = Infos(self, update)

        if infos.is_edited_message or infos.is_channel_post or infos.is_edited_channel_post:
            log.d(f"Ignoring update of type {infos.update_type}")
            return

        if not self._callback:
            self.waiting_data = {}

        if infos.user and not infos.message.is_command:
            if infos.user.is_bot_owner and self._callback:
                log.d(f"Calling callback {self._callback.__name__}")
                self._callback = self._callback(infos)
                return
        elif infos.user:
            if infos.user.is_bot_owner and self._callback:
                if infos.message.command == "cancel":
                    self._callback = None
                    infos.reply("Operation cancelled.")
                    return
            if infos.user.is_bot_owner and infos.message.command == "test":
                elaborator.elaborate_json_backup(infos)

        if infos.message.is_document:
            elaborator.elaborate_file(infos)
        elif infos.message.is_command:
            mongo_interface.increment_read_messages(self.bot_id)
            self._command_elaborator(infos)
        elif infos.is_callback_query:
            self._callback_elaborator(infos)
        elif infos.is_message:
            mongo_interface.increment_read_messages(self.bot_id)
            self._message_elaborator(infos)
コード例 #2
0
def elaborate(infos: Infos):
    if not infos.message.is_text:
        return

    for t_type_elaborator in _t_type_elaborators:
        triggers = mongo_interface.get_triggers_of_type(
            infos.bot.bot_id, t_type_elaborator, infos.db.language)
        for trigger in triggers:
            if "\\@" in trigger.trigger:
                trigger.trigger, identifier = trigger.trigger.split("\\@")
                if identifier.lower() == "owner":
                    identifier = str(infos.bot.owner_id)
                if identifier.isnumeric():
                    if infos.user.uid != int(identifier):
                        continue

            if _t_type_elaborators[t_type_elaborator](infos, trigger):
                return

    if infos.is_to_bot:
        complete_dialog_sec(infos, "generic")
        bot_utils.forward_to_owner(infos)

    if infos.bot.automs_enabled:
        log.d("Autom enabled, elaborating...")
        if randint(_autom_min, _autom_max) == _autom_max:
            complete_dialog_sec(infos, "automatics")
            return
コード例 #3
0
def get_stats(bot_id: int) -> Stats:
    stats = Stats.from_json(_get_db().bot_stats.find_one({"bot_id": bot_id}))
    if not stats:
        log.d(f"Registering stats for bot {bot_id}")
        stats = Stats(bot_id)
        _get_db().bot_stats.insert_one(dict(stats))
    return stats
コード例 #4
0
ファイル: test_log.py プロジェクト: ujiro99/auto_logger
    def test_d__byte(self):
        out = io.StringIO()
        log.logger.addHandler(StreamHandler(stream=out))
        log.set_level(log.Level.DEBUG)

        log.d(b'message')
        self.assertEqual(out.getvalue(), "message\n")
コード例 #5
0
ファイル: bot.py プロジェクト: KaikyuLotus/kitsu-ultimate
 def run(self):
     self.running = True
     self.start_time = time.time()
     log.d("Starting update loop")
     methods.send_message(self.token, self.owner_id,
                          "Master, i just booted up!")
     while self.running:
         self._updater()
コード例 #6
0
ファイル: methods.py プロジェクト: KaikyuLotus/kitsu-ultimate
def execute(token: str,
            method: str,
            params: dict = None,
            post_data: dict = None):
    try:
        if post_data is not None:
            log.d(f"POST request to {_base_url}/bot???/{method}")
            res = _session.post(f"{_base_url}/bot{token}/{method}",
                                params=params,
                                files=post_data,
                                timeout=_timeout)
        else:
            # log.d(f"GET request to {_base_url}/bot???/{method}")
            res = _session.get(f"{_base_url}/bot{token}/{method}",
                               params=params,
                               timeout=_timeout)
    except Timeout as err:
        log.e(f"Timed out request to {_base_url}/bot???/{method}: {err}")
        raise TelegramException(
            f"Timed out request to {_base_url}/bot???/{method}: {err}",
            "Timeout", [key for key in (params if params else [])],
            [params[key] for key in (params if params else [])])

    status_code = res.status_code

    if status_code == 200:
        return res.json()["result"]

    error = f"{status_code} while executing {method}"
    try:
        args = [
            res.json()["description"], error,
            [key for key in (params if params else [])],
            [params[key] for key in (params if params else [])]
        ]
    except JSONDecodeError:
        args = [
            res.text, error, [key for key in (params if params else [])],
            [params[key] for key in params]
        ]

    if status_code == 409:
        raise Conflict(*args)

    if status_code == 404:
        raise NotFound(*args)

    if status_code == 403:
        raise Forbidden(*args)

    if status_code == 401:
        raise Unauthorized(*args)

    if status_code == 400:
        raise BadRequest(*args)

    raise TelegramException(*args)
コード例 #7
0
ファイル: bot.py プロジェクト: KaikyuLotus/kitsu-ultimate
 def _load_data(self):
     log.d("Getting bot data from mongo")
     bot_data = mongo_interface.get_bot_data(self.token)
     self.owner_id = int(bot_data["owner_id"])
     self.clean_start = bot_data["clean_start"]
     self.automs_enabled = bot_data[
         "automs_enabled"] if "automs_enabled" in bot_data else False
     self.custom_command_symb = bot_data[
         "command_symb"] if "command_symb" in bot_data else "/"
コード例 #8
0
def maker_master_command(infos: Infos):
    if not infos.user.is_maker_owner:
        return False

    if infos.message.command in _maker_master_commands:
        log.d(f"Maker owner issued command {infos.message.command}")
        _maker_master_commands[infos.message.command](infos)
        return True
    return False
コード例 #9
0
 def __call(self, cmd):
     """
     Execute a command.
     :param str cmd: Command string.
     :return: Return code of the command.
     :rtype int
     """
     log.d(" > %s" % cmd)
     return subprocess.call(cmd, shell=True)
コード例 #10
0
def owner_command(infos: Infos):
    if not infos.user.is_bot_owner:
        return False

    if infos.message.command in _owner_commands:
        log.d(f"Owner issued command {infos.message.command}")
        _owner_commands[infos.message.command](infos)
        return True

    return False
コード例 #11
0
def detach_bot(token: str):
    log.i(f"Detaching bot {token}")
    for bot in variables.attached_bots:
        log.d(bot.token)
        if bot.token != str(token):
            continue
        variables.attached_bots.remove(bot)
        log.i(f"Bot {token} detached")
        return bot.stop()
    log.i(f"Bot {token} not found")
コード例 #12
0
ファイル: merge.py プロジェクト: ujiro99/auto_logger
 def __files(self, dir_path):
     """
     Find files.
     :return: Iterator[str]
     """
     for root, dirs, files in os.walk(dir_path):
         for file in files:
             ret = os.path.join(root, file)
             log.d(ret)
             yield ret
     return
コード例 #13
0
def maker_command(infos: Infos):
    if not infos.bot.is_maker:
        return False

    if infos.message.command in _maker_commands:
        log.d(f"{infos.user.uid} issued maker "
              f"command {infos.message.command}")
        _maker_commands[infos.message.command](infos)
        return True

    return False
コード例 #14
0
ファイル: lotus.py プロジェクト: KaikyuLotus/kitsu-ultimate
def attach_bots(tokens: list):
    log.d(f"Attaching {len(tokens)} bots")
    if not isinstance(tokens, list):
        log.w("You must pass a list to attach_bots,"
              " operation cancelled.")
    else:
        for token in tokens:
            if is_bot_token(token):
                attach_bot_by_token(token)
            else:
                log.w(f"Invalid token {token} skipping.")
コード例 #15
0
ファイル: lotus.py プロジェクト: KaikyuLotus/kitsu-ultimate
def _load_modules():
    for module in config["modules"]["classes"]:
        try:
            if "." in module:
                class_name = module.split(".")[-1]
                module = ".".join(module.split(".")[:-1])
                LoadedModule = getattr(importlib.import_module(module), class_name)
                log.d(f"Loading module: {module} with class {LoadedModule}")
                load_module(LoadedModule)
        except Exception as err:
            log.e(err)
            traceback.print_exc()
コード例 #16
0
def get_dialog_probability(message: str) -> [Optional[int], str]:
    match = re.search(r"^{(\d{1,3})%}", message)
    prob: Optional[int] = None
    if match:
        prob = int(match.group(1))
        if prob < 1:
            prob = 1
        elif prob > 99:
            prob = 100
        message = message.replace(match.group(0), "")
        log.d(f"Found probability in string: {prob}")
    return prob, message
コード例 #17
0
ファイル: lotus.py プロジェクト: KaikyuLotus/kitsu-ultimate
def attach_bot_by_token(token: str):
    try:
        log.d(f"Attaching bot {token}")
        b = Bot(token)
        variables.attached_bots.append(b)
        log.d(f"Bot {b.bot_id} attached successfully")
        return True
    except Unauthorized:
        log.w(f"Wrong bot token: {token}")
    except TelegramException as error:
        error_name = error.__class__.__name__
        log.e(f"Exception '{error_name}' "
              f"while initializing the bot: {error}")
    return False
コード例 #18
0
def command(infos: Infos):

    triggers = mongo_interface.get_triggers_of_type(infos.bot.bot_id,
                                                    "command",
                                                    infos.db.language)
    for trigger in triggers:
        if elaborate_command(infos, trigger):
            return

    if infos.message.command in _commands:
        log.d(f"User issued command {infos.message.command}")
        _commands[infos.message.command](infos)
        return True
    return False
コード例 #19
0
def complete_dialog_sec(infos: Infos, section: str):
    log.d(f"Elaborating reply of section {section}")
    dialogs: List[Dialog] = mongo_interface.get_dialogs_of_section(
        infos.bot.bot_id, section, infos.db.language)

    if not dialogs:
        log.d(f"No dialogs set for section {section} lang {infos.db.language}")
        infos.bot.notify(
            f"No dialogs set for section {section} lang {infos.db.language}")
        return

    dialog = reply_parser.reply_choice(dialogs)

    infos.reply(dialog.reply, parse_mode=None)
    mongo_interface.increment_dialog_usages(dialog)
コード例 #20
0
def elaborate_triggers(triggers: dict, infos: Infos):
    log.d("Elaborating triggers....")
    mongo_interface.drop_triggers()

    final_trigger_list = []

    for t_type in triggers:
        if isinstance(triggers[t_type], str):
            triggers[t_type] = [
                trigger.replace("_", " ")
                for trigger in triggers[t_type].split()
            ]

        actual_triggers = triggers[t_type]
        section = None

        # TODO add support for importing commands
        if t_type == "equals":
            t_type = "equal"

        elif t_type == "contents":
            t_type = "content"

        elif t_type == "eteractions":
            t_type = "eteraction"

        elif t_type == "interactions":
            t_type = "interaction"

        else:
            if t_type in [
                    "bot_commands", "antispam time", "bot_comm_symbol",
                    "day_parts", "notte", "giorno", "admin_actions"
            ]:
                continue

            section = t_type
            t_type = "interaction"

        for trigger in actual_triggers:
            trigger = update_dummies(trigger)
            n_t = Trigger(t_type, trigger, trigger if not section else section,
                          infos.bot.bot_id, infos.db.user.language, 0)
            print(dict(n_t))
            final_trigger_list.append(n_t)

    mongo_interface.add_triggers(final_trigger_list)
    log.d("Elaborated!")
コード例 #21
0
ファイル: merge.py プロジェクト: ujiro99/auto_logger
    def __parse(self, byte):
        """
        Parse log line.
        :param bytes byte:
        :return: Parse result. If failed to decode, returns None time.
        :rtype Merger.Parsed
        """

        try:
            s = byte[0:Merge.TIME_FMT_LEN].decode(Merge.FILE_ENCODE)
            t = dt.strptime(s, Merge.TIME_FMT)
        except Exception as e:
            log.d(e)
            return self.Parsed(line=byte)

        return self.Parsed(t, byte)
コード例 #22
0
ファイル: bot.py プロジェクト: KaikyuLotus/kitsu-ultimate
 def reply(self,
           infos: Infos,
           text: str,
           quote: bool = True,
           markdown: bool = False,
           markup: List = None,
           nolink: bool = False):
     log.d("Replying with a message")
     methods.send_message(
         self.token,
         infos.chat.cid,
         text,
         reply_to_message_id=infos.message.message_id if quote else None,
         parse_mode="markdown" if markdown else None,
         reply_markup=markup,
         disable_web_page_preview=nolink)
コード例 #23
0
def register_bot(token: str, owner_id: int):
    # Check first if it's a real bot token
    try:
        methods.get_me(token)
        _get_bots_collection().insert_one({
            "token": token,
            "owner_id": owner_id,
            # TODO make a method to change the start mode
            "clean_start": True,
            # TODO implement languages
            "language": "IT"
        })
        log.d(f"Registered new bot with ID {token.split(':')[0]}")
        return True
    except TelegramException as ex:
        log.e(f"Cannot register bot: {ex.message}")
        return False
コード例 #24
0
ファイル: watch.py プロジェクト: ujiro99/auto_logger
def file(dirname, filename, timeout):
    """
    Wait until a file created.
    :param str dirname: Directory path to be watched.
    :param str filename: File name to be watched.
    :param num timeout: How many seconds to be wait. [sec]
    :return: Is created the file.
    :rtype bool
    """
    is_glob = filename.find('*') >= 0
    handler = ChangeHandler(dirname, filename, is_glob)
    observer = Observer()
    observer.schedule(handler, dirname, recursive=False)
    observer.start()

    try:
        UPDATE_INTERVAL = 0.5
        interval = UPDATE_INTERVAL
        while interval >= 0 and timeout > 0:
            time.sleep(0.1)
            timeout -= 0.1
            interval -= 0.1
            log.d('- time out remain %.2f, update interval %.2f' %
                  (timeout, interval))
            if handler.modified is True:
                log.i('- now writing... %s ' % filename)
                handler.modified = False
                interval = UPDATE_INTERVAL

    except KeyboardInterrupt:
        observer.stop()

    if not is_glob:
        is_exists = os.path.exists(os.path.join(dirname, filename))
        if is_exists:
            if timeout <= 0:
                log.w("- The file still updating.")
        else:
            log.i("- time out")
            return False

    observer.stop()
    observer.join(timeout)

    return True
コード例 #25
0
def elaborate_dialogs(dialogs: dict, infos: Infos):
    log.d("Elaborating dialogs...")
    mongo_interface.drop_dialogs()

    final_dialogs_list = []

    for section in dialogs:
        if not dialogs[section]:
            continue

        for reply in dialogs[section]:
            n_d = Dialog(update_dummies(reply), section,
                         infos.db.user.language, infos.bot.bot_id)
            print(dict(n_d))
            final_dialogs_list.append(n_d)

    mongo_interface.add_dialogs(final_dialogs_list)
    log.d("Elaborated!")
コード例 #26
0
def elaborate_file(infos: Infos):
    if not infos.user.is_bot_owner:
        return

    if not infos.message.document.file_name.endswith(".kb"):
        return

    log.d("Found a kitsu backup, trying to decrypt it...")
    content = infos.message.document.download()
    jts = json.loads(decode(_backup_password, content))

    with open("resources/backup.json", "w") as f:
        f.write(json.dumps(jts))

    triggers = jts["triggers"]
    dialogs = jts["dialogs"]
    elaborate_triggers(triggers, infos)
    elaborate_dialogs(dialogs, infos)
コード例 #27
0
def to_it(infos):

    if infos.chat.is_private:
        infos.db.user.language = "IT"
        infos.db.update_user()

    if infos.chat.is_supergroup or infos.chat.is_group:
        log.d("Dummy found in a group")
        infos.db.group.language = "IT"
        infos.db.update_group()

    dialogs = mongo_interface.get_dialogs_of_section(infos.bot.bot_id,
                                                     "speak.it", "IT")
    if not dialogs:
        # TODO handle better missing dialog
        return "Ok"

    reply_parser.execute(reply_parser.reply_choice(dialogs).reply, infos)
    return ""
コード例 #28
0
    def __exec_convert_tar(self, script_path):
        """
        Execute conversion a tar file.
        :param str script_path: Script file path, which will be used by `sed` command.
        :return Output directory
        :rtype str
        """
        out_dir = self.__tar_dir + Converter.DIR_SUFFIX
        for d, f in tqdm(list(self.__files())):
            # create output directory.
            dist = os.path.join(out_dir, d)
            if not os.path.exists(dist):
                os.makedirs(dist)

            # execute conversion
            sp = os.path.join(self.__tar_dir, d, f)
            dp = os.path.join(dist, f)
            log.d("- convert: %s" % dp)
            self.__call(Converter.SED_CMD_FMT % (script_path, sp, dp))

        return out_dir
コード例 #29
0
ファイル: lotus.py プロジェクト: KaikyuLotus/kitsu-ultimate
def run(threaded: bool = True, idle: bool = True, auto_attach: bool = True):

    log.i(f"Starting Kitsu Ultimate version {config['lotus']['version']}")

    _load_modules()

    if config["startup"]["drop"]["dialogs"]:
        log.i("Dropping dialogs")
        mongo_interface.drop_dialogs()

    if config["startup"]["drop"]["triggers"]:
        log.i("Dropping triggers")
        mongo_interface.drop_triggers()

    if config["startup"]["drop"]["bots"]:
        log.i("Dropping bots")
        mongo_interface.drop_bots()

    if config["startup"]["drop"]["groups"]:
        log.i("Dropping groups")
        mongo_interface.drop_groups()

    if config["startup"]["drop"]["users"]:
        log.i("Dropping users")
        mongo_interface.drop_users()

    if not threaded:
        log.i("Running in webhook mode")
        raise NotImplementedError()

    if auto_attach:
        log.d("Auto attaching bots from mongo")
        attach_bots_from_manager()

    log.i("Running attached bots")
    [lotus_interface.run_bot(bot) for bot in variables.attached_bots]

    variables.running = True
    if idle:
        lotus_interface.idle()
コード例 #30
0
def execute(reply: str, infos, markup=None):
    if re.search(r"^\[.+]$", reply, re.DOTALL):
        threading.Thread(target=elaborate_multx, args=(reply, infos)).start()
        return

    match = re.search(r"{media:(\w{3}),(.+?)(,(.+))?}", reply)
    if match:
        log.d("Matched media regex")
        media_type = match.group(1)
        media_id = match.group(2)
        caption = match.group(4)
        if media_type == "stk":
            methods.send_sticker(infos.bot.token,
                                 infos.chat.cid,
                                 media_id,
                                 reply_markup=markup)
        elif media_type == "pht":
            methods.send_photo(infos.bot.token,
                               infos.chat.cid,
                               media_id,
                               caption,
                               reply_markup=markup)
        elif media_type == "aud":
            methods.send_audio(infos.bot.token,
                               infos.chat.cid,
                               media_id,
                               reply_markup=markup)
        elif media_type == "voe":
            methods.send_voice(infos.bot.token,
                               infos.chat.cid,
                               media_id,
                               reply_markup=markup)
        elif media_type == "doc":
            methods.send_doc(infos.bot.token,
                             infos.chat.cid,
                             media_id,
                             reply_markup=markup)
        return

    reply, quote, nolink, markdown, markup_msg = parse(reply, infos)

    if not markup and markup_msg:
        markup = markup_msg

    if reply == "":
        log.d("Ignoring empty message")
        return

    log.d("Sending message")
    return methods.send_message(
        infos.bot.token,
        infos.chat.cid,
        reply,
        reply_to_message_id=infos.message.message_id if quote else None,
        parse_mode="markdown" if markdown else None,
        reply_markup=markup,
        disable_web_page_preview=nolink)