Esempio n. 1
0
 async def learn_markov_from_history(self, channel: discord.TextChannel):
     if channel.permissions_for(channel.guild.me).read_message_history:
         await channel.history(limit=5000).map(self.learn_markov).flatten()
         self.log_info('Markov: Initialized channel %s', channel)
         return True
     self.log_error('Markov: missing ReadMessageHistory permission for %s', channel)
     return False
Esempio n. 2
0
    async def modlog(self, ctx: commands.Context, channel: discord.TextChannel = None):
        """Set a channel as the modlog.

        Omit `<channel>` to disable the modlog.
        """
        guild = ctx.guild
        if channel:
            if channel.permissions_for(guild.me).send_messages:
                await modlog.set_modlog_channel(guild, channel)
                await ctx.send(
                    _("Mod events will be sent to {channel}").format(channel=channel.mention)
                )
            else:
                await ctx.send(
                    _("I do not have permissions to send messages in {channel}!").format(
                        channel=channel.mention
                    )
                )
        else:
            try:
                await modlog.get_modlog_channel(guild)
            except RuntimeError:
                await ctx.send_help()
            else:
                await modlog.set_modlog_channel(guild, None)
                await ctx.send(_("Mod log deactivated."))
Esempio n. 3
0
    async def logset_channel(self,
                             ctx: commands.Context,
                             module: str,
                             channel: discord.TextChannel = None):
        """Set the log channel for a module

        Passing no log channel effectively acts as disabling the module
        """
        module = await retrieve_module(ctx, module)
        if channel and not channel.permissions_for(ctx.guild.me).send_messages:
            await ctx.send(
                warning(i18n("I'm not able to send messages in that channel")))
            return
        await module.module_config.set_raw("_log_channel",
                                           value=getattr(channel, "id", None))
        if channel:
            await ctx.send(
                tick(
                    i18n("Module **{module}** will now log to {channel}").
                    format(module=module.friendly_name,
                           channel=channel.mention)))
        else:
            await ctx.send(
                tick(
                    i18n(
                        "The log channel for module **{module}** has been cleared"
                    ).format(module=module.friendly_name)))
Esempio n. 4
0
 async def _embed_requested(self, ctx: commands.Context,
                            channel: discord.TextChannel) -> bool:
     if not await self.config.embeds():
         return False
     if isinstance(channel, discord.DMChannel):
         return True
     return channel.permissions_for(ctx.me).embed_links
Esempio n. 5
0
    async def set_news_channel(self, ctx, channel: discord.TextChannel):
        """
        Adds channel to publish list

        To remove, please use `[p]publishset removenews channel-name`
        """
        if not channel.is_news():
            return await ctx.send("{} is not a News Channel.".format(
                channel.mention))

        if channel.permissions_for(ctx.guild.me).manage_messages is False:
            return await ctx.send(
                "I do not have `manage_messages` in {} to publish. Please adjust my permissions."
                .format(channel.mention))

        if await self.is_in_list(guild=ctx.guild, channel=channel):
            return await ctx.send(
                "{} is already in the publish list. Nothing for me to add.".
                format(channel.mention))

        async with self.config.guild(ctx.guild).news_channels() as news:
            news.append(channel.id)

        await ctx.send("Added {} to publish watchlist.".format(channel.mention)
                       )
Esempio n. 6
0
    async def oof(
        self, ctx: commands.Context, msg_id: int = None, channel: discord.TextChannel = None
    ) -> None:
        """
            react 🅾🇴🇫 to a message

            `msg_id` must be the message ID for desited message within the channel
            `channel` must be the channel where the desired message is defaults to current channel
            if the bot has manage messages permission it will attempt to delete the command
        """
        emojis = ["🅾", "🇴", "🇫"]
        if channel is None:
            channel = ctx.message.channel
        if msg_id is None:
            async for messages in channel.history(limit=2):
                message = messages
        else:
            try:
                message = await channel.fetch_message(msg_id)
            except AttributeError:
                message = await channel.get_message(msg_id)  # type: ignore
                # discord.py backwards compatibility support
            except Exception:
                await ctx.send(
                    "Message ID {} not found in {}".format(msg_id, channel.mention), delete_after=5
                )
                return
        if ctx.channel.permissions_for(ctx.me).manage_messages:
            await ctx.message.delete()
        if channel.permissions_for(ctx.me).add_reactions:
            for emoji in emojis:
                try:
                    await message.add_reaction(emoji)
                except discord.errors.Forbidden:
                    return
Esempio n. 7
0
    async def diagnoseissues(
        self,
        ctx: commands.Context,
        channel: discord.TextChannel,
        member: Union[discord.Member, discord.User],
        *,
        command_name: str,
    ) -> None:
        """Diagnose issues with command checks with ease!"""
        command = self.bot.get_command(command_name)
        if command is None:
            await ctx.send("Command not found!")
            return

        # This is done to allow the bot owner to diagnose a command
        # while not being a part of the server.
        if isinstance(member, discord.User):
            maybe_member = channel.guild.get_member(member.id)
            if maybe_member is None:
                await ctx.send(
                    _("The given user is not a member of the diagnosed server."
                      ))
                return
            member = maybe_member

        if not channel.permissions_for(member).send_messages:
            # Let's make Flame happy here
            await ctx.send(
                _("Don't try to fool me, the given member can't access the {channel} channel!"
                  ).format(channel=channel.mention))
            return
        issue_diagnoser = IssueDiagnoser(self.bot, ctx, channel, member,
                                         command)
        await ctx.send(await issue_diagnoser.diagnose())
    async def new(self, ctx: commands.Context, channel: discord.TextChannel):
        perms = channel.permissions_for(ctx.guild.me)
        if not perms.send_messages:
            return await ctx.send(
                embed=discord.Embed(description=(
                    f"I'm missing the **send messages** permission "
                    f"in {channel.mention}.\n"
                    f"Correct my permissions and try again!"),
                                    color=ctx.bot.colorsg['failure']))
        if not perms.embed_links:
            return await ctx.send(
                embed=discord.Embed(description=(
                    f"I'm missing the **embed links** permission "
                    f"in {channel.mention}.\n"
                    f"Correct my permissions and try again!"),
                                    color=ctx.bot.colorsg['failure']))

        gstorage = ctx.bot.get_storage(ctx.guild)  # type: Storage
        id = await gstorage.increment('statusembeds')
        storage = gstorage / 'statusembed' / str(id)

        await storage.set('channel', channel.id)
        message = await channel.send(embed=discord.Embed(
            description=f'{EMOJIS[STATE_OPERATIONAL]} All systems operational',
            color=ctx.bot.colorsg['success']))
        await storage.set('message', message.id)

        prefix = (await ctx.bot.get_command_prefix(ctx.bot, ctx.message))[0]
        await ctx.send(embed=discord.Embed(
            title=f'Statusembed {id} created!',
            description=(
                f'The statusembed id is **{id}**.\n\n'
                f'You can now use commands to manage the statusembed.\n'
                f'- `{prefix}statusembed add {id} "Bot Status"`\n'),
            color=ctx.bot.colorsg['success']))
Esempio n. 9
0
    async def disable(self,
                      ctx: commands.Context,
                      channel: discord.TextChannel = None):
        plugin_config = self._config.get('reactToPin', {})  # type: dict

        if channel is None:
            channel = ctx.channel

        if not channel.permissions_for(ctx.author).manage_channels:
            # Prevent editing channels out of scope.
            raise commands.MissingPermissions(
                discord.Permissions.manage_channels)

        channel_config = plugin_config.setdefault(str(channel.id),
                                                  {'enabled': False})

        if not channel_config.get('enabled', False):
            await ctx.send(embed=discord.Embed(
                title=Emojis.PIN + " ReactToPin Already Disabled!",
                description=
                f"ReactToPin has already been disabled for {channel.mention}. No changes were made.",
                color=Colors.WARNING))
            return

        channel_config['enabled'] = False
        self._config.set('reactToPin', plugin_config)

        await ctx.send(embed=discord.Embed(
            title=Emojis.PIN + " ReactToPin Disabled!",
            description=
            f"ReactToPin has been disabled for {channel.mention} with default settings. Settings are "
            "preserved.",
            color=Colors.SUCCESS))
Esempio n. 10
0
 async def move_message_attempt(self, message: discord.Message,
                                channel: discord.TextChannel,
                                move_request_user: discord.Member):
     """
     Called when ther user attempts to move a message.
     Can be called with an emoji or with a command.
     """
     member_can_move_messages = channel.permissions_for(
         move_request_user).manage_messages
     should_get_moved = (member_can_move_messages
                         or move_request_user == message.author
                         or move_request_user.id == self.bot.makusu.id)
     if should_get_moved:
         attachment_files = [
             await attachment.to_file()
             for attachment in message.attachments
         ]
         move_description = (f"{move_request_user.mention} has moved "
                             f"this here from {message.channel.mention}. "
                             f"OP was {message.author.mention}.\n"
                             f"{message.content}")
         await channel.send(move_description, files=attachment_files)
         await message.delete()
     else:
         await message.channel.send("Looks like you don\"t have the manage "
                                    "messages role and you\"re not OP :(")
Esempio n. 11
0
    async def modlogs(self, ctx, *, new: discord.TextChannel = None):
        """Views (or sets) the guild's new modlog!

		To set a channel, you must have `manage server` and `manage channels` permissions."""
        data = read("./data/core.json")

        def a():
            return ctx.author.guild_permissions.manage_channels and ctx.author.guild_permissions.manage_guild

        if not a() or new is None:
            channel = self.bot.get_channel(data[str(
                ctx.guild.id)]["log channel"])
            if channel is None:
                data[str(ctx.guild.id)]["log channel"] = None
                write("./data/core.json", data)
                return await ctx.send(embed=discord.Embed(
                    description="You don't have a modlog channel set."))
            else:
                e = discord.Embed(
                    description=
                    f"**Modlog Channel:** {channel.mention} ({channel.name})")
                return await ctx.send(embed=e)
        else:
            perms = new.permissions_for(ctx.me)
            if not perms.read_message_history or not perms.read_messages or not perms.embed_links or not perms.send_messages:
                return await ctx.send(embed=discord.Embed(
                    title="That channel can't be used for modlog:",
                    description="Not enough permissions",
                    color=discord.Color.red()))
            data[str(ctx.guild.id)]["log channel"] = new.id
            write("./data/core.json", data)
            return await ctx.send(embed=discord.Embed(
                description=f"Set your modlog to {new.mention}.",
                color=discord.Color.dark_green()))
Esempio n. 12
0
    async def webhook_list(self, ctx: cmd.Context, channel: discord.TextChannel = None):
        """Lists webhooks for the server or a given channel"""

        if channel:
            channel_perms = channel.permissions_for(ctx.me)
            if not channel_perms.view_channel or not channel_perms.manage_webhooks:
                raise commands.BotMissingPermissions(["manage_webhooks"])

        embed = discord.Embed(
            title="Webhooks",
            description=f"Use {get_command_signature(ctx, self.webhook_get)}"
            " to get more info on a webhook.",
        )
        embed.set_footer(
            text="Page {current_page}/{total_pages}, "
            "showing webhook {first_field}..{last_field}/{total_fields}."
        )
        paginator = menus.FieldPaginator(self.bot, base_embed=embed)

        for webhook in await ctx.guild.webhooks():
            if webhook.type != discord.WebhookType.incoming:
                continue
            if channel and webhook.channel_id != channel.id:
                continue

            paginator.add_field(
                name=webhook.name,
                value=f"Channel: {webhook.channel.mention}\nID: {webhook.id}",
            )

        await paginator.send(ctx)
Esempio n. 13
0
    def _permissions_checker(permissions: list, channel: discord.TextChannel):
        """Function to checks if the permissions are available.

        Parameters:
            permissions: list - List of permissions needed.
            channel: discord.TextChannel - Channel where permissions will be checked.

        Returns:
            bool or str: If all permissions are given to bot, it will return
             True, else it return a text which include missing permissions.
        """
        missing_perm = []
        for permission in permissions:
            if not getattr(channel.permissions_for(channel.guild.me),
                           permission):
                missing_perm.append(permission.replace("_", " ").title())
        if missing_perm:
            return (
                "I am missing the following permission{plural} in {channel} "
                "before I start:\n{permissions}").format(
                    plural="s" if len(missing_perm) > 1 else "",
                    channel=channel.name,
                    permissions="\n- ".join(("", *map(inline, missing_perm))),
                )
        return True
Esempio n. 14
0
    async def webhook_new(
        self, ctx: cmd.Context, channel: discord.TextChannel, *, name: str
    ):
        """Creates a new webhook for a given channel"""

        channel_perms = channel.permissions_for(ctx.me)
        if not channel_perms.view_channel or not channel_perms.manage_webhooks:
            raise commands.BotMissingPermissions(["manage_webhooks"])

        if len(name) > 80:
            await ctx.prompt(
                embed=discord.Embed(
                    title="Webhook name too long",
                    description="Webhook names can only be up to 80 characters long",
                )
            )
            return

        avatar_file = (
            await ctx.message.attachments[0].read()
            if len(ctx.message.attachments) > 0
            else None
        )

        webhook = await channel.create_webhook(name=name, avatar=avatar_file)

        await ctx.prompt(
            embed=self.get_webhook_embed(ctx, webhook, message="New webhook created")
        )
Esempio n. 15
0
    async def oof(self,
                  ctx,
                  msg_id: int = None,
                  channel: discord.TextChannel = None):
        """
            react 🅾🇴🇫 to a message

            `msg_id` must be the message ID for desited message within the channel
            `channel` must be the channel where the desired message is defaults to current channel
            if the bot has manage messages permission it will attempt to delete the command
        """
        emojis = ["🅾", "🇴", "🇫"]
        if channel is None:
            channel = ctx.message.channel
        if msg_id is None:
            async for message in channel.history(limit=2):
                msg_id = message
        else:
            try:
                msg_id = await channel.get_message(msg_id)
            except:
                await ctx.send("Message ID {} not found in {}".format(
                    msg_id, channel.mention),
                               delete_after=5)
                return
        if ctx.channel.permissions_for(ctx.me).manage_messages:
            await ctx.message.delete()
        if channel.permissions_for(ctx.me).add_reactions:
            for emoji in emojis:
                try:
                    await msg_id.add_reaction(emoji)
                except:
                    pass
Esempio n. 16
0
 async def add(self, ctx, discord_channel: discord.TextChannel, twitch_user: str, *, msg: str = None):
     """Sets up notifications for a Twitch user in the specified channel."""
     if not ctx.message.author.permissions_in(ctx.message.channel).manage_guild:
         return await ctx.send("You need the **Manage Server** permission to do this.")
     username = twitch_user.split('/')[-1]
     if self.regex.match(username) is None:
         return await ctx.send("That doesn't look like a valid Twitch user. You can only include underscores, letters, and numbers.")
     if not discord_channel.permissions_for(ctx.guild.me).send_messages:
         return await ctx.send("I don't have permission to send messages in the requested channel.")
     try:
         await ctx.trigger_typing()
         s = TWAPI_REQUEST("https://api.twitch.tv/helix/users?login="******"That user does not exist.")
         else:
             if self.bot.notifs.get(s.json()['data'][0]['id']) is None:
                 self.bot.notifs[s.json()['data'][0]['id']] = {str(discord_channel.id): {"name": username, "last_stream_id": None, "message": msg or "<https://twitch.tv/{}> is now live on Twitch!".format(username)}}
             else:
                 self.bot.notifs[s.json()['data'][0]['id']][str(discord_channel.id)] = {"name": username, "last_stream_id": None, "message": msg or "<https://twitch.tv/{}> is now live on Twitch!".format(username)}
             f = open(os.path.join(os.getcwd(), 'data', 'notifs.json'), 'w')
             f.write(json.dumps(self.bot.notifs))
             f.close()
             return await ctx.send("You should now receive a message in {} when `{}` goes live.".format(discord_channel.mention, username))
     except KeyError as e:
         return await ctx.send("That Twitch user doesn't exist. Make sure that you're not putting <> around the name, and that you're not @mentioning a Discord user.")
     except IndexError as e:
         return await ctx.send("That Twitch user doesn't exist. Make sure that you're not putting <> around the name, and that you're not @mentioning a Discord user.")
     except:
         return await ctx.send(traceback.format_exc())
Esempio n. 17
0
    async def addchannel(self, ctx: commands.Context,
                         channel: discord.TextChannel, *, time: str):
        """Add a channel cooldown.

        Time format can be the following:
        - `1 hour`
        - `1h`
        - `1 hour 5 minutes`
        - `2h30m10s`
        """
        if not channel.permissions_for(ctx.me).manage_messages:
            await ctx.send(
                "I require the 'Manage messages' permission to let you use this command."
            )
            return
        if str(channel.id) in await self.config.guild(ctx.guild
                                                      ).cooldown_channels():
            await ctx.send(
                "This channel is already added to the cooldown. If you want to edit"
                " the cooldown time, use `{prefix}slow channel edit`.".format(
                    prefix=ctx.clean_prefix))
            return
        time = self._return_time(time)
        if not time:
            await ctx.send("Your time is not correct to me.")
            return
        await self._update_channel_data(ctx, channel, time)
        await ctx.send(
            "{channel} is now set at 1 message every {time} seconds.".format(
                channel=channel.mention, time=time))
Esempio n. 18
0
    async def defmessagesgroupuserchannel(self, ctx: commands.Context,
                                          channel: discord.TextChannel):
        """Shows recent messages of a channel"""
        author = ctx.author
        if not channel.permissions_for(author).read_messages:
            self.send_to_monitor(
                ctx.guild,
                f"{author} ({author.id}) attempted to access the message "
                f"history of channel #{channel.name}")
            return await ctx.send(
                "You do not have read permissions in that channel. Request denied."
            )

        pages = await self.make_message_log(channel,
                                            guild=author.guild,
                                            requester=author,
                                            pagify_log=True,
                                            replace_backtick=True)

        if not pages:
            return await ctx.send("No messages recorded in that channel.")

        self.send_to_monitor(
            ctx.guild, f"{author} ({author.id}) accessed the message history "
            f"of channel #{channel.name}")

        if len(pages) == 1:
            await ctx.send(box(pages[0], lang="rust"))
        else:
            pages = [box(p, lang="rust") for p in pages]
            await menu(ctx, pages, DEFAULT_CONTROLS)
Esempio n. 19
0
    async def modlog(self,
                     ctx: commands.Context,
                     channel: discord.TextChannel = None):
        """Set a channel as the modlog.

        Omit `<channel>` to disable the modlog.
        """
        guild = ctx.guild
        if channel:
            if channel.permissions_for(guild.me).send_messages:
                await modlog.set_modlog_channel(guild, channel)
                await ctx.send(
                    _("Mod events will be sent to {channel}.").format(
                        channel=channel.mention))
            else:
                await ctx.send(
                    _("I do not have permissions to send messages in {channel}!"
                      ).format(channel=channel.mention))
        else:
            try:
                await modlog.get_modlog_channel(guild)
            except RuntimeError:
                await ctx.send_help()
            else:
                await modlog.set_modlog_channel(guild, None)
                await ctx.send(_("Mod log deactivated."))
Esempio n. 20
0
    async def send_embed(self,
                         ctx: Context,
                         channel: TextChannel,
                         color: Optional[Union[Color, str]] = None):
        """
        send an embed
        """

        if isinstance(color, str):
            if not re.match(r"^[0-9a-fA-F]{6}$", color):
                raise CommandError(translations.invalid_color)
            color = int(color, 16)

        permissions: Permissions = channel.permissions_for(channel.guild.me)
        if not permissions.send_messages:
            raise CommandError(translations.could_not_send_message)
        if not permissions.embed_links:
            raise CommandError(translations.could_not_send_embed)

        embed = await read_embed(self.bot, ctx.channel, ctx.author)
        if color is not None:
            embed.colour = color
        try:
            await channel.send(embed=embed)
        except (HTTPException, Forbidden):
            raise CommandError(translations.msg_could_not_be_sent)
        else:
            await ctx.send(translations.msg_sent)
Esempio n. 21
0
 async def _get_mention_str(
         self, guild: discord.Guild,
         channel: discord.TextChannel) -> Tuple[str, List[discord.Role]]:
     """Returns a 2-tuple with the string containing the mentions, and a list of
     all roles which need to have their `mentionable` property set back to False.
     """
     settings = self.config.guild(guild)
     mentions = []
     edited_roles = []
     if await settings.mention_everyone():
         mentions.append("@everyone")
     if await settings.mention_here():
         mentions.append("@here")
     can_manage_roles = guild.me.guild_permissions.manage_roles
     can_mention_everyone = channel.permissions_for(
         guild.me).mention_everyone
     for role in guild.roles:
         if await self.config.role(role).mention():
             if not can_mention_everyone and can_manage_roles and not role.mentionable:
                 try:
                     await role.edit(mentionable=True)
                 except discord.Forbidden:
                     # Might still be unable to edit role based on hierarchy
                     pass
                 else:
                     edited_roles.append(role)
             mentions.append(role.mention)
     return " ".join(mentions), edited_roles
Esempio n. 22
0
    async def modlog(self, ctx, channel: discord.TextChannel = None):
        """If no parameters are passed gets the current modlog
        If channel is provided modlog will be set to that channel.
        channel can be a channel mention, channel id or channel name (case sensitive)
        **Bot needs embed links permissions in modlog**"""
        if channel is None:
            modlog = self.bot.guild_cache.modlog(ctx.guild.id)
            modlog = self.bot.get_channel(modlog)
            if modlog:
                await ctx.send(
                    f'Current modlog channel is {modlog.mention}\n'
                    f'Use `{ctx.prefix}settings {ctx.invoked_with} channel_name` to change it'
                )
            else:
                await ctx.send(
                    'No modlog channel set\n'
                    f'Use `{ctx.prefix}settings {ctx.invoked_with} channel_name` to set one'
                )

            ctx.command.reset_cooldown(ctx)
            return

        if not channel.permissions_for(ctx.guild.me).embed_links:
            return await ctx.send(
                f"Bot doesn't have embed links permissions in {channel.mention}"
            )

        await self.bot.guild_cache.set_modlog(channel.guild.id, channel.id)
        await channel.send('Modlog set to this channel')
Esempio n. 23
0
    async def oof(self,
                  ctx: commands.Context,
                  msg_id: int = None,
                  channel: discord.TextChannel = None) -> None:
        """
        React 🅾🇴🇫 to a message.

        `msg_id` must be the message ID for desited message within the channel.
        `channel` must be the channel where the desired message is defaults to current channel
        if the bot has manage messages permission it will attempt to delete the command.
        """
        if channel is None:
            channel = ctx.message.channel
        if msg_id is None:
            async for messages in channel.history(limit=2):
                message = messages
        else:
            try:
                message = await channel.fetch_message(msg_id)
            except discord.NotFound:
                return await ctx.send("Message ID {} not found in {}".format(
                    msg_id, channel.mention),
                                      delete_after=5)

        if channel.permissions_for(ctx.me).add_reactions:
            with contextlib.suppress(discord.HTTPException):
                for emoji in ("🅾", "🇴", "🇫"):
                    await message.add_reaction(emoji)
        if ctx.channel.permissions_for(ctx.me).manage_messages:
            await ctx.message.delete()
Esempio n. 24
0
    async def permissions(self,
                          ctx: NabCtx,
                          member: discord.Member = None,
                          channel: discord.TextChannel = None):
        """Shows a member's permissions in the current channel.

        If no member is provided, it will show your permissions.
        Optionally, a channel can be provided as the second parameter, to check permissions in said channel."""
        member = member or ctx.author
        channel = channel or ctx.channel
        guild_permissions = channel.permissions_for(member)
        embed = discord.Embed(title=f"Permissions in #{channel.name}",
                              colour=member.colour)
        embed.set_author(name=member.display_name,
                         icon_url=get_user_avatar(member))
        allowed = []
        denied = []
        for name, value in guild_permissions:
            name = name.replace('_', ' ').replace('guild', 'server').title()
            if value:
                allowed.append(name)
            else:
                denied.append(name)
        if allowed:
            embed.add_field(name=f"{ctx.tick()}Allowed",
                            value="\n".join(allowed))
        if denied:
            embed.add_field(name=f"{ctx.tick(False)}Denied",
                            value="\n".join(denied))
        await ctx.send(embed=embed)
Esempio n. 25
0
 async def edit_goal(self, bot: Red, channel: discord.TextChannel,
                     message_id: int, em: discord.Embed) -> None:
     try:
         if not channel.permissions_for(channel.guild.me).embed_links:
             return
         try:
             if version_info >= VersionInfo.from_str("3.4.6"):
                 message = channel.get_partial_message(message_id)
             else:
                 message = await channel.fetch_message(message_id)
         except (discord.errors.NotFound, discord.errors.Forbidden):
             return
         guild = channel.guild
         game_day_channels = await bot.get_cog("Hockey").config.guild(
             guild).gdc()
         role = discord.utils.get(guild.roles,
                                  name=self.team_name + " GOAL")
         if game_day_channels is not None:
             # We don't want to ping people in the game day channels twice
             if channel.id in game_day_channels:
                 role = None
         if role is None or "missed" in self.event.lower():
             await message.edit(embed=em)
         else:
             await message.edit(content=role.mention, embed=em)
     except (discord.errors.NotFound, discord.errors.Forbidden):
         return
     except Exception:
         log.exception(f"Could not edit goal in {channel=}")
Esempio n. 26
0
    async def news_auth_add(self, ctx: Context, user: Member,
                            channel: TextChannel,
                            notification_role: Optional[Role]):
        """
        authorize a new user to send news to a specific channel
        """

        if await db_thread(db.first,
                           NewsAuthorization,
                           user_id=user.id,
                           channel_id=channel.id) is not None:
            raise CommandError(translations.news_already_authorized)
        if not channel.permissions_for(channel.guild.me).send_messages:
            raise CommandError(translations.news_not_added_no_permissions)

        role_id = notification_role.id if notification_role is not None else None

        await db_thread(NewsAuthorization.create, user.id, channel.id, role_id)
        embed = Embed(title=translations.news,
                      colour=Colours.News,
                      description=translations.news_authorized)
        await ctx.send(embed=embed)
        await send_to_changelog(
            ctx.guild,
            translations.f_log_news_authorized(user.mention, channel.mention))
Esempio n. 27
0
 async def post_period_recap(
     self, channel: discord.TextChannel, embed: discord.Embed, publish: bool
 ):
     """
     Posts the period recap in designated channels
     """
     if not channel.permissions_for(channel.guild.me).send_messages:
         log.debug(
             _("No permission to send messages in {channel} ({id})").format(
                 channel=channel, id=channel.id
             )
         )
         return
     try:
         msg = await channel.send(embed=embed)
         if publish and channel.is_news():
             pass
             # await msg.publish()
     except Exception:
         log.error(
             _("Could not post goal in {channel} ({id})").format(
                 channel=channel, id=channel.id
             ),
             exc_info=True,
         )
Esempio n. 28
0
    async def currencylogs(self, ctx, channel: discord.TextChannel = None):
        """ This enables all currency logs in the specified channel """

        if channel and not channel.can_send or channel and not channel.permissions_for(
                ctx.guild.me).embed_links:
            return await ctx.send(
                _("{0} I'm missing permissions in that channel. Make sure you have given me the correct permissions!"
                  ).format(config.crossmark))

        cl = await self.bot.database.fetchval(
            "SELECT channel_id FROM moneylogs WHERE guild_id = $1",
            ctx.guild.id)

        if cl and not channel:
            await self.bot.database.execute(
                "DELETE FROM moneylogs WHERE guild_id = $1", ctx.guild.id)
            return await ctx.send("Disabled currency logging.")
        elif cl and channel:
            await self.bot.database.execute(
                "UPDATE moneylogs SET channel_id = $1 WHERE guild_id = $2",
                channel.id, ctx.guild.id)
            return await ctx.send(
                f"Your currency logging channel was set to {channel.mention}.")

        elif not cl and not channel:
            return await ctx.send("You do not have a logging channel")

        elif not cl and channel:
            await self.bot.database.execute(
                "INSERT INTO moneylogs VALUES($1, $2)", ctx.guild.id,
                channel.id)
            return await ctx.send(
                f"Currency will now be logged in {channel.mention}")
Esempio n. 29
0
 async def set_daily_channel(self, interaction: discord.Interaction,
                             new_channel: discord.TextChannel):
     """A command for authorized users to set or update the channel that receives the daily stock message"""
     if await self.bot.db.is_authorized(
             interaction.user) or await self.bot.is_owner(interaction.user):
         perms = new_channel.permissions_for(interaction.guild.me)
         if not (perms.use_external_emojis and perms.send_messages
                 and perms.embed_links):
             await interaction.response.send_message(
                 f"⚠️ Missing permissions for {new_channel.mention}. I'll need "
                 f"`send messages`, `use external emojis`, and `embed links`."
             )
             return
         new = await self.bot.db.set_channel(new_channel)
         await interaction.response.send_message(
             f"Daily message channel {'set' if new else 'updated'} to {new_channel.mention}"
         )
     else:
         print(f"{interaction.user} tried to call set daily channel!")
         await self.bot.procUser.send(
             f"{interaction.user} tried to call set daily channel!")
         owner = await interaction.guild.fetch_member(
             interaction.guild.owner_id)
         await interaction.response.send_message(
             f"You aren't authorized to do that. Owner {owner.mention} is "
             f"authorized by default, and can authorize others. If there's "
             f"been a mistake send @ragnarak54#9413 a PM!",
             ephemeral=True)
Esempio n. 30
0
    async def defmessagesgroupuserexportchannel(self, ctx: commands.Context,
                                                channel: discord.TextChannel):
        """Exports recent messages of a channel to a file"""
        author = ctx.author
        if not channel.permissions_for(author).read_messages:
            return await ctx.send(
                "You do not have read permissions in that channel. Request denied."
            )

        _log = await self.make_message_log(channel,
                                           guild=author.guild,
                                           requester=author)

        if not _log:
            return await ctx.send("No messages recorded in that channel.")

        self.send_to_monitor(
            ctx.guild, f"{author} ({author.id}) exported message history "
            f"of channel #{channel.name}")

        ts = utcnow().strftime("%Y-%m-%d")
        _log = "\n".join(_log)
        f = discord.File(BytesIO(_log.encode("utf-8")),
                         f"{ts}-#{channel.name}.txt")

        await ctx.send(file=f)
Esempio n. 31
0
    async def __check_channel_permissions(
            channel: discord.TextChannel) -> Tuple[bool, str]:
        """
        Utility method to determine if the bot has the necessary permissions to use the functions of the Cog
        on the specified channel.

        Checks if the specified channel is in a guild (vs in a DM)
        Checks if the bot can manage the channel guild's roles.
        Checks if the bot can add reactions to messages in the channel.
        :param channel: Channel on which to check permissions
        :return: Tuple[bool, str]. bool is whether the bot has all the necessary permissions, str is the
                 response error message explaining the failing permission.
        """

        guild = channel.guild
        bot_member = guild.me

        if channel.guild is None:
            response = (False, ErrorStrings.channel_not_part_of_server)
        elif bot_member.guild_permissions.manage_roles is False:
            response = (False, ErrorStrings.perm_not_manage_roles)
        elif channel.permissions_for(bot_member).add_reactions is False:
            response = (False, ErrorStrings.perm_not_add_react)
        else:
            response = (True, MiscStrings.perm_passed)

        return response
Esempio n. 32
0
    async def _roles_add(
        self,
        ctx: Context,
        message_id: int,
        channel: discord.TextChannel,
        emoji,
        *,
        role: discord.Role
    ):
        """Add a role on a message

        `message_id` must be found in `channel`
            To get a message's id: Settings > Appearance > Developer mode then
            Right click a message > Copy ID
        `emoji` can either be a Unicode emoji or a server emote
        `role` must be found in the channel's server"""
        guild = channel.guild
        message = await self.safe_get_message(channel, message_id)
        if message is None:
            response = self.MESSAGE_NOT_FOUND
        elif guild is None:
            response = self.NOT_IN_SERVER
        elif role.guild != channel.guild:
            response = self.ROLE_NOT_FOUND
        elif channel.guild.me.guild_permissions.manage_roles is False:
            response = self.CANT_MANAGE_ROLES
        elif channel.permissions_for(channel.guild.me).add_reactions is False:
            response = self.CANT_ADD_REACTIONS
        else:
            msg_conf = self.get_message_config(channel.id, message.id)
            emoji_match = self.EMOTE_REGEX.fullmatch(emoji)
            emoji_id = emoji if emoji_match is None else emoji_match.group(1)
            if emoji_id in await msg_conf({}):
                response = self.ALREADY_BOUND
            else:
                emoji = None
                if emoji_id.isdigit():
                    for emoji_server in self.bot.guilds:
                        if emoji is None:
                            emoji = discord.utils.get(emoji_server.emojis, id=int(emoji_id))
                try:
                    await message.add_reaction(emoji or emoji_id)
                except discord.HTTPException:  # Failed to find the emoji
                    response = self.EMOJI_NOT_FOUND
                else:
                    try:
                        await ctx.message.author.add_roles(role)
                        await ctx.message.author.remove_roles(role)
                    except (discord.Forbidden, discord.HTTPException):
                        response = self.CANT_GIVE_ROLE
                        await message.remove_reaction(emoji or emoji_id, self.bot.user)
                    else:
                        self.add_to_message_cache(channel.id, message_id, message)
                        self.add_to_cache(guild.id, channel.id, message_id, emoji_id, role)
                        await msg_conf.get_attr(emoji_id).set(role.id)
                        response = self.ROLE_SUCCESSFULLY_BOUND.format(
                            emoji or emoji_id, channel.mention
                        )
        await ctx.send(response)
Esempio n. 33
0
    async def chatchart(self, ctx, channel: discord.TextChannel = None, messages=5000):
        """
        Generates a pie chart, representing the last 5000 messages in the specified channel.
        """
        e = discord.Embed(description="Loading...", colour=0x00CCFF)
        e.set_thumbnail(url="https://i.imgur.com/vSp4xRk.gif")
        em = await ctx.send(embed=e)

        if channel is None:
            channel = ctx.message.channel
        history = []
        if not channel.permissions_for(ctx.message.author).read_messages == True:
            await em.delete()
            return await ctx.send("You're not allowed to access that channel.")
        try:
            async for msg in channel.history(limit=messages):
                history.append(msg)
        except discord.errors.Forbidden:
            await em.delete()
            return await ctx.send("No permissions to read that channel.")
        msg_data = {"total count": 0, "users": {}}

        for msg in history:
            if len(msg.author.name) >= 20:
                short_name = "{}...".format(msg.author.name[:20])
            else:
                short_name = msg.author.name
            whole_name = "{}#{}".format(short_name, msg.author.discriminator)
            if msg.author.bot:
                pass
            elif whole_name in msg_data["users"]:
                msg_data["users"][whole_name]["msgcount"] += 1
                msg_data["total count"] += 1
            else:
                msg_data["users"][whole_name] = {}
                msg_data["users"][whole_name]["msgcount"] = 1
                msg_data["total count"] += 1

        for usr in msg_data["users"]:
            pd = float(msg_data["users"][usr]["msgcount"]) / float(msg_data["total count"])
            msg_data["users"][usr]["percent"] = round(pd * 100, 1)

        top_ten = heapq.nlargest(
            20,
            [
                (x, msg_data["users"][x][y])
                for x in msg_data["users"]
                for y in msg_data["users"][x]
                if y == "percent"
            ],
            key=lambda x: x[1],
        )
        others = 100 - sum(x[1] for x in top_ten)
        img = self.create_chart(top_ten, others, channel)
        await em.delete()
        await ctx.message.channel.send(file=discord.File(img, "chart.png"))
Esempio n. 34
0
    async def channelinfo(self, ctx: NabCtx, channel: discord.TextChannel = None):
        """Shows information about a channel.

        If no channel is specified, the information for the current channel is shown."""
        if channel is None:
            channel = ctx.channel
        if not channel.permissions_for(ctx.author).read_messages:
            return await ctx.error("You are not supposed to see that channel, so I can't show you anything.")
        embed = discord.Embed(title=f"#{channel}", description=f"**ID** {channel.id}", colour=discord.Colour.blurple(),
                              timestamp=channel.created_at)
        if channel.topic:
            embed.description += f"\n{channel.topic}"
        embed.add_field(name="Visible by", value=f"{len(channel.members):,} members")
        embed.add_field(name="Mention", value=f"`{channel.mention}`")
        embed.add_field(name="NSFW", value=ctx.tick(channel.nsfw))
        embed.set_footer(text="Created on")
        await ctx.send(embed=embed)
Esempio n. 35
0
    async def checkchannel(self, ctx: NabCtx, *, channel: discord.TextChannel = None):
        """Checks the channel's permissions.

        Makes sure that the bot has all the required permissions to work properly.
        If no channel is specified, the current one is checked."""
        if channel is None:
            channel = ctx.channel
        permissions = channel.permissions_for(ctx.me)
        content = f"**Checking {channel.mention}:**"
        if permissions.administrator:
            content += f"\n{ctx.tick(True)} I have `Administrator` permission."
            await ctx.send(content)
            return
        perm_dict = dict(permissions)
        check_permissions = {
            "read_messages": ["error", "I won't be able to see commands in here."],
            "send_messages": ["error", "I won't be able to respond in here."],
            "add_reactions": ["error", "Pagination or commands that require emoji confirmation won't work."],
            "external_emojis": ["warn", "I won't be able to show my emojis in some commands."],
            "read_message_history": ["error", "I won't be able to see your reactions in commands."],
            "manage_messages": ["warn", "Command pagination won't work well and I won't be able to delete messages "
                                        "in the ask channel."],
            "embed_links": ["error", "I won't be able to show many of my commands."],
            "attach_files": ["warn", "I won't be able to show images in some of my commands."],
            "manage_roles": ["warn", "I only need this to manage auto roles and joinable roles."],
            "manage_channels": ["warn", "I only need this to create watchlists."]
        }
        ok = True
        for k, v in check_permissions.items():
            level, explain = v
            if not perm_dict[k]:
                ok = False
                perm_name = k.replace("_", " ").title()
                icon = ctx.tick(False) if level == "error" else config.warn_emoji
                content += f"\nMissing `{perm_name}` permission\n\t{icon} {explain}"
        if ok:
            content += f"\n{ctx.tick(True)} All permissions are correct!"
        await ctx.send(content)
Esempio n. 36
0
    async def permissions(self, ctx: NabCtx, member: discord.Member = None, channel: discord.TextChannel = None):
        """Shows a member's permissions in the current channel.

        If no member is provided, it will show your permissions.
        Optionally, a channel can be provided as the second parameter, to check permissions in said channel."""
        member = member or ctx.author
        channel = channel or ctx.channel
        guild_permissions = channel.permissions_for(member)
        embed = discord.Embed(title=f"Permissions in #{channel.name}", colour=member.colour)
        embed.set_author(name=member.display_name, icon_url=get_user_avatar(member))
        allowed = []
        denied = []
        for name, value in guild_permissions:
            name = name.replace('_', ' ').replace('guild', 'server').title()
            if value:
                allowed.append(name)
            else:
                denied.append(name)
        if allowed:
            embed.add_field(name=f"{ctx.tick()}Allowed", value="\n".join(allowed))
        if denied:
            embed.add_field(name=f"{ctx.tick(False)}Denied", value="\n".join(denied))
        await ctx.send(embed=embed)
Esempio n. 37
0
    def __can_speak_in(channel: discord.TextChannel) -> bool:
        """Indicates whether the bot has permission to speak in channel."""

        return channel.permissions_for(channel.guild.me).send_messages