Ejemplo n.º 1
0
async def on_add_plugin_u(c, u):
    is_query = hasattr(u, "data")
    if is_query:
        await u.message.delete()
    lang = u._lang

    loop_count = 0
    while True:
        loop_count += 1
        if not is_query and u.document:
            msg = u
            if loop_count > 1:
                break  # avoid infinite loop
        elif not is_query and u.reply_to_message and u.reply_to_message.document:
            msg = u.reply_to_message
            if loop_count > 1:
                break  # avoid infinite loop
        else:
            msg = await u.from_user.ask(lang.plugin_file_ask)
        if await filters.regex("/cancel")(c, msg):
            return await msg.reply(lang.command_cancelled)
        if not msg.document:
            await msg.reply(lang.plugin_waiting_file, quote=True)
            continue
        if not re.search("(py)$", msg.document.file_name):
            await msg.reply(lang.plugin_format_not_accepted, quote=True)
            continue
        if msg.document.file_size > (5 * 1024 * 1024):
            await msg.reply(lang.plugin_too_big, quote=True)
            continue
        break
    filename = await msg.download(f"cache/")
    filename = os.path.relpath(filename)
    plugin = read_plugin_info(filename)

    # Showing info
    text = write_plugin_info(plugins, lang, plugin, status_line="")
    lines = [
        [
            (lang.add, f"confirm_add_plugin {plugin['type']} {filename}"),
            (lang.cancel, "cancel_plugin"),
        ]
    ]
    keyb = ikb(lines)
    await msg.reply(text, keyb, disable_web_page_preview=True, quote=True)
Ejemplo n.º 2
0
async def on_plugin_action(c, m):
    lang = m._lang
    action = m.matches[0]["action"]
    if action in ["+", "add"]:
        if await filters.me(c, m):
            await m.delete()
        return await on_add_plugin_u(c, m)

    # remove plugin on .plugin rm
    act = m.edit if await filters.me(c, m) else m.reply
    msg = m.reply_to_message

    if not msg.document:
        return await act(lang.plugin_rm_not_document)
    if not msg.document.file_name.endswith(".py"):
        return await act(lang.plugin_rm_not_py)

    basename = msg.document.file_name
    cache_filename = await msg.download("cache/")
    plugin = read_plugin_info(cache_filename)
    if not plugin:
        os.remove(cache_filename)
        return await msg.reply(lang.plugin_info_block_not_found, quote=True)
    plugin_type = plugin["type"]

    if basename not in plugins[plugin_type]:
        return await act(lang.plugin_rm_not_added(name=basename))

    plugin = plugins[plugin_type][basename]

    # compare files via hash
    with open(cache_filename) as remote_file, open(
            plugin["filename"]) as local_file:
        local_data = local_file.read()
        local_hash = hashlib.md5(local_data.encode()).hexdigest()[:10]

        temp_data = remote_file.read()
        remote_hash = hashlib.md5(temp_data.encode()).hexdigest()[:10]
    os.remove(cache_filename)

    if local_hash != remote_hash:
        return await act(lang.plugin_rm_remote_local_are_diff(name=basename))

    inactive = await get_inactive_plugins(plugins)

    if not os.path.exists(plugin["filename"]):
        del plugins[plugin_type][basename]
        return await act(lang.plugin_not_exists_on_server)

    if plugin["notation"] in inactive:
        inactive = [x for x in inactive if x != plugin["notation"]]
        await Config.get(key="INACTIVE_PLUGINS"
                         ).update(value=json.dumps(inactive))

    try:
        module = importlib.import_module(plugin["notation"])
    except Exception as e:
        os.remove(plugin["filename"])
        return await act(lang.plugin_could_not_load(e=e))

    functions = [*filter(callable, module.__dict__.values())]
    functions = [*filter(lambda f: hasattr(f, "handler"), functions)]

    client = (user, bot)[plugin_type == "bot"]
    for f in functions:
        client.remove_handler(*f.handler)
    del plugins[plugin_type][basename]
    os.remove(plugin["filename"])

    await act(lang.plugin_removed_text(name=basename))
Ejemplo n.º 3
0
    workdir=".",
    config_file="./config.ini",
    **pyrogram_config,
)
bot.set_parse_mode("html")

cmds = [
    "help",
    "ping",
    "upgrade",
    "restart",
    "eval",
    "exec",
    "cmd",
    "settings",
    "plugins",
    "commands",
    "start",
]
cmds = {x: 1 for x in cmds}

plugins = {"user": {}, "bot": {}}
for file in glob.glob("userlixo/handlers/*/plugins/*.py"):
    basename = os.path.basename(file)
    plugin_type = ("user", "bot")["handlers/bot/" in file]
    if basename.startswith("__"):
        continue

    info = read_plugin_info(file)
    plugins[plugin_type][basename] = info
Ejemplo n.º 4
0
async def on_confirm_plugin(c, cq):
    lang = cq._lang
    module = None

    plugin_type = cq.matches[0]["plugin_type"]
    client = (user, bot)[plugin_type == "bot"]

    cache_filename = cq.matches[0]["filename"]
    basename = os.path.basename(cache_filename)
    new_filename = "userlixo/handlers/" + plugin_type + "/plugins/" + basename

    plugin = read_plugin_info(cache_filename)
    new_notation = re.sub("\.py$", "", os.path.relpath(new_filename)).replace("/", ".")

    requirements = plugin.get("requirements")
    if requirements:
        DGRAY = 'echo -e "\033[1;30m"'
        RESET = 'echo -e "\033[0m"'
        req_list = requirements.split()
        req_text = ""
        for r in req_list[:-1]:
            req_text += f" ├ <code>{r}</code>\n"
        req_text += f" └ <code>{req_list[-1]}</code>"
        text = lang.installing_plugin_requirements
        text.escape_html = False
        await cq.edit(text(requirements=req_text))
        os.system(f"{DGRAY}; {sys.executable} -m pip install {requirements}; {RESET}")

    # Safely unload the plugin if existent
    if os.path.exists(new_filename):
        try:
            module = importlib.import_module(new_notation)
        except Exception as e:
            return await cq.edit(
                lang.plugin_could_not_load_existent(name=basename, e=e)
            )

        functions = [*filter(callable, module.__dict__.values())]
        functions = [*filter(lambda f: hasattr(f, "handlers"), functions)]

        for f in functions:
            for handler in f.handlers:
                client.remove_handler(*handler)

    os.renames(cache_filename, new_filename)
    plugin = read_plugin_info(new_filename)

    try:
        if module:
            importlib.reload(module)
        module = importlib.import_module(plugin["notation"])
    except Exception as e:
        os.remove(new_filename)
        await cq.edit(lang.plugin_could_not_load(e=e))
        raise e

    functions = [*filter(callable, module.__dict__.values())]
    functions = [*filter(lambda f: hasattr(f, "handlers"), functions)]

    if not len(functions):
        os.remove(new_filename)
        return await cq.edit(lang.plugin_has_no_handlers)

    for f in functions:
        for handler in f.handlers:
            client.add_handler(*handler)

    plugins[plugin_type][basename] = plugin
    reload_plugins_requirements(plugins)

    inactive = await get_inactive_plugins(plugins)

    if plugin["notation"] in inactive:
        inactive = [x for x in inactive if x != plugin["notation"]]
        await Config.get(key="INACTIVE_PLUGINS").update(value=json.dumps(inactive))

    # Discover which page is this plugin listed in
    quant_per_page = 4 * 2  # lines times columns
    page = math.ceil(len(plugins) / quant_per_page)

    keyb = ikb(
        [[(lang.see_plugin_info, f"info_plugin {basename} {plugin_type} {page}")]]
    )
    text = lang.plugin_added(name=basename)
    if "DYNO" in os.environ:
        text += "\n\n" + lang.alert_need_deploy
    await cq.edit(text, keyb)