Example #1
0
async def unban(ctx: MrvnCommandContext, member: Member):
    try:
        await member.unban()
    except Forbidden:
        await ctx.respond_embed(Style.ERROR, ctx.translate("moderation_bot_insufficient_perms"))
    else:
        await ctx.respond_embed(Style.OK, ctx.format("moderation_command_unban_successful", member.mention))
Example #2
0
async def add(ctx: MrvnCommandContext,
              status: Option(str, choices=[
                  OptionChoice("Online", "online"),
                  OptionChoice("Invisible", "invisible"),
                  OptionChoice("Idle", "idle"),
                  OptionChoice("Do Not Disturb", "dnd")
              ]),
              activity: Option(str, choices=[
                  OptionChoice("Playing", "playing"),
                  OptionChoice("Streaming", "streaming"),
                  OptionChoice("Listening", "listening"),
                  OptionChoice("Watching", "watching"),
                  OptionChoice("Competing", "competing")
              ]),
              text: ParseUntilEndsOption(str)):
    if len(await BotStatusEntry.filter()) == ENTRIES_LIMIT:
        await ctx.respond_embed(Style.ERROR, ctx.translate("bot_status_command_add_limit_reached"))

        return
    elif len(text) > 50:
        await ctx.respond_embed(Style.ERROR, ctx.translate("bot_status_command_add_text_too_long"))

        return

    await BotStatusEntry.create(status=status, activity=activity.lower(), text=text)

    status_update.start_task()

    await ctx.respond_embed(Style.OK, ctx.translate("bot_status_command_add_status_added"))
Example #3
0
async def shell(ctx: MrvnCommandContext, command: ParseUntilEndsOption(str)):
    if "shutdown" in command.lower() or "restart" in command.lower():
        await ctx.respond_embed(
            Style.ERROR,
            ctx.translate("execute_command_shell_prohibited_word"))

        return

    await ctx.defer()

    encoding = "cp866" if platform.system() == "Windows" else "utf-8"

    try:
        result = subprocess.check_output(command,
                                         shell=True,
                                         timeout=5,
                                         stderr=subprocess.STDOUT)
    except subprocess.TimeoutExpired:
        await ctx.respond_embed(
            Style.WARN,
            ctx.translate("execute_command_shell_executed_timeout"))
    except subprocess.CalledProcessError as ex:
        await ctx.respond_embed(Style.ERROR, ex.output.decode(encoding),
                                ctx.translate("execute_command_shell_error"))
    else:
        await ctx.respond_embed(Style.OK, result.decode(encoding),
                                ctx.translate("execute_command_shell_ok"))
Example #4
0
async def cmds(ctx: MrvnCommandContext):
    cat_commands = {}

    for cat in categories.categories:
        cat_commands[cat] = runtime.bot.get_category_commands(cat, ctx.guild_id)

    cat_commands = {k: v for k, v in sorted(cat_commands.items(), key=lambda item: len(item[1]), reverse=True)}

    items = [Button(label=f"{ctx.translate(cat.name)} ({len(items)})", disabled=not len(items),
                    style=ButtonStyle.blurple if len(items) else ButtonStyle.gray) for cat, items in
             cat_commands.items()]

    view = CategoryView(ctx, items, author=ctx.author, timeout=10)

    message = await ctx.respond(ctx.translate("std_command_help_choose_category"), view=view)

    await view.wait()

    if view.category_len is None:
        return

    category, items = list(cat_commands.items())[view.category_len]
    count = len(items)

    num_pages = math.ceil(count / PAGE_SIZE) if count > PAGE_SIZE else 1

    paginator = CmdsPaginator(ctx, items, ctx.translate(category.name), num_pages=num_pages, timeout=30,
                              original_author=ctx.author, guild=ctx.guild)

    await paginator.attach(message)
Example #5
0
async def wiki(ctx: MrvnCommandContext, query: ParseUntilEndsOption(str)):
    await ctx.defer()

    session = ClientSession(timeout=ClientTimeout(20))

    params = {"action": "query",
              "format": "json",
              "list": "search",
              "srsearch": query}

    try:
        response = await session.get("https://ru.wikipedia.org/w/api.php",
                                     params=params)
    except (asyncio.TimeoutError, ClientConnectionError):
        await ctx.respond_embed(Style.ERROR, ctx.translate("search_connection_error"))

        return

    data = await response.json()

    await session.close()
    response.close()

    items = [x["title"] for x in data["query"]["search"]]

    if not len(items):
        await ctx.respond_embed(Style.ERROR, ctx.format("search_command_not_found", query))

        return

    paginator = WikiPaginator("ru", tr=ctx, author=ctx.author, original_author=ctx.author, timeout=30, pages=items,
                              guild=ctx.guild)

    await paginator.respond_ctx(ctx)
Example #6
0
async def unmute(ctx: MrvnCommandContext, member: Member):
    try:
        await member.edit(communication_disabled_until=None)
    except Forbidden:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("moderation_bot_insufficient_perms"))
    else:
        await ctx.respond_embed(
            Style.OK,
            ctx.format("moderation_command_unmute_successful", member.mention))
Example #7
0
    async def send_command_exception_message(ctx: MrvnCommandContext, exc):
        logger.error(traceback.format_exc())

        await ctx.respond_embed(
            Style.ERROR,
            ctx.format(
                "mrvn_api_command_execution_error_desc", "".join(
                    traceback.format_exception(value=exc,
                                               etype=type(exc),
                                               tb=exc.__traceback__))),
            ctx.translate("mrvn_api_command_execution_error_title"))
Example #8
0
async def set_prefix(ctx: MrvnCommandContext, command: command_option, prefix: str):
    if prefix not in PREFIX_LIST:
        await ctx.respond_embed(Style.ERROR, ctx.format("std_command_override_prefix_not_in_list", " ".join(PREFIX_LIST)))
        return

    override = (await CommandOverride.get_or_create(guild_id=ctx.guild_id, command_name=command.name))[0]

    override.prefix = prefix

    await override.save()

    await ctx.respond_embed(Style.OK, ctx.format("std_command_override_prefix_changed", command.name))
Example #9
0
async def list_(ctx: MrvnCommandContext, global_setting: bool):
    items = []

    for cat in settings.categories:
        cat_settings = cat.get_settings(global_setting)

        items.append(
            Button(label=ctx.translate(cat.name),
                   style=ButtonStyle.blurple
                   if len(cat_settings) else ButtonStyle.gray,
                   disabled=not len(cat_settings)))

    view = CategoryView(ctx, items, author=ctx.author, timeout=10)

    message = await ctx.respond(
        ctx.translate("std_command_settings_choose_category"), view=view)

    await view.wait()

    if view.category_len is None:
        return

    category = settings.categories[view.category_len]
    category_settings = category.get_settings(global_setting)

    count = len(category_settings)

    num_pages = math.ceil(count / PAGE_SIZE) if count > PAGE_SIZE else 1

    settings_list = []

    for setting in category_settings:
        if global_setting:
            value = (await setting.get_or_create())[0].value
        else:
            value = (await
                     setting.get_or_create(guild_id=ctx.guild_id))[0].value

        settings_list.append(
            (f"{setting.key} [{value}]", ctx.translate(setting.description)))

    paginator = CmdsPaginator(ctx,
                              settings_list,
                              ctx.translate(category.name),
                              is_global=global_setting,
                              num_pages=num_pages,
                              timeout=30,
                              original_author=ctx.author,
                              guild=ctx.guild)

    await paginator.attach(message)
Example #10
0
    async def process_dm(self, ctx: MrvnCommandContext):
        allow_dms = (await SettingAllowCommandsInDMs.get_or_create())[0].value

        if not allow_dms:
            await ctx.respond_embed(
                Style.ERROR, ctx.translate("mrvn_core_dm_commands_disabled"))
            return True

        guild_only = self.is_guild_only(ctx.command)

        if guild_only:
            await ctx.respond_embed(
                Style.ERROR, ctx.translate("mrvn_core_command_is_guild_only"))

        return guild_only
Example #11
0
async def purge(ctx: MrvnCommandContext,
                number: Option(int, min_value=1, max_value=200),
                member: Member = None):
    try:
        deleted = await ctx.channel.purge(
            limit=number,
            check=lambda msg: member is None or msg.author == member,
            bulk=True)
    except Forbidden:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("moderation_bot_insufficient_perms"))
    else:
        await ctx.respond_embed(
            Style.OK,
            ctx.format("moderation_command_purge_messages_removed",
                       ctx.author.mention, deleted))
Example #12
0
    async def convert(converter, ctx: MrvnCommandContext, argument: str) -> Union[SlashCommand, SlashCommandGroup]:
        try:
            command = next(filter(lambda it: it.name == argument, runtime.bot.application_commands))
        except StopIteration:
            raise ArgumentParseException(ctx.translate("std_command_override_command_not_found"))

        return command
Example #13
0
async def glados(ctx: MrvnCommandContext, text: ParseUntilEndsOption(str)):
    await ctx.defer()

    data = {"text": text, "character": "GLaDOS", "emotion": "Contextual"}

    session = ClientSession(timeout=ClientTimeout(20))

    try:
        response = await session.post(TTS_URL, headers=TTS_HEADERS, json=data)
    except (asyncio.TimeoutError, ClientConnectionError):
        await ctx.respond_embed(
            Style.ERROR,
            ctx.translate("fun_stuff_command_glados_request_error"))

        return

    if response.status != 200:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("fun_stuff_command_glados_api_error"))

        return

    response_data = await response.json(content_type=None)
    response.close()

    result_url = AUDIO_URL + response_data["wavNames"][0]

    try:
        response = await session.get(result_url, headers=TTS_HEADERS)
    except (asyncio.TimeoutError, ClientConnectionError):
        await ctx.respond_embed(
            Style.ERROR,
            ctx.translate("fun_stuff_command_glados_download_error"))

        return

    buf = BytesIO(await response.read())

    await session.close()
    response.close()

    await ctx.respond(file=File(
        buf,
        filename=
        f"GLaDOS_{ctx.message.id if not ctx.interaction else ctx.interaction.id}.wav"
    ))
Example #14
0
async def vision(ctx: MrvnCommandContext, image: Option(Attachment)):
    if not image.content_type.startswith("image"):
        await ctx.respond_embed(
            Style.ERROR,
            ctx.translate("vision_command_vision_invalid_content_type"))

        return

    await ctx.defer()

    session = aiohttp.ClientSession(timeout=ClientTimeout(20))

    try:
        response = await session.post(
            SERVICE_URL,
            data="userlink=%s" % parse.quote(image.url, safe=''),
            headers={
                "Cookie": "textonly=true; imageonly=true; qronly=false",
                "Content-Type": "application/x-www-form-urlencoded"
            })
    except (aiohttp.ClientConnectionError, asyncio.TimeoutError):
        await ctx.respond_embed(
            Style.ERROR,
            ctx.translate("vision_command_vision_connection_error"))

        return
    finally:
        await session.close()

    text = await response.text()

    response.close()

    soup = BeautifulSoup(text, "html.parser")
    results = soup.find_all("div", {"class": "success description"})

    if not len(results):
        await ctx.respond_embed(Style.ERROR,
                                ctx.translate("vision_command_vision_fail"))
        return

    embed = ctx.get_embed(Style.INFO, results[0].text,
                          ctx.translate("vision_command_vision_title"))
    embed.set_image(url=image.url)

    await ctx.respond(embed=embed)
Example #15
0
async def prefix_disable(ctx: MrvnCommandContext, command: command_option):
    override = (await CommandOverride.get_or_create(guild_id=ctx.guild_id, command_name=command.name))[0]

    override.prefix = ""

    await override.save()

    await ctx.respond_embed(Style.OK, ctx.format("std_command_custom_prefix_disabled", command.name))
Example #16
0
async def command_set_enabled(ctx: MrvnCommandContext, command: command_option, enable: bool):
    override = (await CommandOverride.get_or_create(guild_id=ctx.guild_id, command_name=command.name))[0]

    override.disabled = not enable

    await override.save()

    await ctx.respond_embed(Style.OK, ctx.format(
        f"std_command_override_command_{'enabled' if enable else 'disabled'}", command.name))
Example #17
0
async def execute(ctx: MrvnCommandContext, code: ParseUntilEndsOption(str)):
    if ctx.interaction is None:
        if len((splitted := ctx.message.content.split("```"))) == 3:
            code = splitted[1].rstrip()
        else:
            await ctx.respond_embed(
                Style.ERROR,
                ctx.translate("execute_command_execute_invalid_format"))

            return
Example #18
0
async def info(ctx: MrvnCommandContext, command: command_option):
    override = await CommandOverride.get_or_none(guild_id=ctx.guild_id, command_name=command.name)

    if not override:
        await ctx.respond_embed(Style.ERROR, ctx.translate("std_command_override_no_override"))

        return

    empty = ctx.translate("std_command_override_empty")

    enabled = not override.disabled
    prefix = override.prefix if len(override.prefix) else empty
    perm_list = ", ".join(override.discord_permissions) if len(override.discord_permissions) else empty
    channel_list = ", ".join([channel.mention if (channel := runtime.bot.get_channel(x)) else str(x) for x in
                              override.whitelist_channel_ids]) if len(override.whitelist_channel_ids) else empty

    await ctx.respond_embed(Style.INFO,
                            ctx.format("std_command_override_info", enabled, prefix, perm_list, channel_list),
                            ctx.format("std_command_override_info_title", command.name))
Example #19
0
async def owner_list(ctx: MrvnCommandContext):
    owner_ids = list([x.user_id for x in await MrvnUser.filter(is_owner=True)])

    app = await runtime.bot.application_info()  # type: ignore
    if app.team:
        owner_ids.extend([m.id for m in app.team.members])
    else:
        owner_ids.append(app.owner.id)

    if not len(owner_ids):
        await ctx.respond_embed(Style.ERROR,
                                ctx.translate("std_command_owners_no_owners"))

        return

    owners = [
        user.mention if (user := runtime.bot.get_user(x)) else
        ctx.translate("std_command_owners_unknown") for x in owner_ids
    ]
Example #20
0
async def ban(ctx: MrvnCommandContext, member: Member):
    if member == runtime.bot.user:
        await ctx.respond_embed(Style.ERROR, ctx.translate("moderation_cant_do_this_to_bot"))

        return
    elif member == ctx.author:
        await ctx.respond_embed(Style.ERROR, ctx.translate("moderation_cant_do_this_to_self"))

        return
    elif ctx.author.top_role.position < member.top_role.position or ctx.author.guild_permissions < member.guild_permissions:
        await ctx.respond_embed(Style.ERROR, ctx.translate("moderation_cant_do_this_to_this_user"))

        return

    try:
        await member.ban(delete_message_days=0)
    except Forbidden:
        await ctx.respond_embed(Style.ERROR, ctx.translate("moderation_bot_insufficient_perms"))
    else:
        await ctx.respond_embed(Style.OK, ctx.format("moderation_command_ban_success", member.mention))
Example #21
0
async def commands(ctx: MrvnCommandContext):
    await ctx.defer()

    command_entries = sorted(await StatsCommandEntry.filter(guild_id=ctx.guild_id), key=lambda k: k.count,
                             reverse=True)[:10]
    command_stats = "\n".join([f"**{x.command_name}** - `{x.count}`" for x in command_entries])

    user_entries = sorted(await StatsUserCommandsEntry.filter(guild_id=ctx.guild_id), key=lambda k: k.count,
                          reverse=True)[:10]
    user_stats = "\n".join([f"{get_user_mention(x.user_id)} - `{x.count}`" for x in user_entries])

    embed = ctx.get_embed(Style.INFO, title=ctx.translate("statistics_command_commands_title"))
    embed.description = f"""
{ctx.translate("statistics_command_commands_command_top")}
{command_stats}
{ctx.translate("statistics_command_commands_user_top")}
{user_stats}
"""

    await ctx.respond(embed=embed)
Example #22
0
async def messages_command(ctx: MrvnCommandContext):
    await ctx.defer()

    data = await get_monthly_messages(ctx.guild_id)
    legend_text = ctx.format("statistics_command_messages_legend",
                             ctx.guild.name)

    result = await asyncio.get_event_loop().run_in_executor(
        None, functools.partial(plot.get_plot, data, legend_text))

    await ctx.respond(file=File(result, filename="Chart.png"))
Example #23
0
async def edit_(ctx: MrvnCommandContext, key: str, value: str,
                global_setting: bool):
    cls = GlobalSetting if global_setting else GuildSetting

    try:
        setting = next(filter(lambda it: it.key == key, cls.__subclasses__()))
    except StopIteration:
        await ctx.respond_embed(
            Style.ERROR,
            ctx.translate("std_command_settings_edit_invalid_key"))
        return

    if global_setting:
        model = (await setting.get_or_create())[0]
    else:
        model = (await setting.get_or_create(guild_id=ctx.guild_id))[0]

    value_type = type(model.value_field)

    if value_type == bool:
        value = value.lower() == "true"

    try:
        model.value = value
    except SettingsValueWriteError as e:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate(e.message),
            ctx.translate("std_command_settings_edit_invalid_value"))
        return

    try:
        await model.save()
    except ValueError:
        await ctx.respond_embed(
            Style.ERROR,
            ctx.format("std_command_settings_edit_invalid_value_for_type",
                       value_type.__name__))
        return

    await ctx.respond_embed(
        Style.OK, ctx.translate("std_command_settings_edit_value_set"))
Example #24
0
async def remove(ctx: MrvnCommandContext):
    entries = await BotStatusEntry.filter()

    if not len(entries):
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("bot_status_command_remove_no_entries"))

        return

    view = EntriesView(ctx, await BotStatusEntry.filter(), timeout=40)

    await view.respond(ctx)
Example #25
0
async def permissions_edit(ctx: MrvnCommandContext, command: command_option, permission: str, add_: bool):
    permission = permission.lower()

    if permission not in Permissions.VALID_FLAGS.keys():
        await ctx.respond_embed(Style.ERROR, ctx.translate("std_command_override_invalid_permission"))

        return

    override = (await CommandOverride.get_or_create(guild_id=ctx.guild_id, command_name=command.name))[0]

    if add_ and permission not in override.discord_permissions:
        override.discord_permissions.append(permission)

        await override.save()
    elif not add_ and permission in override.discord_permissions:
        override.discord_permissions.remove(permission)

        await override.save()

    await ctx.respond_embed(Style.OK, ctx.format(
        f"std_command_override_permission_{'added' if add_ else 'removed'}", permission, command.name))
Example #26
0
 async def process_override(self, ctx: MrvnCommandContext,
                            override: CommandOverride) -> bool:
     if override.disabled:
         await ctx.respond_embed(
             Style.ERROR,
             ctx.translate("mrvn_core_override_command_disabled"))
         return False
     elif len(override.whitelist_channel_ids
              ) and ctx.channel_id not in override.whitelist_channel_ids:
         channel_list = ", ".join([
             channel.mention if (channel := self.get_channel(x)) else str(x)
             for x in override.whitelist_channel_ids
         ])
Example #27
0
async def edit_owner(ctx: MrvnCommandContext, user: User, add_: bool):
    mrvn_user = (await MrvnUser.get_or_create(user_id=user.id))[0]

    if add_ and mrvn_user.is_owner:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("std_command_owner_already_an_owner"))

        return
    elif not add_ and not mrvn_user.is_owner:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("std_command_owner_not_an_owner"))

        return

    mrvn_user.is_owner = add_

    await mrvn_user.save()

    await ctx.respond_embed(
        Style.OK,
        ctx.format(
            "std_command_owner_add" if add_ else "std_command_owner_remove",
            user.mention))
Example #28
0
async def man(ctx: MrvnCommandContext, cmd_name: ParseUntilEndsOption(str)):
    cmd_split = iter(cmd_name.split())

    name = next(cmd_split)

    for cmd in runtime.bot.application_commands:
        if isinstance(cmd, (SlashCommand, SlashCommandGroup)
                      ) and cmd.name == name and ctx.guild_id in cmd.guild_ids:
            command = cmd
            break
    else:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("std_command_help_command_not_found"))

        return

    root = command

    try:
        while isinstance(command, SlashCommandGroup):
            sub_cmd_name = next(cmd_split)

            command = next(
                filter(lambda it: it.name == sub_cmd_name,
                       command.subcommands))
    except StopIteration:
        await ctx.respond_embed(
            Style.INFO, runtime.bot.get_command_desc(root, ctx, as_tree=True))

        return

    embed = ctx.get_embed(Style.INFO)

    embed.add_field(name=runtime.bot.get_command_desc(command, ctx),
                    value=command.description)

    await ctx.respond(embed=embed)
Example #29
0
async def channel_edit(ctx: MrvnCommandContext, command: SlashCommand, channel: TextChannel, add_: bool):
    override = (await CommandOverride.get_or_create(guild_id=ctx.guild_id, command_name=command.name))[0]

    channel_id = channel.id

    if add_ and channel_id not in override.whitelist_channel_ids:
        override.whitelist_channel_ids.append(channel_id)

        await override.save()
    elif not add_ and channel_id in override.whitelist_channel_ids:
        override.whitelist_channel_ids.remove(channel_id)

        await override.save()

    await ctx.respond_embed(Style.OK, ctx.format(
        f"std_command_override_channel_{'added' if add_ else 'removed'}", channel.mention, command.name))
Example #30
0
async def mute(ctx: MrvnCommandContext, member: Member, time: int,
               unit: Option(str,
                            choices=[
                                OptionChoice("Seconds", "s"),
                                OptionChoice("Minutes", "m"),
                                OptionChoice("Hours", "h"),
                                OptionChoice("Days", "d"),
                                OptionChoice("Weeks", "w"),
                                OptionChoice("Months", "mo"),
                                OptionChoice("Years", "y")
                            ])):
    if member == runtime.bot.user:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("moderation_cant_do_this_to_bot"))

        return
    elif member == ctx.author:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("moderation_cant_do_this_to_self"))

        return
    elif member.guild_permissions.administrator:
        await ctx.respond_embed(
            Style.ERROR,
            ctx.translate("moderation_command_mute_cant_mute_administrator"))

        return
    elif ctx.author.top_role.position < member.top_role.position or ctx.author.guild_permissions < member.guild_permissions:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("moderation_cant_do_this_to_this_user"))

        return

    timestamp = datetime.datetime.utcnow() + datetime.timedelta(
        0, time * TIME_DICT[unit])

    try:
        await member.edit(communication_disabled_until=timestamp)
    except Forbidden:
        await ctx.respond_embed(
            Style.ERROR, ctx.translate("moderation_bot_insufficient_perms"))
    else:
        await ctx.respond_embed(
            Style.OK,
            ctx.format("moderation_command_mute_successful", member.mention))