Exemple #1
0
        async def yes():
            failures = await Actions.mass_action(ctx, "warning", targets, self._warn, max_targets=10, allow_bots=False,
                                                 message=False, reason=reason, dm_action=True, require_on_server=False)

            await MessageUtils.send_to(ctx, "YES", "mwarn_confirmation", count=len(targets) - len(failures))
            if len(failures) > 0:
                await Pages.create_new(self.bot, "mass_failures", ctx, action_type="warn",
                                       failures="----NEW PAGE----".join(Pages.paginate("\n".join(failures))))
Exemple #2
0
 async def uid(self, ctx, *, text: str):
     """uid_help"""
     parts = await Utils.get_user_ids(text)
     if len(parts) > 0:
         for chunk in Pages.paginate("\n".join(parts), 200):
             await ctx.send(chunk)
     else:
         await MessageUtils.send_to(ctx, "NO", "no_uids_found")
Exemple #3
0
 def gen_roles_pages(guild: discord.Guild):
     role_list = dict()
     longest_name = 1
     for role in guild.roles:
         role_list[f"{role.name} - {role.id}"] = role
         longest_name = max(longest_name, len(role.name))
     return Pages.paginate("\n".join(
         f"{role_list[r].name} {' ' * (longest_name - len(role_list[r].name))} - {role_list[r].id}"
         for r in sorted(role_list.keys())))
Exemple #4
0
 async def mutuals(self, ctx, user: UserID):
     mutuals = []
     for guild in self.bot.guilds:
         if guild.get_member(user) is not None:
             mutuals.append(guild)
     for page in Pages.paginate("\n".join(f"{guild.id} - {guild.name}"
                                          for guild in mutuals),
                                prefix="```py\n",
                                suffix="```"):
         await ctx.send(page)
Exemple #5
0
async def gen_cog_help(bot, cog, member, guild):
    commands, longest = await cog_commands(bot, cog, member, guild)
    output = f'- {cog}\n'
    if commands is not None:
        for command_name, info in commands.items():
            output += command_name + (
                " " * (longest - len(command_name) + 4)) + info + "\n"
        return Pages.paginate(output)
    else:
        return None
Exemple #6
0
 def gen_role_pages(self, guild: discord.Guild):
     roles = Configuration.get_var(guild.id, "SELF_ROLES")
     current_roles = ""
     count = 1
     for role in roles:
         current_roles += f"{count}) <@&{role}>\n\n"
         count += 1
         if count > 10:
             count = 1
     return Pages.paginate(current_roles, max_lines=20)
Exemple #7
0
async def fetch_infraction_pages(guild_id, query, amount, fields, requested):
    key = get_key(guild_id, query, fields, amount)
    if query == "":
        infs = await Infraction.filter(guild_id=guild_id
                                       ).order_by("-id").limit(50)
    else:
        subfilters = []
        if "[user]" in fields and isinstance(query, int):
            subfilters.append(Q(user_id=query))
        if "[mod]" in fields and isinstance(query, int):
            subfilters.append(Q(mod_id=query))
        if "[reason]" in fields:
            subfilters.append(Q(reason__icontains=str(query)))

        infs = await Infraction.filter(
            Q(Q(*subfilters, join_type="OR"),
              guild_id=guild_id,
              join_type="AND")).order_by("-id").limit(int(amount))
    longest_type = 4
    longest_id = len(str(infs[0].id)) if len(infs) > 0 else len(
        Translator.translate('id', guild_id))
    longest_timestamp = max(len(Translator.translate('timestamp', guild_id)),
                            19)
    types = dict()
    for inf in infs:
        t = inf.type.lower()
        longest_type = max(longest_type, len(Translator.translate(t,
                                                                  guild_id)))
        if t not in types:
            types[t] = 1
        else:
            types[t] += 1
    header = ", ".join(
        Translator.translate(f"{k}s", guild_id, count=v)
        for k, v in types.items())
    name = await Utils.username(query) if isinstance(
        query, int) else await Utils.clean(bot.get_guild(guild_id).name)
    title = f"{Emoji.get_chat_emoji('SEARCH')} {Translator.translate('inf_search_header', guild_id, name=name, page_num=100, pages=100)}\n```md\n\n```"
    page_header = get_header(longest_id, 37, longest_type, longest_timestamp,
                             guild_id)
    mcount = 2000 - len(header) - len(page_header) - len(title)
    out = "\n".join(
        f"{Utils.pad(str(inf.id), longest_id)} | <@{Utils.pad(str(inf.user_id), 37)}> | <@{Utils.pad(str(inf.mod_id), 37)}> | {datetime.fromtimestamp(inf.start)} | {Utils.pad(Translator.translate(inf.type.lower(), guild_id), longest_type)} | {Utils.trim_message(inf.reason, 1000)}"
        for inf in infs)
    pages = Pages.paginate(out, max_chars=mcount)
    if bot.redis_pool is not None:
        GearbotLogging.debug(f"Pushing placeholders for {key}")
        pipe = bot.redis_pool.pipeline()
        for page in pages:
            pipe.lpush(key, "---NO PAGE YET---")
        await pipe.execute()
    bot.loop.create_task(
        update_pages(guild_id, query, fields, amount, pages, requested,
                     longest_id, longest_type, longest_timestamp, header))
    return len(pages)
Exemple #8
0
    async def eval(self, ctx:commands.Context, *, code: str):
        output = None
        env = {
            'bot': self.bot,
            'ctx': ctx,
            'channel': ctx.channel,
            'author': ctx.author,
            'guild': ctx.guild,
            'message': ctx.message
        }

        env.update(globals())

        if code.startswith('```'):
            code = "\n".join(code.split("\n")[1:-1])

        out = io.StringIO()

        to_compile = f'async def func():\n{textwrap.indent(code, "  ")}'

        try:
            exec(to_compile, env)
        except Exception as e:
            output = f'{e.__class__.__name__}: {e}'
        else:
            func = env['func']
            try:
                with contextlib.redirect_stdout(out):
                    ret = await func()
            except Exception as e:
                value = out.getvalue()
                output = f'{value}{traceback.format_exc()}'
            else:
                value = out.getvalue()
                if ret is None:
                    if value:
                        output = value
                else:
                    output = f'{value}{ret}'
        if output is not None:
            pipe = self.bot.redis_pool.pipeline()
            k = f'eval:{ctx.message.id}'
            pipe.set(k, output)
            pipe.expire(k, 7*24*60*60)
            await pipe.execute()
            pages = Pages.paginate(output, prefix='```py\n', suffix='```')
            content, view, _ = SimplePager.get_parts(pages, 0, ctx.guild.id if ctx.guild is not None else 0, f'eval:{ctx.message.id}')
            await ctx.send(f'Eval output 1/{len(pages)}{content}', view=view)
        else:
            await ctx.message.add_reaction(Emoji.get_emoji("YES"))
Exemple #9
0
    async def eval(self, ctx: commands.Context, *, code: str):
        output = None
        env = {
            'bot': self.bot,
            'ctx': ctx,
            'channel': ctx.channel,
            'author': ctx.author,
            'guild': ctx.guild,
            'message': ctx.message
        }

        env.update(globals())

        if code.startswith('```'):
            code = "\n".join(code.split("\n")[1:-1])

        out = io.StringIO()

        to_compile = f'async def func():\n{textwrap.indent(code, "  ")}'

        try:
            exec(to_compile, env)
        except Exception as e:
            output = f'{e.__class__.__name__}: {e}'
        else:
            func = env['func']
            try:
                with contextlib.redirect_stdout(out):
                    ret = await func()
            except Exception as e:
                value = out.getvalue()
                output = f'{value}{traceback.format_exc()}'
            else:
                value = out.getvalue()
                if ret is None:
                    if value:
                        output = value
                else:
                    output = f'{value}{ret}'
        if output is not None:
            await Pages.create_new(self.bot,
                                   "eval",
                                   ctx,
                                   pages="----NEW PAGE----".join(
                                       Pages.paginate(output)),
                                   code=code,
                                   trigger=ctx.message.id,
                                   sender=ctx.author.id)
        else:
            await ctx.message.add_reaction(Emoji.get_emoji("YES"))
Exemple #10
0
 async def pull(self, ctx):
     """Pulls from github so an upgrade can be performed without full restart"""
     async with ctx.typing():
         code, out, error = await Utils.execute(["git pull origin master"])
     if code is 0:
         await Pages.create_new(
             "pull",
             ctx,
             title=
             f"{Emoji.get_chat_emoji('YES')} Pull completed with exit code {code}",
             pages=Pages.paginate(out.decode('utf-8')))
     else:
         await ctx.send(
             f"{Emoji.get_chat_emoji('NO')} Pull completed with exit code {code}```yaml\n{out.decode('utf-8')}\n{error.decode('utf-8')}```"
         )
Exemple #11
0
async def gen_command_help(bot, ctx, command):
    if ctx.prefix is None:
        ctx.prefix = ""
    bot.help_command.context = ctx
    usage = ctx.bot.help_command.get_command_signature(command)
    sub_info = None
    if isinstance(command, GroupMixin) and hasattr(command, "all_commands"):
        subcommands, longest = await gen_commands_list(bot, ctx, command.all_commands.values())
        if subcommands is not None:
            sub_info = "\nSub commands:\n"
            for command_name, info in subcommands.items():
                sub_info += "  " + command_name + (" " * (longest - len(command_name) + 4)) + info + "\n"
            sub_info += Translator.translate('help_footer', ctx, prefix=ctx.prefix, signature=ctx.bot.help_command.get_command_signature(command).replace(ctx.prefix, ""))

    return Pages.paginate(f"{usage}\n\n{Translator.translate(command.help, ctx)}\n{'' if sub_info is None else sub_info}".replace(ctx.me.mention, f"@{ctx.me.name}"))
async def gen_command_help(bot, ctx, command):
    usage = ctx.prefix.replace(ctx.me.mention,
                               f"@{ctx.me.name}") + command.signature
    sub_info = None
    if isinstance(command, GroupMixin) and hasattr(command, "all_commands"):
        subcommands, longest = await gen_commands_list(
            bot, ctx, command.all_commands.values())
        if subcommands is not None:
            sub_info = "\nSub commands:\n"
            for command_name, info in subcommands.items():
                sub_info += "  " + command_name + (
                    " " * (longest - len(command_name) + 4)) + info + "\n"
            sub_info += f"You can get more info about a command (params and subcommands) by using '{ctx.prefix}help {command.signature} <subcommand>'\nCommands followed by ↪  have subcommands".replace(
                ctx.me.mention, f"@{ctx.me.name}") + command.signature

    return Pages.paginate(
        f"{usage}\n\n{Translator.translate(command.help, ctx)}\n{'' if sub_info is None else sub_info}"
        .replace(ctx.me.mention, f"@{ctx.me.name}"))
Exemple #13
0
 async def list(self, ctx):
     """remind_list_help"""
     reminders = await Reminder.filter(status=ReminderStatus.Pending,
                                       user_id=ctx.author.id)
     if len(reminders) == 0:
         await MessageUtils.send_to(ctx, "WARNING", "reminder_none")
         return
     items = "\n".join(
         f"{str(r.id).ljust(5)} | {timeago.format(r.send).ljust(14)} | {timeago.format(r.time).ljust(14)} | {Utils.clean_name(r.to_remind)}"
         for r in reminders)
     header = "ID    | Scheduled      | Delivery       | Content"
     pages = Pages.paginate(
         items,
         prefix=f"```md\n{header}\n{'-' * len(header)}\n",
         suffix="```")
     await Pages.create_new(self.bot,
                            "reminder_list",
                            ctx,
                            pages=json.dumps(pages))
Exemple #14
0
def dict_to_pages(dict, suffix=""):
    pages = []
    output = ""
    for out in dict.values():
        if len(output) + len(out) > 1000:
            pages.append(f"{output}\n{suffix}")
            output = out
        else:
            if output == "":
                output = Utils.trim_message(out, 2000 - 15 - len(suffix))
            else:
                output += out + "\n"
    pages.append(f"{output}\n{suffix}")
    # if some page does end up over 2k, split it
    real_pages = []
    for p in pages:
        for page in Pages.paginate(p, max_lines=100):
            real_pages.append(page)
    return real_pages
Exemple #15
0
        async def yes():
            pmessage = await MessageUtils.send_to(ctx, "REFRESH", "processing")
            failures = await Actions.mass_action(ctx,
                                                 "warning",
                                                 targets,
                                                 self._warn,
                                                 max_targets=10,
                                                 allow_bots=False,
                                                 message=False,
                                                 reason=reason)

            await pmessage.delete()
            await MessageUtils.send_to(ctx,
                                       "YES",
                                       "mwarn_confirmation",
                                       count=len(targets) - len(failures))
            if len(failures) > 0:
                await Pages.create_new(self.bot,
                                       "mass_failures",
                                       ctx,
                                       action="warn",
                                       failures="----NEW PAGE----".join(
                                           Pages.paginate(
                                               "\n".join(failures))))
Exemple #16
0
 async def _blacklist_init(ctx):
     pages = Pages.paginate("\n".join(Configuration.get_var(ctx.guild.id, "WORD_BLACKLIST")))
     return f"**{Translator.translate(f'blacklist_list', ctx, server=ctx.guild.name, page_num=1, pages=len(pages))}**```\n{pages[0]}```", None, len(pages) > 1, []
Exemple #17
0
    async def on_interaction(self, interaction):
        guild = self.bot.get_guild(interaction.guild_id)
        if interaction.type == InteractionType.component:
            cid = interaction.data.custom_id
            if cid.startswith('self_role'):
                parts = cid.split(':')
                if parts[1] == 'role':
                    rid = parts[2]
                    if rid.isnumeric():
                        rid = int(rid)
                        roles = Configuration.get_var(interaction.guild_id,
                                                      "ROLES", "SELF_ROLES")
                        if rid in roles:
                            role = guild.get_role(rid)
                            if role is None:
                                roles.remove(rid)
                                Configuration.set_var(interaction.guild_id,
                                                      "ROLES", "SELF_ROLES",
                                                      roles)
                                v = SelfRoleView(guild=guild, page=0)
                                interaction.response.edit_message(
                                    content=Translator.translate(
                                        "assignable_roles",
                                        interaction.guild_id,
                                        server_name=guild.name,
                                        page_num=1,
                                        page_count=v.pages),
                                    view=v)
                                interaction.followup.send_message(
                                    MessageUtils.assemble(
                                        interaction.guild_id, 'WARNING',
                                        'self_role_missing'),
                                    ephemeral=True)
                            else:
                                try:
                                    if role in interaction.user.roles:
                                        await interaction.user.remove_roles(
                                            role)
                                        await interaction.response.send_message(
                                            Translator.translate(
                                                "role_left",
                                                interaction.guild_id,
                                                role_name=role.name,
                                                user=interaction.user),
                                            ephemeral=True)
                                    else:
                                        await interaction.user.add_roles(role)
                                        await interaction.response.send_message(
                                            Translator.translate(
                                                "role_joined",
                                                interaction.guild_id,
                                                role_name=role.name,
                                                user=interaction.user),
                                            ephemeral=True)
                                except disnake.Forbidden:
                                    await interaction.response.send_message(
                                        f"{Emoji.get_chat_emoji('NO')} {Translator.translate('role_too_high_add', interaction.guild_id, role=role.name)}",
                                        ephemeral=True)
                elif parts[1] == "page":
                    v = SelfRoleView(guild=interaction.guild,
                                     page=int(parts[2]))
                    await interaction.response.edit_message(
                        content=Translator.translate(
                            "assignable_roles",
                            interaction.guild_id,
                            server_name=interaction.guild.name,
                            page_num=int(parts[2]) + 1,
                            page_count=v.pages),
                        view=v)
            elif cid.startswith('help:'):
                parts = cid.split(':')
                if parts[1] == 'page':
                    q = parts[3] if parts[3] != 'None' else None
                    content, view = await Help.message_parts(
                        self.bot, q, guild, interaction.user, int(parts[2]))
                    await interaction.response.edit_message(content=content,
                                                            view=view)
                elif parts[1] == 'selector':
                    q = interaction.values[0]
                    q = q if q != 'None' else None
                    content, view = await Help.message_parts(
                        self.bot, q, guild, interaction.user, 0)
                    await interaction.response.edit_message(content=content,
                                                            view=view)
            elif cid.startswith('pager:'):
                parts = cid.split(':')
                t = parts[2]
                if t == 'eval':
                    if interaction.user.id not in Configuration.get_master_var(
                            'BOT_ADMINS'):
                        return
                    output = await self.bot.redis_pool.get(f'eval:{parts[3]}')
                    if output is None:
                        await interaction.response.send_message(
                            "Eval output no longer available", ephemeral=True)
                    else:
                        pages = Pages.paginate(output,
                                               prefix='```py\n',
                                               suffix='```')
                        content, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), interaction.guild_id,
                            f'eval:{parts[3]}')
                        await interaction.response.edit_message(
                            content=
                            f'Eval output {page_num + 1}/{len(pages)}{content}',
                            view=view)
                elif t == 'commands':
                    cog = self.bot.get_command("CustCommands")
                    if cog is not None:
                        pages = cog.get_command_pages(interaction.guild_id)
                        content, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), guild.id, 'commands')
                        page = cog.gen_command_page(pages, page_num,
                                                    interaction.guild)
                        await interaction.response.edit_message(embed=page,
                                                                view=view)
                elif t == 'emoji':
                    cog = self.bot.get_cog('Emoji')
                    if cog is not None:
                        amount = len(guild.emojis) + 1
                        content, view, page_num = SimplePager.get_parts(
                            range(amount), int(parts[1]), interaction.guild.id,
                            'emoji')
                        await interaction.response.edit_message(
                            embed=cog.gen_emoji_page(guild, page_num),
                            view=view)
                elif t == 'role_list':
                    cog = self.bot.get_cog('Moderation')
                    if cog is not None:
                        pages = cog.gen_roles_pages(interaction.guild,
                                                    parts[3])
                        content, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), guild.id,
                            f'role_list:{parts[3]}')
                        await interaction.response.edit_message(
                            content=
                            f"**{Translator.translate('roles', interaction.guild_id, server_name=guild.name, page_num=page_num + 1, pages=len(pages))}**```\n{pages[page_num]}```",
                            view=view)
                elif t == 'censor_list':
                    cog = self.bot.get_cog('Moderation')
                    if cog is not None:
                        censor_list = Configuration.get_var(
                            interaction.guild.id, "CENSORING",
                            "TOKEN_CENSORLIST")
                        pages = Pages.paginate("\n".join(censor_list))
                        page, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), interaction.guild.id,
                            'censor_list')
                        await interaction.response.edit_message(
                            content=
                            f"**{Translator.translate(f'censor_list', guild, server=guild.name, page_num=page_num + 1, pages=len(pages))}**```\n{page}```",
                            view=view)
                elif t == 'word_censor_list':
                    cog = self.bot.get_cog('Moderation')
                    if cog is not None:
                        censor_list = Configuration.get_var(
                            guild.id, "CENSORING", "WORD_CENSORLIST")
                        pages = Pages.paginate("\n".join(censor_list))
                        page, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), guild.id, 'word_censor_list')
                        await interaction.response.edit_message(
                            content=
                            f"**{Translator.translate(f'word_censor_list', guild, server=guild.name, page_num=page_num + 1, pages=len(pages))}**```\n{page}```",
                            view=view)
                elif t == 'full_censor_list':
                    cog = self.bot.get_cog('Moderation')
                    if cog is not None:
                        censor_list = Configuration.get_var(
                            guild.id, "CENSORING", "FULL_MESSAGE_LIST")
                        pages = Pages.paginate("\n".join(censor_list))
                        page, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), guild.id, 'full_censor_list')
                        await interaction.response.edit_message(
                            content=
                            f"**{Translator.translate(f'full_censor_list', guild, server=guild.name, page_num=page_num + 1, pages=len(pages))}**```\n{page}```",
                            view=view)
                elif t == 'flag_list':
                    cog = self.bot.get_cog('Moderation')
                    if cog is not None:
                        censor_list = Configuration.get_var(
                            guild.id, "FLAGGING", "TOKEN_LIST")
                        pages = Pages.paginate("\n".join(censor_list))
                        page, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), guild.id, 'flag_list')
                        await interaction.response.edit_message(
                            content=
                            f"**{Translator.translate(f'flagged_list', guild, server=guild.name, page_num=page_num + 1, pages=len(pages))}**```\n{page}```",
                            view=view)
                elif t == 'word_flag_list':
                    cog = self.bot.get_cog('Moderation')
                    if cog is not None:
                        censor_list = Configuration.get_var(
                            guild.id, "FLAGGING", "WORD_LIST")
                        pages = Pages.paginate("\n".join(censor_list))
                        page, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), guild.id, 'word_flag_list')
                        await interaction.response.edit_message(
                            content=
                            f"**{Translator.translate(f'flagged_word_list', guild, server=guild.name, page_num=page_num + 1, pages=len(pages))}**```\n{page}```",
                            view=view)
                elif t == 'mass_failures':
                    output = await self.bot.redis_pool.get(
                        f'mass_failures:{parts[3]}')
                    if output is None:
                        await interaction.response.send_message(
                            MessageUtils.assemble(interaction.guild_id, 'NO',
                                                  'view_expired'),
                            ephemeral=True)
                    else:
                        pages = Pages.paginate(output,
                                               prefix='```\n',
                                               suffix='```')
                        content, view, page_num = SimplePager.get_parts(
                            pages, int(parts[1]), interaction.guild_id,
                            f'mass_failures:{parts[3]}:{parts[4]}')
                        await interaction.response.edit_message(
                            content=
                            f"**{Translator.translate(f'mass_failures_{parts[4]}', interaction.guild_id, page_num=page_num+1, pages=len(pages))}**{content}",
                            view=view)
            elif cid.startswith('einf_search:'):
                parts = cid.split(':')
                uid = int(parts[1])
                old_page = int(parts[2])
                t = parts[3]

                if t == 'first_page':
                    page, current, pages, query, fields = await get_ephemeral_cached_page(
                        interaction, uid, 0)
                    await interaction.response.edit_message(
                        content=await InfractionUtils.assemble_message(
                            interaction.guild_id, page, query, current, pages),
                        view=EphemeralInfSearch(filters=fields,
                                                pages=pages,
                                                current_page=current,
                                                guild_id=interaction.guild_id,
                                                userid=uid))
                elif t == 'prev_page':
                    page, current, pages, query, fields = await get_ephemeral_cached_page(
                        interaction, uid, old_page - 1)
                    await interaction.response.edit_message(
                        content=await InfractionUtils.assemble_message(
                            interaction.guild_id, page, query, current, pages),
                        view=EphemeralInfSearch(filters=fields,
                                                pages=pages,
                                                current_page=current,
                                                guild_id=interaction.guild_id,
                                                userid=uid))
                elif t == 'blank':
                    await interaction.response.send_message(
                        Emoji.get_chat_emoji('AE'), ephemeral=True)
                elif t == 'next_page':
                    page, current, pages, query, fields = await get_ephemeral_cached_page(
                        interaction, uid, old_page + 1)
                    await interaction.response.edit_message(
                        content=await InfractionUtils.assemble_message(
                            interaction.guild_id, page, query, current, pages),
                        view=EphemeralInfSearch(filters=fields,
                                                pages=pages,
                                                current_page=current,
                                                guild_id=interaction.guild_id,
                                                userid=uid))
                elif t == 'last_page':
                    page, current, pages, query, fields = await get_ephemeral_cached_page(
                        interaction, uid, 1000)
                    await interaction.response.edit_message(
                        content=await InfractionUtils.assemble_message(
                            interaction.guild_id, page, query, current, pages),
                        view=EphemeralInfSearch(filters=fields,
                                                pages=pages,
                                                current_page=current,
                                                guild_id=interaction.guild_id,
                                                userid=uid))
        elif interaction.type == InteractionType.application_command:
            if interaction.data.name == "Extract user IDs":
                self.bot.metrics.uid_usage.labels(
                    type="channel", cluster=self.bot.cluster).inc()
                await interaction.response.defer(ephemeral=True)
                parts = await Utils.get_user_ids(interaction.target.content)
                if len(parts) > 0:
                    for chunk in Pages.paginate("\n".join(parts), 200):
                        await interaction.followup.send(chunk)
                else:
                    await interaction.followup.send(
                        MessageUtils.assemble(interaction.guild, "NO",
                                              "no_uids_found"))
            elif interaction.data.name == "Send user IDs to DM":
                self.bot.metrics.uid_usage.labels(
                    type="DM", cluster=self.bot.cluster).inc()
                await interaction.response.defer(ephemeral=True)
                parts = await Utils.get_user_ids(interaction.target.content)
                if len(parts) > 0:
                    try:
                        for chunk in Pages.paginate("\n".join(parts), 200):
                            await interaction.user.send(chunk)
                    except Forbidden:
                        await interaction.followup.send("Unable to send DM")
                    else:
                        await interaction.followup.send("IDs sent in DM")
                else:
                    try:
                        await interaction.user.send(
                            MessageUtils.assemble(interaction.guild, "NO",
                                                  "no_uids_found"))
                    except Forbidden:
                        await interaction.followup.send("Unable to send DM")
                    else:
                        await interaction.followup.send("IDs sent in DM")
            elif interaction.data.name == "Userinfo":
                if await Permissioncheckers.check_permission(
                        self.bot.get_command("userinfo"), interaction.guild,
                        interaction.user, self.bot):
                    t = "allowed"
                    target = interaction.data.target
                    embed = await Utils.generate_userinfo_embed(
                        target, target if isinstance(target, Member) else None,
                        interaction.guild, interaction.user)
                    await interaction.response.send_message(embed=embed,
                                                            ephemeral=True)
                else:
                    t = "denied"
                    await interaction.response.send_message(
                        MessageUtils.assemble(interaction.guild, 'LOCK',
                                              'permission_denied'),
                        ephemeral=True)
                self.bot.metrics.userinfo_usage.labels(
                    type=t, cluster=self.bot.cluster).inc()
            elif interaction.data.name == "Search Infractions":
                if await Permissioncheckers.check_permission(
                        self.bot.get_command("inf search"), interaction.guild,
                        interaction.user, self.bot):
                    uid = interaction.data.target.id
                    t = "allowed"
                    await interaction.response.send_message(
                        MessageUtils.assemble(interaction.guild, 'SEARCH',
                                              'inf_search_compiling'),
                        ephemeral=True)

                    pages = await InfractionUtils.fetch_infraction_pages(
                        interaction.guild.id, uid, 100,
                        ["[user]", "[mod]", "[reason]"], 0)
                    page = await self.bot.wait_for(
                        'page_assembled',
                        check=lambda l: l['key'] == get_key(
                            interaction.guild.id, uid, [
                                "[user]", "[mod]", "[reason]"
                            ], 100) and l['page_num'] == 0)
                    await interaction.edit_original_message(
                        content=await InfractionUtils.assemble_message(
                            interaction.guild.id, page['page'], uid, 0, pages),
                        view=EphemeralInfSearch(
                            filters=["[user]", "[mod]", "[reason]"],
                            pages=pages,
                            guild_id=interaction.guild.id,
                            userid=uid))
                else:
                    t = "denied"
                    await interaction.response.send_message(
                        MessageUtils.assemble(interaction.guild, 'LOCK',
                                              'permission_denied'),
                        ephemeral=True)
                self.bot.metrics.inf_search_usage.labels(
                    type=t, cluster=self.bot.cluster).inc()
async def updater(cog: BCVersionChecker):
    GearbotLogging.info("Started BC version checking background task")
    session: aiohttp.ClientSession = cog.bot.aiosession
    lastUpdate = 0
    while cog.running:
        try:
            # check for a newer bc version
            async with session.get(
                    'https://www.mod-buildcraft.com/build_info_full/last_change.txt'
            ) as reply:
                stamp = await reply.text()
                stamp = int(stamp[:-1])
                if stamp > lastUpdate:
                    GearbotLogging.info("New BC version somewhere!")
                    lastUpdate = stamp
                    cog.BC_VERSION_LIST = await getList(session, "BuildCraft")
                    cog.BCC_VERSION_LIST = await getList(
                        session, "BuildCraftCompat")
                    highestMC = VersionInfo.getLatest(
                        cog.BC_VERSION_LIST.keys())
                    latestBC = VersionInfo.getLatest(
                        cog.BC_VERSION_LIST[highestMC])
                    generalID = 309218657798455298
                    channel: discord.TextChannel = cog.bot.get_channel(
                        generalID)
                    old_latest = Configuration.get_persistent_var(
                        "latest_bc", "0.0.0")
                    Configuration.set_persistent_var(
                        "latest_bc", latestBC
                    )  # save already so we don't get stuck and keep trying over and over if something goes wrong
                    if channel is not None and latestBC != old_latest:
                        GearbotLogging.info(
                            f"New BuildCraft version found: {latestBC}")
                        notify_channel = cog.bot.get_channel(
                            349517224320565258)
                        await notify_channel.send(
                            f"{Emoji.get_chat_emoji('WRENCH')} New BuildCraft version detected ({latestBC})"
                        )
                        GearbotLogging.info(
                            f"Fetching metadata for BuildCraft {latestBC}")
                        message = await notify_channel.send(
                            f"{Emoji.get_chat_emoji('REFRESH')} Fetching metadata..."
                        )
                        info = await cog.getVersionDetails(
                            "BuildCraft", latestBC)
                        GearbotLogging.info(f"Metadata acquired: {info}")
                        await message.edit(
                            content=
                            f"{Emoji.get_chat_emoji('YES')} Metadata acquired")
                        if 'blog_entry' in info:
                            message = await notify_channel.send(
                                f"{Emoji.get_chat_emoji('REFRESH')} Updating general topic..."
                            )
                            newTopic = f"General discussions about BuildCraft.\n" \
                                f"Latest version: {latestBC}\n" \
                                f"Full changelog and download: {info['blog_entry']}"
                            await channel.edit(topic=newTopic)
                            await message.edit(
                                content=
                                f"{Emoji.get_chat_emoji('YES')} Topic updated")
                        else:
                            notify_channel.send(
                                f"{Emoji.get_chat_emoji('WARNING')} No blog post data found, notifying <@180057061353193472>"
                            )

                        # message = await notify_channel.send(f"{Emoji.get_chat_emoji('REFRESH')} Uploading files to CurseForge...")
                        # code, output, errors = await Utils.execute(f'cd BuildCraft/uploader && gradle curseforge -Pnew_version="{latestBC}"')
                        # GearbotLogging.info(f"Upload to CF complete\n)------stdout------\n{output}\n------stderr------\n{errors}")
                        # if code is 0:
                        #     content = f"{Emoji.get_chat_emoji('YES')} All archives successfully uploaded"
                        #     await message.edit(content=content)
                        # else:
                        #     content = f"{Emoji.get_chat_emoji('NO')} Upload failed with code {code}, notifying <@106354106196570112>"
                        #     await notify_channel.send(content)

            # update FAQs if needed
            async with session.get(
                    'https://mod-buildcraft.com/website_src/faq.md') as reply:
                data = await reply.text()
                h = hashlib.md5(data.encode('utf-8')).hexdigest()
                old = Configuration.get_persistent_var("BCFAQ", "")
                channel = cog.bot.get_channel(361557801492938762)  # FAQs
                if channel is not None and h != old:
                    Configuration.set_persistent_var("BCFAQ", h)
                    #clean the old stuff
                    await channel.purge()

                    #send banner
                    with open("BuildCraft/FAQs.png", "rb") as file:
                        await channel.send(file=File(file, filename="FAQs.png")
                                           )
                    #send content
                    out = ""
                    parts = [
                        d.strip("#").strip() for d in data.split("##")[1:]
                    ]
                    for part in parts:
                        lines = part.splitlines()
                        content = '\n'.join(lines[1:])
                        out += f"**```{lines[0].strip()}```**{content}\n"
                    for page in Pages.paginate(out,
                                               max_chars=2048,
                                               max_lines=50):
                        embed = Embed(description=page)
                        await channel.send(embed=embed)

                pass
        except CancelledError:
            pass  # bot shutdown
        except Exception as ex:
            cog.bot.errors = cog.bot.errors + 1
            GearbotLogging.error(
                "Something went wrong in the BC version checker task")
            GearbotLogging.error(traceback.format_exc())
            embed = discord.Embed(colour=discord.Colour(0xff0000),
                                  timestamp=datetime.datetime.utcfromtimestamp(
                                      time.time()))
            embed.set_author(
                name="Something went wrong in the BC version checker task:")
            embed.add_field(name="Exception", value=str(ex))
            v = ""
            for line in traceback.format_exc().splitlines():
                if len(v) + len(line) >= 1024:
                    embed.add_field(name="Stacktrace", value=v)
                    v = ""
                v = f"{v}\n{line}"
            if len(v) > 0:
                embed.add_field(name="Stacktrace", value=v)
            await GearbotLogging.bot_log(embed=embed)
        for i in range(1, 60):
            if cog.force or not cog.running:
                break
            await asyncio.sleep(10)

    GearbotLogging.info("BC version checking background task terminated")
Exemple #19
0
async def handle_exception(exception_type,
                           bot,
                           exception,
                           event=None,
                           message=None,
                           ctx=None,
                           *args,
                           **kwargs):
    if bot is not None:
        bot.errors = bot.errors + 1
    with sentry_sdk.push_scope() as scope:
        embed = Embed(colour=Colour(0xff0000),
                      timestamp=datetime.utcfromtimestamp(time.time()))

        # something went wrong and it might have been in on_command_error, make sure we log to the log file first
        lines = [
            "\n===========================================EXCEPTION CAUGHT, DUMPING ALL AVAILABLE INFO===========================================",
            f"Type: {exception_type}"
        ]

        arg_info = ""
        for arg in list(args):
            arg_info += extract_info(arg) + "\n"
        if arg_info == "":
            arg_info = "No arguments"

        kwarg_info = ""
        for name, arg in kwargs.items():
            kwarg_info += "{}: {}\n".format(name, extract_info(arg))
        if kwarg_info == "":
            kwarg_info = "No keyword arguments"

        lines.append("======================Exception======================")
        lines.append(f"{str(exception)} ({type(exception)})")

        lines.append("======================ARG INFO======================")
        lines.append(arg_info)
        sentry_sdk.add_breadcrumb(category='arg info',
                                  message=arg_info,
                                  level='info')

        lines.append("======================KWARG INFO======================")
        lines.append(kwarg_info)
        sentry_sdk.add_breadcrumb(category='kwarg info',
                                  message=kwarg_info,
                                  level='info')

        lines.append("======================STACKTRACE======================")
        tb = "".join(traceback.format_tb(exception.__traceback__))
        lines.append(tb)

        if message is None and event is not None and hasattr(event, "message"):
            message = event.message

        if message is None and ctx is not None:
            message = ctx.message

        if message is not None and hasattr(message, "content"):
            lines.append(
                "======================ORIGINAL MESSAGE======================")
            lines.append(message.content)
            if message.content is None or message.content == "":
                content = "<no content>"
            else:
                content = message.content
            scope.set_tag('message content', content)
            embed.add_field(name="Original message",
                            value=Utils.trim_message(content, 1000),
                            inline=False)

            lines.append(
                "======================ORIGINAL MESSAGE (DETAILED)======================"
            )
            lines.append(extract_info(message))

        if event is not None:
            lines.append(
                "======================EVENT NAME======================")
            lines.append(event)
            scope.set_tag('event name', event)
            embed.add_field(name="Event", value=event)

        if ctx is not None:
            lines.append(
                "======================COMMAND INFO======================")

            lines.append(f"Command: {ctx.command.name}")
            embed.add_field(name="Command", value=ctx.command.name)
            scope.set_tag('command', ctx.command.name)

            channel_name = 'Private Message' if isinstance(
                ctx.channel,
                PrivateChannel) else f"{ctx.channel.name} (`{ctx.channel.id}`)"
            lines.append(f"Channel: {channel_name}")
            embed.add_field(name="Channel", value=channel_name, inline=False)
            scope.set_tag('channel', channel_name)

            sender = f"{str(ctx.author)} (`{ctx.author.id}`)"
            scope.user = dict(id=ctx.author.id, username=str(ctx.author))
            lines.append(f"Sender: {sender}")
            embed.add_field(name="Sender", value=sender, inline=False)

        lines.append(
            "===========================================DATA DUMP COMPLETE==========================================="
        )
        GearbotLogging.error("\n".join(lines))

        for t in [ConnectionClosed, ClientOSError, ServerDisconnectedError]:
            if isinstance(exception, t):
                return
        #nice embed for info on discord

        embed.set_author(name=exception_type)
        embed.add_field(name="Exception",
                        value=f"{str(exception)} (`{type(exception)}`)",
                        inline=False)
        parts = Pages.paginate(tb, max_chars=1024)
        num = 1
        for part in parts:
            embed.add_field(name=f"Traceback {num}/{len(parts)}", value=part)
            num += 1
        sentry_sdk.capture_exception(exception)
    # try logging to botlog, wrapped in an try catch as there is no higher lvl catching to prevent taking down the bot (and if we ended here it might have even been due to trying to log to botlog
    try:
        await GearbotLogging.bot_log(embed=embed)
    except Exception as ex:
        GearbotLogging.error(
            f"Failed to log to botlog, either Discord broke or something is seriously wrong!\n{ex}"
        )
        GearbotLogging.error(traceback.format_exc())
Exemple #20
0
async def send_buffer(channel, buffer):
    pages = Pages.paginate(buffer, max_lines=500)
    for page in pages:
        await channel.send(page)
Exemple #21
0
 async def _blacklist_update(ctx, message, page_num, action, data):
     pages = Pages.paginate("\n".join(Configuration.get_var(ctx.guild.id, "WORD_BLACKLIST")))
     page, page_num = Pages.basic_pages(pages, page_num, action)
     return f"**{Translator.translate(f'blacklist_list', ctx, server=message.channel.guild.name, page_num=page_num + 1, pages=len(pages))}**```\n{page}```", None, page_num