示例#1
0
    async def slash_factoid(self,
                            ctx: ApplicationCommandInteraction,
                            mention: Member = None):
        if not self.bot.is_supporter(ctx.author) and self.limiter.is_limited(
                ctx.data.id, ctx.channel_id):
            logger.debug(
                f'rate-limited (sc): "{ctx.author}", channel: "{ctx.channel}", factoid: "{ctx.data.name}"'
            )
            return

        logger.info(
            f'factoid requested (sc) by: "{ctx.author}", channel: "{ctx.channel}", factoid: "{ctx.data.name}"'
        )
        await self.increment_uses(ctx.data.name)
        message = self.resolve_variables(
            self.factoids[ctx.data.name]['message'])

        embed = None
        if self.factoids[ctx.data.name]['embed']:
            embed = Embed(colour=self._factoids_colour, description=message)
            message = ''
            if self.factoids[ctx.data.name]['image_url']:
                embed.set_image(url=self.factoids[ctx.data.name]['image_url'])

        if mention and isinstance(mention, Member):
            return await ctx.send(content=f'{mention.mention} {message}',
                                  embed=embed)
        else:
            return await ctx.send(content=message, embed=embed)
示例#2
0
 def vip(self, streamer: Streamer, info, mod_action: ModAction,
         embed: disnake.Embed) -> disnake.Embed:
     embed = self.set_user_attrs(streamer, info, mod_action, embed)
     embed.title = embed.title.replace('Vip',
                                       'VIP')  #Capitalize VIP for the looks
     embed.colour = self.colour.green
     return True, embed
示例#3
0
    async def sub_unsub_group_helper(
        self, ctx: Context, func: Callable, action: str
    ) -> None:
        """
        Helper function for subscribe_group and unsubscribe_group.

        If `func` is `apply_role`, `role_lst` stores the role(s) which are added to the user
        If `func` is `remove_role`, `role_lst` stores the role(s) which are removed from the user
        """
        roles = await self.get_roles(ctx)
        role_lst = [
            role.name for role in roles if await func(ctx, role)
        ]  # Applies/Removes the role(s) and stores a list of applied/removed role(s)
        if role_lst:
            msg = (
                f"{', '.join(role_lst[:-1])} and {role_lst[-1]}"
                if len(role_lst) > 1
                else role_lst[0]
            )  # Stores a string which tells what role(s) is/are added to or removed from the user
            embed = Embed(
                title=f"{Emojis.confirmation_emoji} {action}",
                description=f"You've {action.lower()} to {ctx.guild}'s {msg}.",
                color=Colours.green,
            )
        else:
            embed = Embed(
                title=f"{Emojis.warning_emoji} Already {action.lower()}",
                description=f"You're already {action.lower()} to {ctx.guild}'s announcements and polls.",
                color=Colours.soft_red,
            )
        await ctx.send(content=ctx.author.mention, embed=embed)
示例#4
0
    async def gurkan_count(self, ctx: Context) -> None:
        """
        Goes through a list of all the members and uses regex to check if the member is a gurkan.

        Sends the count of total Gurkans in the server,\
        and the percentage of the gurkans to the server members.
        """
        members = ctx.guild.members
        gurkans = sum(gurkan_check(member.display_name) for member in members)
        rate = round((gurkans / len(members)) * 100)

        count_emb = Embed()

        if rate == 100:
            title = f"Whoa!! All {gurkans} members are gurkans!"
            color = Colours.green

        elif rate == 0:
            title = "No one is a gurkan?! That's lame."
            color = Colours.soft_red

        else:
            rate_m = [RATE_DICT[r] for r in RATE_DICT if rate in r][0]

            title = f"{Emojis.cucumber_emoji} {gurkans} members"
            color = Colours.green
            description = f"About {rate}% ({gurkans}/ {len(members)}) of members are gurkans, that's {rate_m}"

        count_emb.title = title
        count_emb.color = color
        count_emb.description = description

        await ctx.send(embed=count_emb)
示例#5
0
文件: Emoji.py 项目: gearbot/GearBot
    def gen_emoji_page(self, guild: disnake.Guild, page):
        se = sorted(guild.emojis, key=lambda e: e.name)

        embed = Embed(color=0x2db1f3)
        embed.set_author(name=Translator.translate('emoji_server',
                                                   guild,
                                                   server=guild.name,
                                                   page=page + 1,
                                                   pages=len(guild.emojis) +
                                                   1),
                         url=guild.icon.url)
        if page == 0:
            for chunk in Utils.chunks(se, 18):
                embed.add_field(name="\u200b",
                                value=" ".join(str(e) for e in chunk))
            animated = set()
            static = set()
            for e in guild.emojis:
                (animated if e.animated else static).add(str(e))
            max_emoji = guild.emoji_limit
            embed.add_field(name=Translator.translate('static_emoji', guild),
                            value=f"{len(static)} / {max_emoji}")
            embed.add_field(name=Translator.translate('animated_emoji', guild),
                            value=f"{len(animated)} / {max_emoji}")
        else:
            self.add_emoji_info(guild, embed, se[page - 1])

        return embed
示例#6
0
    async def is_gurkan(self, ctx: Context, *,
                        user: Optional[Union[Member, str]]) -> None:
        """
        The gurkanrate of the user and whether the user is a gurkan is sent in an embed,\
        the color depending on how high the rate is.

        Can be used on other members, or even text.
        """
        if not isinstance(user, str):
            user = user.display_name if user else ctx.author.display_name

        gurk_state = gurkan_check(user)
        gurk_rate = gurkan_rate(user)
        rate_embed = Embed(description=f"{user}'s gurk rate is {gurk_rate}%")

        if not gurk_state:
            color = Colours.soft_red
            title = f"{Emojis.invalid_emoji} Not gurkan"
        else:
            color = Colours.green
            title = f"{Emojis.cucumber_emoji} Gurkan"

        rate_embed.color = color
        rate_embed.title = title

        await ctx.send(embed=rate_embed)
示例#7
0
    async def post_formatted_message(
        self,
        actor: User,
        action: str,
        *,
        body: Optional[str] = None,
        link: Optional[str] = None,
        colour: int = Colours.green,
    ) -> None:
        """Format and post a message to the #log channel."""
        logger.trace(f'Creating log "{actor.id} {action}"')

        embed = Embed(
            title=(
                f"{actor} "
                f"{f'({actor.display_name}) ' if actor.display_name != actor.name else ''}"
                f"({actor.id}) {action}"
            ),
            description=body or "<no additional information provided>",
            colour=colour,
            timestamp=datetime.utcnow(),
        ).set_thumbnail(url=actor.display_avatar.url)

        if link:
            embed.url = link

        await self.post_message(embed=embed)
示例#8
0
文件: utils.py 项目: gurkult/gurkbot
    async def charinfo(self, ctx: Context, *, characters: str) -> None:
        """Shows you information about up to 50 unicode characters."""
        match = re.match(r"<(a?):(\w+):(\d+)>", characters)
        if match:
            raise BadArgument(
                "Only unicode characters can be processed, but a custom Discord emoji "
                "was found. Please remove it and try again.",
            )
        if len(characters) > 50:
            raise BadArgument(f"Too many characters ({len(characters)}/50)")

        def get_info(char: str) -> Tuple[str, str]:
            digit = f"{ord(char):x}"
            if len(digit) <= 4:
                u_code = f"\\u{digit:>04}"
            else:
                u_code = f"\\U{digit:>08}"
            url = f"https://www.compart.com/en/unicode/U+{digit:>04}"
            name = f"[{unicodedata.name(char, '')}]({url})"
            info = f"`{u_code.ljust(10)}`: {name} - {utils.escape_markdown(char)}"
            return info, u_code

        char_list, raw_list = zip(*(get_info(c) for c in characters))
        embed = Embed(title="Character info", colour=Colours.green)

        if len(characters) > 1:
            # Maximum length possible is 502 out of 1024, so there's no need to truncate.
            embed.add_field(
                name="Full Raw Text", value=f"`{''.join(raw_list)}`", inline=False
            )

        await LinePaginator.paginate(
            char_list, ctx, embed, max_lines=10, max_size=2000, empty=False
        )
示例#9
0
    async def append_reminder(self, timestamp: datetime, ctx: Context,
                              content: str) -> None:
        """Add reminder to database and schedule it."""
        sql = (
            "INSERT INTO reminders(jump_url, user_id, channel_id, end_time, content) "
            "VALUES ($1, $2, $3, $4, $5)RETURNING reminder_id")
        async with self.bot.db_pool.acquire() as connection:
            reminder_id = await connection.fetchval(
                sql,
                ctx.message.jump_url,
                ctx.author.id,
                ctx.channel.id,
                timestamp,
                content,
            )

        embed = Embed(
            title=":white_check_mark:  Reminder set",
            color=Colours.green,
            description=REMINDER_DESCRIPTION.format(
                arrive_in=humanize.precisedelta(timestamp - datetime.utcnow(),
                                                format="%0.0f"), ),
        )
        embed.set_footer(text=f"ID: {reminder_id}")
        await ctx.send(embed=embed)
        self.reminders[reminder_id] = {
            "reminder_id": reminder_id,
            "jump_url": ctx.message.jump_url,
            "user_id": ctx.author.id,
            "channel_id": ctx.channel.id,
            "end_time": timestamp,
            "content": content,
        }

        await self.schedule_reminder(self.get_recent_reminder())
示例#10
0
 def raid(self, streamer: Streamer, info, mod_action: ModAction,
          embed: disnake.Embed) -> disnake.Embed:
     embed = self.set_chatroom_attrs(mod_action, embed)
     embed.add_field(
         name="Raided Channel",
         value=
         f"[{info['args'][0]}](<https://www.twitch.tv/{info['args'][0]}>)",
         inline=True)
     return embed
示例#11
0
 async def unused(self, ctx: Context):
     embed = Embed(title='Unused Factoids')
     description = []
     for fac in sorted(self.factoids.values(), key=lambda a: a['uses']):
         if fac['uses'] > 0:
             break
         description.append(f'- {fac["name"]}')
     embed.description = '```{}```'.format('\n'.join(description))
     return await ctx.send(embed=embed)
示例#12
0
 async def startup_greeting(self) -> None:
     """Announce presence to the devlog channel."""
     embed = Embed(description="Connected!")
     embed.set_author(
         name="Gurkbot",
         url=constants.BOT_REPO_URL,
         icon_url=self.user.display_avatar.url,
     )
     await self.get_channel(constants.Channels.devlog).send(embed=embed)
示例#13
0
 def followers(self, streamer: Streamer, info, mod_action: ModAction,
               embed: disnake.Embed) -> disnake.Embed:
     embed = self.set_chatroom_attrs(mod_action, embed)
     embed.add_field(
         name=
         f"Time Needed to be Following (minute{'' if int(info['args'][0]) == 1 else 's'})",
         value=f"`{info['args'][0]}`",
         inline=True)
     return embed
示例#14
0
 def slow(self, streamer: Streamer, info, mod_action: ModAction,
          embed: disnake.Embed) -> disnake.Embed:
     embed = self.set_chatroom_attrs(mod_action, embed)
     embed.add_field(
         name=
         f"Slow Amount (second{'' if int(info['args'][0]) == 1 else 's'})",
         value=f"`{info['args'][0]}`",
         inline=True)
     return embed
示例#15
0
 def set_appeals_attrs(self, streamer: Streamer, info,
                       mod_action: ModAction,
                       embed: disnake.Embed) -> disnake.Embed:
     self.set_user_attrs(streamer, info, mod_action, embed)
     embed.add_field(
         name="Moderator Reason",
         value=
         f"`{info['moderator_message'] if info['moderator_message'] != '' else 'None Provided'}`",
         inline=False)
     return embed
示例#16
0
 def embed_helper(self, description: str, field: str) -> Embed:
     """Embed helper function."""
     embed = Embed(title="Eval Results",
                   colour=self.GREEN,
                   description=description)
     embed.add_field(
         name="Output",
         value=field,
     )
     return embed
示例#17
0
 def delete(self, streamer: Streamer, info, mod_action: ModAction,
            embed: disnake.Embed) -> disnake.Embed:
     embed = self.set_user_attrs(streamer, info, mod_action, embed)
     if "`" in info['args'][1]:
         embed.add_field(name="Message", value=f"```{info['args'][1]}```")
     else:
         embed.add_field(name="Message", value=f"`{info['args'][1]}`")
     # embed.add_field(
     #     name="Message ID", value=f"`{info['args'][2]}`")
     return embed
示例#18
0
 async def _send_paginated_embed(ctx: Context, lines: Iterable[str],
                                 title: str) -> None:
     """Send paginated embed."""
     embed = Embed()
     embed.set_author(name=title)
     await LinePaginator.paginate(
         [f"{i}. {line}" for i, line in enumerate(lines, start=1)],
         ctx,
         embed,
         allow_empty_lines=True,
     )
示例#19
0
 async def bottom(self, ctx: Context):
     embed = Embed(title='Least used Factoids')
     description = [
         'Pos - Factoid (uses)', '--------------------------------'
     ]
     for pos, fac in enumerate(sorted(self.factoids.values(),
                                      key=lambda a: a['uses'])[:10],
                               start=1):
         description.append(f'{pos:2d}. - {fac["name"]} ({fac["uses"]})')
     embed.description = '```{}```'.format('\n'.join(description))
     return await ctx.send(embed=embed)
示例#20
0
 def set_user_attrs(self, streamer: Streamer, info, mod_action: ModAction,
                    embed: disnake.Embed) -> disnake.Embed:
     user = info["target_user_login"] or info['args'][0]
     user_escaped = user.lower().replace('_', '\_')
     embed.title = f"Mod {mod_action.value.replace('_', ' ').title()} Action"
     #embed.description=f"[Review Viewercard for User](<https://www.twitch.tv/popout/{streamer.username}/viewercard/{user.lower()}>)"
     embed.color = self.colour.red
     embed.add_field(
         name="Flagged Account",
         value=
         f"[{user_escaped}](<https://www.twitch.tv/popout/{streamer.username}/viewercard/{user_escaped}>)",
         inline=True)
     return embed
示例#21
0
def add_author_footer(embed: discord.Embed,
                      author: Union[discord.User, discord.Member],
                      set_timestamp=True,
                      additional_text: Union[Iterable[str], None] = None):
    if set_timestamp:
        embed.timestamp = datetime.now(tz=timezone.utc)

    if additional_text is not None:
        embed.set_footer(icon_url=author.display_avatar.url,
                         text=' | '.join((str(author), *additional_text)))
    else:
        embed.set_footer(icon_url=author.display_avatar.url, text=str(author))

    return embed
示例#22
0
    async def listfilters(self, ctx: Context):
        if not self.bot.is_admin(ctx.author):
            return
        if not self.bot.is_private(ctx.channel):
            return

        _ban_filters = []
        _kick_filters = []
        _delete_filters = []
        for name, regex in sorted(self.filters.items()):
            if name in self.bannable:
                _ban_filters.append(f'* "{name}" - `{regex.pattern}`')
            elif name in self.kickable:
                _kick_filters.append(f'* "{name}" - `{regex.pattern}`')
            else:
                _delete_filters.append(f'* "{name}" - `{regex.pattern}`')

        embed = Embed(title='Registered Message Filters')
        if _ban_filters:
            embed.add_field(name='Ban Filters',
                            inline=False,
                            value='```\n{}\n```'.format(
                                '\n'.join(_ban_filters)))
        if _kick_filters:
            embed.add_field(name='Kick Filters',
                            inline=False,
                            value='```\n{}\n```'.format(
                                '\n'.join(_kick_filters)))
        if _delete_filters:
            embed.add_field(name='Delete Filters',
                            inline=False,
                            value='```\n{}\n```'.format(
                                '\n'.join(_delete_filters)))

        return await ctx.send(embed=embed)
示例#23
0
    async def status(self, ctx: Context):
        if not self.bot.is_admin(ctx.author):
            return

        embed = Embed(title='OBS Bot Status')
        embed.add_field(
            name='Core',
            inline=False,
            value=(
                f'Version:  {__version__} - "{__codename__}" Edition\n'
                f'Uptime:  {time.time() - self.bot.start_time:.0f} seconds\n'))

        mentions = ', '.join(u.mention for u in (self.bot.get_user(_id)
                                                 for _id in self.bot.admins)
                             if u)
        embed.add_field(name='Bot admins', inline=False, value=mentions)

        # get information from other Cogs if possible
        if fac := self.bot.get_cog('Factoids'):
            total_uses = sum(i['uses'] for i in fac.factoids.values())
            embed.add_field(
                name='Factoid module',
                inline=False,
                value=(f'Factoids:  {len(fac.factoids)}\n'
                       f'Aliases:  {len(fac.alias_map)}\n'
                       f'Total uses:  {total_uses} (since 2018-06-07)'))
示例#24
0
async def ask(ctx, text, options, timeout=60):
    embed = Embed(color=0x68a910,
                  description='\n'.join(f"{option.emoji} {option.text}"
                                        for option in options))
    message = await ctx.send(text, embed=embed)
    handlers = dict()
    for option in options:
        await message.add_reaction(option.emoji)
        handlers[str(option.emoji)] = option.handler

    def check(reaction):
        return reaction.user_id == ctx.message.author.id and str(
            reaction.emoji) in handlers.keys(
            ) and reaction.message_id == message.id

    try:
        reaction = await ctx.bot.wait_for('raw_reaction_add',
                                          timeout=timeout,
                                          check=check)
    except asyncio.TimeoutError:
        await MessageUtils.send_to(ctx,
                                   "NO",
                                   "confirmation_timeout",
                                   timeout=30)
        return
    else:
        await handlers[str(reaction.emoji)]()
    finally:
        try:
            await message.delete()
        except NotFound:
            pass
示例#25
0
文件: Emoji.py 项目: gearbot/GearBot
 async def emoji_roles_remove(self, ctx, emote: disnake.Emoji,
                              roles: Greedy[disnake.Role]):
     if roles is None:
         return MessageUtils.send_to(ctx, 'NO', 'roles_no_roles')
     todo = set()
     refused = set()
     for role in roles:
         (refused if role not in emote.roles else todo).add(role)
     new_roles = list(emote.roles)
     for role in todo:
         new_roles.remove(role)
     await emote.edit(name=emote.name, roles=new_roles)
     await asyncio.sleep(1)  # sleep so the cache can update
     embed = Embed(color=0x2db1f3)
     self.add_emoji_info(ctx, embed, emote)
     message = MessageUtils.assemble(ctx,
                                     "YES",
                                     "emoji_roles_remove_success",
                                     roles=self.pretty_role_list(todo, ctx))
     if len(refused) > 0:
         message += "\n" + MessageUtils.assemble(
             ctx,
             "NO",
             "emoji_roles_remove_role_not_in_list",
             roles=self.pretty_role_list(refused, ctx))
     await ctx.send(message)
示例#26
0
    async def on_message(self, message: Message) -> None:
        """Log DM messages to #dm-logs."""
        # If the guild attribute is set it isn't a DM
        if message.guild:
            return

        # Outbound messages shouldn't be logged
        if message.author.id == self.bot.user.id:
            return

        if not self.dm_log_channel:
            await self.bot.wait_until_ready()
            self.dm_log_channel = await self.bot.fetch_channel(Channels.dm_log)

            if not self.dm_log_channel:
                logger.error(
                    f"Failed to get the #dm-log channel with ID {Channels.dm_log}."
                )
                return

        await self.dm_log_channel.send(
            embed=Embed(
                title=f"Direct message from {message.author}",
                description=message.content,
                colour=Colours.green,
                timestamp=datetime.utcnow(),
            ).set_thumbnail(url=message.author.display_avatar.url)
        )
示例#27
0
async def create_self_roles(bot, ctx):
    # create and send
    pages = gen_role_pages(ctx.guild)
    embed = Embed(title=Translator.translate("assignable_roles",
                                             ctx,
                                             server_name=ctx.guild.name,
                                             page_num=1,
                                             page_count=len(pages)),
                  colour=Colour(0xbffdd),
                  description=pages[0])
    message = await ctx.send(embed=embed)
    # track in redis
    pipe = bot.redis_pool.pipeline()
    pipe.sadd(f"self_role:{ctx.guild.id}", message.id)
    pipe.expire(f"self_role:{ctx.guild.id}", 60 * 60 * 24 * 7)
    bot.loop.create_task(
        ReactionManager.register(bot,
                                 message.id,
                                 ctx.channel.id,
                                 "self_role",
                                 duration=60 * 60 * 24 * 7,
                                 pipe=pipe))
    bot.loop.create_task(update_reactions(message, pages[0], len(pages) > 1))

    # cleanup
    bot.loop.create_task(self_cleaner(bot, ctx.guild.id))
示例#28
0
文件: xkcd.py 项目: gurkult/gurkbot
    async def fetch_xkcd_comics(self, ctx: Context,
                                comic: Optional[str]) -> None:
        """
        Getting an xkcd comic's information along with the image.

        To get a random comic, don't type any number as an argument. To get the latest, type 'latest'.
        """
        embed = Embed(title=f"XKCD comic '{comic}'")

        embed.colour = Colours.soft_red

        if comic and (comic := re.match(COMIC_FORMAT, comic)) is None:
            embed.description = (
                "Comic parameter should either be an integer or 'latest'.")
            await ctx.send(embed=embed)
            return
示例#29
0
 async def ping(self, ctx: commands.Context) -> None:
     """Ping the bot to see its latency."""
     embed = Embed(
         title="Pong!",
         description=f"Gateway Latency: {round(self.bot.latency * 1000)}ms",
         color=Colours.green,
     )
     await ctx.send(content=ctx.author.mention, embed=embed)
示例#30
0
    async def handle_unexpected_error(self, ctx: commands.Context,
                                      error: commands.CommandError) -> None:
        """Send a generic error message in `ctx` and log the exception as an error with exc_info."""
        await ctx.send(
            f"Sorry, an unexpected error occurred. Please let us know!\n\n"
            f"```{error.__class__.__name__}: {error}```")

        push_alert = Embed(
            title="An unexpected error occurred",
            color=Colours.soft_red,
        )
        push_alert.add_field(
            name="User",
            value=f"id: {ctx.author.id} | username: {ctx.author.mention}",
            inline=False,
        )
        push_alert.add_field(name="Command",
                             value=ctx.command.qualified_name,
                             inline=False)
        push_alert.add_field(
            name="Message & Channel",
            value=
            f"Message: [{ctx.message.id}]({ctx.message.jump_url}) | Channel: <#{ctx.channel.id}>",
            inline=False,
        )
        push_alert.add_field(name="Full Message",
                             value=ctx.message.content,
                             inline=False)

        dev_alerts = self.bot.get_channel(Channels.devalerts)
        if dev_alerts is None:
            logger.info(
                f"Fetching dev-alerts channel as it wasn't found in the cache (ID: {Channels.devalerts})"
            )
            try:
                dev_alerts = await self.bot.fetch_channel(Channels.devalerts)
            except disnake.HTTPException as discord_exc:
                logger.exception("Fetch failed", exc_info=discord_exc)
                return

        # Trigger the logger before trying to use Discord in case that's the issue
        logger.error(
            f"Error executing command invoked by {ctx.message.author}: {ctx.message.content}",
            exc_info=error,
        )
        await dev_alerts.send(embed=push_alert)