async def on_remove_sudoer(c, cq):
    lang = cq._lang
    who = tryint(cq.matches[0]["who"])

    # Sanitize list
    sudoers[:] = [*map(tryint, sudoers)]
    removed = [x for x in sudoers if x != who]
    sudoers[:] = removed

    await Config.get(key="SUDOERS_LIST"
                     ).update(value=" ".join([*map(str, sudoers)]))

    text, keyboard = await sudoers_interface(cq)
    await cq.edit(text, keyboard)
Beispiel #2
0
async def load_env():
    environment_vars = {
        "DATABASE_URL": [
            "sqlite://userlixo/database/database.sqlite",
            "Address of the database (sqlite or postgres).",
        ],
        "LANGUAGE": ["en", "Language for UserLixo's strings"],
        "LOGS_CHAT": [
            "me",
            "Chat where the logs (e.g. startup alert) will be sent. Can be username, link or id.",
        ],
        "PREFIXES": [".", "Prefixes for the userbot commands"],
        "SUDOERS_LIST": [
            "",
            "List of users (usernames and ids separated by space) that will have permission to use your userbot/assistant.",
        ],
        "BOT_TOKEN": ["", "Token of the assistant inline bot"],
    }

    restricted_vars = ["DATABASE_URL"]
    required_vars = ["BOT_TOKEN"]
    missing_vars = []
    for env_key, (default_value, env_info) in environment_vars.items():
        value_on_env = os.getenv(env_key, default_value)

        value_on_db = await Config.get_or_none(key=env_key)

        if not value_on_db:
            if "DYNO" in os.environ and env_key not in restricted_vars:
                os.environ[env_key] = value_on_env
                await Config.create(key=env_key, value=value_on_env)
            elif env_key in restricted_vars:
                os.environ[env_key] = value_on_env
            else:
                missing_vars.append([env_key, value_on_env, env_info])
            continue
        os.environ[env_key] = value_on_db.value

    if missing_vars:
        if len(missing_vars) == len(
                environment_vars.keys()) - len(restricted_vars):
            text = "[dodger_blue1 bold underline]Welcome to UserLixo![/][deep_sky_blue1]\nAs the first step we need to setup some config vars.\n\nYou will be asked for a value for each var, but you can just press enter to leave it empty or use the default value. Let's get started![/]"
        else:
            text = (
                "[bold yellow]Some required config vars are missing. Let's add them.[/]"
            )
        print(text)
    for env_key, value_on_env, env_info in missing_vars:
        text = f"\n┌ [light_sea_green]{env_key}[/light_sea_green]"
        if value_on_env != "":
            text += f" [deep_sky_blue4](default: {value_on_env})[/]"
        elif env_key in required_vars:
            text += f" [yellow](required)[/]"
        text += f"\n├ [medium_purple4 italic]{env_info}[/]"
        print(text)

        try:
            user_value = input("└> ")
        except (KeyboardInterrupt, EOFError):
            print("[red1]Operation cancelled by user")
            exit()
        if not user_value:
            user_value = value_on_env

        if env_key in required_vars and not user_value:
            print(f"[red1]{env_key} is required, cannot be empty.")
            exit()

        row = await Config.create(key=env_key, value=user_value)
        os.environ[env_key] = row.value

    langs.code = os.environ["LANGUAGE"]

    # Sanitize sudoers list
    parts = os.getenv("SUDOERS_LIST").split()
    parts = [*map(lambda x: tryint(x.lstrip("@").lower()), parts)]
    parts = [*set(parts)]
    parts = [x for x in parts if x != "me"]
    sudoers.extend(parts)
Beispiel #3
0
async def main():
    await connect_database()
    await load_env()
    os.system("clear")

    @aiocron.crontab("*/1 * * * *")
    async def clean_cache():
        for file in glob.glob("cache/*"):
            if not os.path.isfile(file):
                continue
            creation_time = datetime.fromtimestamp(os.path.getctime(file))
            now_time = datetime.now()
            diff = now_time - creation_time
            minutes_passed = diff.total_seconds() / 60

            if minutes_passed >= 10:
                os.remove(file)

    if "DYNO" not in os.environ and not os.path.exists("user.session"):
        from userlixo.login import main as login

        await login()
        os.system("clear")

    await user.start()
    await bot.start()
    await unload_inactive_plugins()

    user.me = await user.get_me()
    bot.me = await bot.get_me()
    user.assistant = bot

    if user.me.id not in sudoers:
        sudoers.append(user.me.id)

    # Editing restaring alert
    restarting_alert = await Config.filter(key="restarting_alert")
    if len(restarting_alert) > 1:
        await Config.filter(key="restarting_alert").delete()
        restarting_alert = []

    if restarting_alert:
        restarting_alert = restarting_alert[0]

        parts = restarting_alert.value.split("|")
        message_id, chat_id, cmd_timestamp, from_cmd = parts

        cmd_timestamp = float(cmd_timestamp)
        now_timestamp = datetime.now().timestamp()
        diff = round(now_timestamp - cmd_timestamp, 2)

        title, p = await shell_exec('git log --format="%B" -1')
        rev, p = await shell_exec("git rev-parse --short HEAD")
        date, p = await shell_exec(
            'git log -1 --format=%cd --date=format:"%d/%m %H:%M"')
        timezone, p = await shell_exec(
            'git log -1 --format=%cd --date=format:"%z"')
        local_version = int((await shell_exec("git rev-list --count HEAD"))[0])

        timezone = timezone_shortener(timezone)
        date += f" ({timezone})"

        kwargs = {}
        text = (langs.upgraded_alert
                if from_cmd.startswith("upgrade") else langs.restarted_alert)

        text = text(rev=rev,
                    date=date,
                    seconds=diff,
                    local_version=local_version)
        if "DYNO" in os.environ and from_cmd.startswith("upgrade"):
            text += "\n\n" + langs.alert_need_deploy

        try:
            editor = bot if from_cmd.endswith("_bot") else user
            if editor == bot:
                keyb = ikb([[(langs.back, "start")]])
                kwargs.update(reply_markup=keyb)
            if chat_id == "inline":
                await bot.edit_inline_text(message_id, text, **kwargs)
            else:
                await editor.edit_message_text(tryint(chat_id),
                                               tryint(message_id), text,
                                               **kwargs)
        except Exception as e:
            print(
                f"[yellow]Failed to edit the restarting alert. Maybe the message has been deleted or somehow it became inacessible.\n>> {e}[/yellow]"
            )
        await Config.get(id=restarting_alert.id).delete()

    # Showing alert in cli
    date, p = await shell_exec(
        'git log -1 --format=%cd --date=format:"%d/%m %H:%M"')
    timezone, p = await shell_exec('git log -1 --format=%cd --date=format:"%z"'
                                   )
    local_version = int((await shell_exec("git rev-list --count HEAD"))[0])

    timezone = timezone_shortener(timezone)
    date += f" ({timezone})"
    mention = "@" + user.me.username if user.me.username else user.me.id
    text = f":ok: [bold green]UserLixo is running[/bold green] :ok:"

    userlixo_info = {
        "Version": local_version,
        "Account": mention,
        "Bot": "@" + bot.me.username,
        "Prefixes": os.getenv("PREFIXES"),
        "Logs_chat": os.getenv("LOGS_CHAT"),
        "Sudoers": ", ".join([*set(map(str, sudoers))
                              ]),  # using set() to make the values unique
        "Commit_date": date,
    }
    for k, v in userlixo_info.items():
        text += f"\n[dim cyan]{k}:[/dim cyan] [dim]{v}[/dim]"

    print(Panel.fit(text, border_style="green", box=box.ASCII))

    # Sending alert via Telegram
    try:
        await alert_startup()
    except Exception as e:
        print(
            f"[bold yellow]Error while sending startup alert to LOGS_CHAT: {e}"
        )

    # Alert about unused requirements
    if unused_requirements:
        unused = ", ".join(unused_requirements)
        print(
            f"[yellow]The following packages are not required by plugins anymore: [/][cyan]{unused}"
        )
        try:
            await user.send_message(
                os.getenv("LOGS_CHAT"),
                f"The following packages are not required by plugins anymore: {unused}",
            )
        except Exception as e:
            print("Error while sending alert about unused_requirements:\n  > ",
                  e)
    await idle()