Ejemplo n.º 1
0
    async def requirerole(self, ctx: commands.Context, *roles: RoleTuple):
        """Require one of any specific roles to use the bot in the current guild

        To require a member to __not__ have one or more roles, you can use
        `~` before the role name to treat it as a blacklisted role.
        If a role name has `~` at the start of it's name, you can escape
        it with a backslash (`\`) character. Blacklisted roles override
        any possible whitelisted roles a member may have.

        Role names are case sensitive. If a role has spaces in it's name, wrap it in quotes.
        Passing no roles removes any currently set role requirements.

        The guild owner and members with the Administrator permission
        always bypass these requirements, regardless of roles."""
        seen = SeenSet()
        roles = tuple(
            (k, v) for k, v in roles
            if seen.mark_seen(k))  # type: Tuple[Tuple[discord.Role, bool]]
        whitelist = tuple(r for r, v in roles
                          if v)  # type: Tuple[discord.Role]
        blacklist = tuple(r for r, v in roles
                          if not v)  # type: Tuple[discord.Role]

        if ctx.guild.default_role in roles:
            await ctx.send(
                warning(
                    _("I can't set a role requirement with the guild's default role - "
                      "if you'd like to clear your current role requirements, "
                      "you can execute this command with no arguments to do so."
                      )))
            return

        await self.config.guild(ctx.guild).roles.set({
            "whitelist": [x.id for x in whitelist],
            "blacklist": [x.id for x in blacklist]
        })
        if not roles:
            await ctx.send(tick(_("Cleared currently set role requirements.")))
            return

        whitelist = ", ".join(
            escape(str(x), mass_mentions=True, formatting=True)
            for x in whitelist)
        blacklist = ", ".join(
            escape(str(x), mass_mentions=True, formatting=True)
            for x in blacklist)

        msg = _(
            "A member will now need to pass the following checks to use my commands:\n\n"
        )
        if whitelist:
            msg += _("**Any of the following roles:**\n{roles}").format(
                roles=whitelist)
        if whitelist and blacklist:
            msg += "\n\n"
        if blacklist:
            msg += _("**None of the following roles:**\n{roles}").format(
                roles=blacklist)

        await ctx.send(tick(msg))
Ejemplo n.º 2
0
 async def game_outcomes(self, guild, players, target):
     success_rate = await self.calculate_success(guild, target)
     crew = await self.config.guild(guild).Crew()
     config = await self.get_guild_settings(guild)
     good_out, bad_out = self.get_theme(config)
     results = []
     for player in players:
         chance = random.randint(1, 100)
         if chance <= success_rate:
             good_thing = random.choice(good_out)
             good_out.remove(good_thing)
             crew[player.id] = {
                 "Name": escape(player.display_name, formatting=True),
                 "Bonus": good_thing[1]
             }
             await self.config.guild(guild).Crew.set(crew)
             await self.add_member_spree(player)
             results.append(good_thing[0].format(
                 escape(player.display_name, formatting=True)))
         else:
             bad_thing = random.choice(bad_out)
             dropout_msg = (bad_thing[0] +
                            "```\n{0} dropped out of the game.```").format(
                                escape(player.display_name,
                                       formatting=True))
             await self.failure_handler(player, bad_thing[1])
             del crew[str(player.id)]
             await self.config.guild(guild).Crew.set(crew)
             bad_out.remove(bad_thing)
             results.append(dropout_msg)
     return results
Ejemplo n.º 3
0
 async def _clear_heist(self, ctx, user: discord.Member):
     """Clears a member of jail and death statuses."""
     author = ctx.message.author
     await self.thief.member_clear(user)
     await ctx.send("```{} administratively cleared {}```".format(
         escape(author.display_name, formatting=True),
         escape(user.display_name, formatting=True)))
Ejemplo n.º 4
0
    async def check_streams(self):
        for stream in self.streams:
            with contextlib.suppress(Exception):
                try:
                    if stream.__class__.__name__ == "TwitchStream":
                        await self.maybe_renew_twitch_bearer_token()
                        embed, is_rerun = await stream.is_online()
                    else:
                        embed = await stream.is_online()
                        is_rerun = False
                except OfflineStream:
                    if not stream._messages_cache:
                        continue
                    for message in stream._messages_cache:
                        with contextlib.suppress(Exception):
                            autodelete = await self.db.guild(message.guild).autodelete()
                            if autodelete:
                                await message.delete()
                    stream._messages_cache.clear()
                    await self.save_streams()
                else:
                    if stream._messages_cache:
                        continue
                    for channel_id in stream.channels:
                        channel = self.bot.get_channel(channel_id)
                        if not channel:
                            continue
                        ignore_reruns = await self.db.guild(channel.guild).ignore_reruns()
                        if ignore_reruns and is_rerun:
                            continue
                        mention_str, edited_roles = await self._get_mention_str(channel.guild)

                        if mention_str:
                            alert_msg = await self.db.guild(channel.guild).live_message_mention()
                            if alert_msg:
                                content = alert_msg.format(mention=mention_str, stream=stream)
                            else:
                                content = _("{mention}, {stream} is live!").format(
                                    mention=mention_str,
                                    stream=escape(
                                        str(stream.name), mass_mentions=True, formatting=True
                                    ),
                                )
                        else:
                            alert_msg = await self.db.guild(channel.guild).live_message_nomention()
                            if alert_msg:
                                content = alert_msg.format(stream=stream)
                            else:
                                content = _("{stream} is live!").format(
                                    stream=escape(
                                        str(stream.name), mass_mentions=True, formatting=True
                                    )
                                )

                        m = await channel.send(content, embed=embed)
                        stream._messages_cache.append(m)
                        if edited_roles:
                            for role in edited_roles:
                                await role.edit(mentionable=False)
                        await self.save_streams()
Ejemplo n.º 5
0
    async def _play_heist(self, ctx):
        """This begins a Heist"""
        author = ctx.message.author
        guild = ctx.guild
        config = await self.thief.get_guild_settings(guild)
        theme = await self.thief.get_guild_theme(guild)
        crew = await self.thief.config.guild(guild).Crew()

        await self.thief.check_server_settings(guild)
        await self.thief.check_member_settings(author)

        cost = config["Cost"]
        wait_time = config["Wait"]
        prefix = ctx.prefix

        # Theme Variables
        t_crew = theme["Crew"]
        t_heist = theme["Heist"]
        t_vault = theme["Vault"]

        outcome, msg = await self.thief.requirement_check(prefix, author, cost)

        if outcome == "Failed":
            return await ctx.send(msg)

        if not config["Planned"]:
            await bank.withdraw_credits(author, cost)
            config["Planned"] = True
            await self.thief.config.guild(guild).Config.set(config)
            crew = await self.thief.add_crew_member(author)
            await ctx.send(
                "A {4} is being planned by {0}\nThe {4} "
                "will begin in {1} seconds. Type {2}heist play to join their "
                "{3}.".format(
                    escape(author.display_name, formatting=True),
                    wait_time,
                    ctx.prefix,
                    t_crew,
                    t_heist,
                ))
            await asyncio.sleep(wait_time)

            crew = await self.thief.config.guild(guild).Crew()

            if len(crew) <= 1:
                await ctx.send(
                    "You tried to rally a {}, but no one wanted to follow you. The "
                    "{} has been cancelled.".format(t_crew, t_heist))
                await self.thief.reset_heist(guild)
            else:
                await self.heist_game(ctx, guild, t_heist, t_crew, t_vault)

        else:
            await bank.withdraw_credits(author, cost)
            crew = await self.thief.add_crew_member(author)
            crew_size = len(crew)
            await ctx.send("{0} has joined the {2}.\nThe {2} now has {1} "
                           "members.".format(
                               escape(author.display_name, formatting=True),
                               crew_size, t_crew))
Ejemplo n.º 6
0
    async def someone(self, ctx, *, text: str = None):
        """Help I've fallen and I need @someone.

        Discord 2018 April Fools."""
        smilies = [
            "¯\\_(ツ)_/¯",
            "(∩ ͡° ͜ʖ ͡°)⊃━☆゚. o ・ 。゚",
            "(∩ ͡° ͜ʖ ͡°)⊃━✿✿✿✿✿✿",
            "༼ つ ◕_◕ ༽つ",
            "(◕‿◕✿)",
            "(⁄ ⁄•⁄ω⁄•⁄ ⁄)",
            "(╯°□°)╯︵ ┻━┻",
            "ಠ_ಠ",
            "¯\\(°_o)/¯",
            "(✿ ͡◕ ᴗ◕)つ━━✫・o。",
            "ヽ༼ ಠ益ಠ ༽ノ",
        ]
        smile = random.choice(smilies)
        member = random.choice(ctx.channel.members)
        await ctx.send(
            "**@someone** {} ***{}*** {}".format(
                smile,
                chat.escape(member.display_name, mass_mentions=True),
                chat.escape(text, mass_mentions=True) if text else "",
            )
        )
Ejemplo n.º 7
0
 async def channels(self, ctx, *, server: int = None):
     """Get all channels on server"""
     if server is None:
         server = ctx.guild
     else:
         server = discord.utils.get(self.bot.guilds, id=server)
     if server is None:
         await ctx.send("Failed to get server with provided ID")
         return
     categories = "\n".join(
         [chat.escape(x.name)
          for x in server.categories]) or "No categories"
     text_channels = "\n".join(
         [chat.escape(x.name)
          for x in server.text_channels]) or "No text channels"
     voice_channels = "\n".join(
         [chat.escape(x.name)
          for x in server.voice_channels]) or "No voice channels"
     em = discord.Embed(title="Channels list",
                        color=await ctx.embed_color())
     em.add_field(name="Categories:", value=categories, inline=False)
     em.add_field(name="Text channels:", value=text_channels, inline=False)
     em.add_field(name="Voice channels:",
                  value=voice_channels,
                  inline=False)
     em.set_footer(
         text="Total count of channels: {} • "
         "Categories: {} • "
         "Text Channels: {} • "
         "Voice Channels: {}".format(
             len(server.channels), len(server.categories),
             len(server.text_channels), len(server.voice_channels)))
     await ctx.send(embed=em)
Ejemplo n.º 8
0
 async def send_to(self, ctx: Context, content=None):
     if await ctx.embed_requested():
         return await ctx.send(content=content, embed=self)
     content = str(content) if content is not None else None
     if content:
         content = [content, ""]
     else:
         content = []
     next_break = False
     title = self._("title")
     if title:
         content.append(CF.bold(title))
         next_break = True
     name = self._("author.name")
     if name:
         content.append(CF.italics(name))
         next_break = True
     url = self._("thumbnail.url")
     if url and not url.startswith("attachment://"):
         content.append(f"<{url}>")
         next_break = True
     description = self._("description")
     if description:
         content.append(CF.box(CF.escape(description, formatting=True)))
         next_break = False
     if next_break:
         content.append("")
         next_break = False
     for i in range(len(self.fields)):
         inline, name, value = (
             self._("fields", i, "inline"),
             self._("fields", i, "name"),
             self._("fields", i, "value"),
         )
         if not inline or len(name) + len(
                 value) > 78 or "\n" in name or "\n" in value:
             content.append(name)
             content.append(CF.box(CF.escape(value, formatting=True)))
             next_break = False
         else:
             content.append(f"{name}: {value}")
             next_break = True
     if next_break:
         content.append("")
         next_break = False
     url = self._("image.url")
     if url and not url.startswith("attachment://"):
         content.append(f"<{url}>")
     url = self._("video.url")
     if url and not url.startswith("attachment://"):
         content.append(f"<{url}>")
     text, timestamp = self._("footer.text"), self._("timestamp")
     if text and timestamp:
         content.append(f"{text} | {timestamp}")
     elif text:
         content.append(text)
     elif timestamp:
         content.append(f"{timestamp} UTC")
     content = list(CF.pagify("\n".join(map(str, content)), shorten_by=0))
     return await ctx.send_interactive(content)
Ejemplo n.º 9
0
    async def _add_remove(self,
                          ctx: commands.Context,
                          role: discord.Role,
                          *,
                          rm: bool = False):
        if role.is_default():
            raise commands.BadArgument(
                "cannot make a server's default role mentionable")
        async with self.config.guild(ctx.guild).roles() as roles:
            if rm is False:
                if role.id in roles:
                    await ctx.send(
                        warning(_("That role is already mentionable")))
                    return
                roles.append(role.id)

            else:
                if role.id not in roles:
                    await ctx.send(
                        warning(_("That role is not currently mentionable")))
                    return
                roles.remove(role.id)

            await ctx.send(
                escape(
                    tick(
                        _("`{}` is now allowed to be mentioned").format(role.
                                                                        name)),
                    mass_mentions=True,
                ) if rm is False else escape(
                    tick(
                        _("`{}` is no longer allowed to be mentioned").
                        format(role.name)),
                    mass_mentions=True,
                ))
Ejemplo n.º 10
0
    async def uinfo(self, ctx, user: discord.Member = None):
        """Shows user information. Defaults to author."""
        if user is None:
            user = ctx.author

        with sps(Exception):
            caller = inspect.currentframe().f_back.f_code.co_name

        try:
            roles = [r for r in user.roles if r.name != "@everyone"]
            _roles = [roles[0].name,] + [f'{r.name:>{len(r.name)+17}}' for r in roles[1:]]
        except IndexError:
            # if there are no roles then roles[0] will raise the IndexError here
            _roles = ["None"]

        seen = str(len(set([member.guild.name for member in self.bot.get_all_members() if member.id == user.id])))

        load = "```\nLoading user info...```"
        waiting = await ctx.send(load)

        data = "```ini\n"
        data += "[Name]:          {}\n".format(cf.escape(str(user)))
        data += "[ID]:            {}\n".format(user.id)
        data += "[Status]:        {}\n".format(user.status)
        data += "[Servers]:       {} shared\n".format(seen)
        if actplay := discord.utils.get(user.activities, type=discord.ActivityType.playing):
            data += "[Playing]:       {}\n".format(cf.escape(str(actplay.name)))
Ejemplo n.º 11
0
    async def _bailout_heist(self, ctx, user: discord.Member = None):
        """Specify who you want to pay for release. Defaults to you."""
        author = ctx.message.author
        theme = await self.thief.get_guild_theme(ctx.guild)

        t_bail = theme["Bail"]
        t_sentence = theme["Sentence"]

        if user is None:
            player = author
        else:
            player = user

        if await self.thief.get_member_status(player) != "Apprehended":
            return await ctx.send("{} is not in jail.".format(
                escape(player.display_name, formatting=True)))

        cost = await self.thief.get_member_bailcost(player)
        if not await bank.get_balance(player) >= cost:
            await ctx.send(
                "You do not have enough to afford the {} amount.".format(
                    t_bail))
            return

        if player.id == author.id:
            msg = (
                "Do you want to make a {0} amount? It will cost {1} credits. If you are "
                "caught again, your next {2} and {0} amount will triple. "
                "Do you still wish to pay the {0} amount?".format(
                    t_bail, cost, t_sentence))
        else:
            msg = (
                "You are about pay a {2} amount for {0} and it will cost you {1} credits. "
                "Are you sure you wish to pay {1} for {0}?".format(
                    escape(player.display_name, formatting=True), cost,
                    t_bail))

        await ctx.send(msg)
        try:
            response = await self.bot.wait_for(
                "message", timeout=15, check=lambda x: x.author == author)
        except asyncio.TimeoutError:
            await ctx.send("You took too long. canceling transaction.")
            return

        if "yes" in response.content.lower():
            msg = (
                "Congratulations {}, you are free! Enjoy your freedom while it "
                "lasts...".format(escape(player.display_name,
                                         formatting=True)))
            await bank.withdraw_credits(author, cost)
            await self.thief.set_member_free(author)
            await self.thief.set_member_oob(author, False)
        elif "no" in response.content.lower():
            msg = "Canceling transaction."
        else:
            msg = "Incorrect response, canceling transaction."

        await ctx.send(msg)
Ejemplo n.º 12
0
 async def uinfo(self, ctx, *, member: discord.Member = None):
     """Information on a user"""
     if member is None:
         member = ctx.message.author
     em = discord.Embed(
         title=chat.escape(str(member), formatting=True),
         color=member.color.value and member.color or discord.Embed.Empty,
     )
     if member.nick:
         em.add_field(name=_("Nickname"), value=member.nick)
     else:
         em.add_field(name=_("Name"), value=member.name)
     em.add_field(
         name=_("Client"),
         value="📱: {}\n"
         "🖥: {}\n"
         "🌎: {}".format(
             str(member.mobile_status).capitalize(),
             str(member.desktop_status).capitalize(),
             str(member.web_status).capitalize(),
         ),
     )
     em.add_field(name=_("Joined server"),
                  value=member.joined_at.strftime(self.TIME_FORMAT))
     em.add_field(name="ID", value=member.id)
     em.add_field(
         name=_("Exists since"),
         value=member.created_at.strftime(self.TIME_FORMAT),
     )
     if member.color.value:
         em.add_field(name=_("Color"), value=member.colour)
     if member.premium_since:
         em.add_field(
             name=_("Boosted server"),
             value=member.premium_since.strftime(self.TIME_FORMAT),
         )
     em.add_field(name=_("Bot?"), value=bool_emojify(member.bot))
     em.add_field(name=_("System?"), value=bool_emojify(member.system))
     em.add_field(
         name=_("Server permissions"),
         value="[{0}](https://fixator10.ru/permissions-calculator/?v={0})".
         format(member.guild_permissions.value),
     )
     if member.voice:
         em.add_field(name=_("In voice channel"),
                      value=member.voice.channel.mention)
     em.add_field(
         name=_("Mention"),
         value=f"{member.mention}\n{chat.inline(member.mention)}",
         inline=False,
     )
     if roles := [
             role.name for role in member.roles if not role.is_default()
     ]:
         em.add_field(
             name=_("Roles"),
             value=chat.escape("\n".join(roles), formatting=True),
             inline=False,
         )
Ejemplo n.º 13
0
async def emoji_embed(
        ctx, emoji: Union[discord.Emoji,
                          discord.PartialEmoji]) -> discord.Embed:
    """Make embed with info about emoji"""
    em = discord.Embed(
        title=isinstance(emoji, str) and "\n".join(
            map(
                lambda c: unicodedata.name(
                    c, _("[Unable to resolve unicode name]")), emoji))
        or chat.escape(emoji.name, formatting=True),
        color=await ctx.embed_color(),
    )
    if isinstance(emoji, str):
        # em.add_field(name=_("Unicode emoji"), value="✅")
        em.add_field(
            name=_("Unicode character"),
            value="\n".join(
                f"\\{c}" if c not in NON_ESCAPABLE_CHARACTERS else c
                for c in emoji),
        )
        em.add_field(
            name=_("Unicode category"),
            value="\n".join(unicodedata.category(c) for c in emoji),
        )
        em.set_image(url=await get_twemoji(emoji))
    if not isinstance(emoji, str):
        em.add_field(name=_("ID"), value=emoji.id)
        em.add_field(name=_("Animated"), value=bool_emojify(emoji.animated))
        em.set_image(url=emoji.url)
    if isinstance(emoji, discord.Emoji):
        em.add_field(
            name=_("Exists since"),
            value=emoji.created_at.strftime(ctx.cog.TIME_FORMAT),
        )
        em.add_field(name=_('":" required'),
                     value=bool_emojify(emoji.require_colons))
        em.add_field(name=_("Managed"), value=bool_emojify(emoji.managed))
        em.add_field(name=_("Server"), value=emoji.guild)
        em.add_field(name=_("Available"), value=bool_emojify(emoji.available))
        em.add_field(name=_("Usable by bot"),
                     value=bool_emojify(emoji.is_usable()))
        if emoji.roles:
            em.add_field(
                name=_("Roles"),
                value=chat.escape("\n".join(x.name for x in emoji.roles),
                                  formatting=True),
                inline=False,
            )
    elif isinstance(emoji, discord.PartialEmoji):
        em.add_field(
            name=_("Exists since"),
            value=emoji.created_at.strftime(ctx.cog.TIME_FORMAT),
        )
        em.add_field(name=_("Custom emoji"),
                     value=bool_emojify(emoji.is_custom_emoji()))
        # em.add_field(
        #     name=_("Unicode emoji"), value=bool_emojify(emoji.is_unicode_emoji())
        # )
    return em
Ejemplo n.º 14
0
    async def check_clips(self):
        log.debug("Checking streamers for clips")

        for stream in self.streams:
            log.debug(
                f"Checking for new {stream.__class__.__name__ } clips from {stream.name}"
            )

            with contextlib.suppress(Exception):
                #try:
                if stream.__class__.__name__ == "TwitchStream":
                    await self.maybe_renew_twitch_bearer_token()
                    embeds = await stream.get_new_clips(log)
                else:
                    embeds = await stream.get_new_clips(log)
                log.debug(f"{len(embeds)} clips found in get_new_clips")
                await self.save_streams()

                for channel_id in stream.channels:
                    channel = self.bot.get_channel(channel_id)
                    if not channel:
                        continue
                    mention_str, edited_roles = await self._get_mention_str(
                        channel.guild)

                    if mention_str:
                        alert_msg = await self.config.guild(
                            channel.guild).live_message_mention()
                        if alert_msg:
                            content = alert_msg.format(mention=mention_str,
                                                       stream=stream)
                        else:
                            content = (
                                "{mention}, {stream} has a new clip!").format(
                                    mention=mention_str,
                                    stream=escape(str(stream.name),
                                                  mass_mentions=True,
                                                  formatting=True),
                                )
                    else:
                        alert_msg = await self.config.guild(
                            channel.guild).live_message_nomention()
                        if alert_msg:
                            content = alert_msg.format(stream=stream)
                        else:
                            content = ("{stream} has a new clip!").format(
                                stream=escape(str(stream.name),
                                              mass_mentions=True,
                                              formatting=True))
                    for embed in embeds:
                        m = await channel.send(content, embed=embed)
                        if edited_roles:
                            for role in edited_roles:
                                await role.edit(mentionable=False)
                    #stream.last_checked = datetime.utcnow().isoformat() # Update the last checked time now that we're at the end.
                    await self.save_streams()
Ejemplo n.º 15
0
 async def fetchwidget(self, ctx, *, server_id: int):
     """Get data about server by ID via server's widget"""
     try:
         widget = await self.bot.fetch_widget(server_id)
     except discord.Forbidden:
         await ctx.send(chat.error(_("Widget is disabled for this server.")))
         return
     except discord.HTTPException as e:
         await ctx.send(chat.error(_("Widget for that server is not found: {}").format(e.text)))
         return
     try:
         invite = await widget.fetch_invite()
     except discord.HTTPException:
         invite = None
     em = discord.Embed(
         title=_("Server info"), color=await ctx.embed_color(), url=widget.json_url
     )
     em.add_field(name=_("Name"), value=chat.escape(widget.name, formatting=True))
     stats_text = _(
         "**Online member count:** {members}\n" "**Voice channel count:** {channels}"
     ).format(members=len(widget.members), channels=len(widget.channels))
     if invite:
         guild = invite.guild
         em.description = guild.description and guild.description or None
         stats_text += "\n" + _(
             "**Server ID**: {guild_id}\n"
             "**Approximate member count:** {approx_members}\n"
             "**Approx. active members count:** {approx_active}\n"
             "**Invite Channel:** {channel}"
         ).format(
             guild_id=guild.id,
             approx_members=invite.approximate_member_count,
             approx_active=invite.approximate_presence_count,
             channel=chat.escape(invite.channel.name, formatting=True),
         )
         if guild.features:
             em.add_field(
                 name=_("Features"),
                 value="\n".join(_(GUILD_FEATURES.get(f, f)) for f in guild.features).format(
                     banner=guild.banner and f" [🔗]({guild.banner_url_as(format='png')})" or "",
                     splash=guild.splash and f" [🔗]({guild.splash_url_as(format='png')})" or "",
                     discovery=getattr(guild, "discovery_splash", None)
                     and f" [🔗]({guild.discovery_splash_url_as(format='png')})"
                     or "",
                 ),
                 inline=False,
             )
         if invite.guild.icon:
             em.set_image(url=invite.guild.icon_url_as(static_format="png", size=4096))
     em.add_field(name=_("Stats"), value=stats_text, inline=False)
     if widget.invite_url:
         em.add_field(name=_("Widget's invite"), value=widget.invite_url)
     await ctx.send(embed=em)
Ejemplo n.º 16
0
    async def __flipx(self, ctx, *, text=None):
        """Flips a coin... or text/mention.

        Defaults to coin.
        """
        if text != None and len(text) > 0:
            if len(ctx.message.mentions) > 0:
                member = ctx.message.mentions[0]
            elif len(ctx.message.channel_mentions) > 0:
                channel = ctx.message.channel_mentions[0]
                text = "#" + channel.name
                member = None
            elif len(ctx.message.role_mentions) > 0:
                role = ctx.message.role_mentions[0]
                text = role.name
                member = None
            else:
                member = discord.utils.find(
                    lambda m: m.name.lower() == text.lower(),
                    ctx.bot.get_all_members())
            msg = ""
            if member != None:
                if member.id == self.bot.user.id:
                    member = ctx.message.author
                    msg = "Nice try. You think this is funny? How about *this* instead:\n\n"
                text = member.display_name
            new_text = text.translate(self._flipmap)[::-1]
            await ctx.send("{} (╯°□°)╯︵ {}".format(
                msg, escape(new_text, mass_mentions=True)))
        else:
            author = ctx.message.author
            await ctx.send("I Choose: ***{}***".format(
                choice(["HEADS", "TAILS"])))
Ejemplo n.º 17
0
    async def format_page(self, menu: menus.MenuPages, entries: List[Tuple[int, Dict]]):
        ctx = menu.ctx
        loses_len = max(len(humanize_number(entries[0][1]["loses"])) + 3, 8)
        win_len = max(len(humanize_number(entries[0][1]["wins"])) + 3, 6)
        xp__len = max(len(humanize_number(entries[0][1]["xp__earnings"])) + 3, 8)
        gold__len = max(len(humanize_number(entries[0][1]["gold__losses"])) + 3, 12)
        start_position = (menu.current_page * self.per_page) + 1
        pos_len = len(str(start_position + 9)) + 2
        header = (
            f"{'#':{pos_len}}{'Wins':{win_len}}"
            f"{'Losses':{loses_len}}{'XP Won':{xp__len}}{'Gold Spent':{gold__len}}{'Adventurer':2}"
        )

        author = ctx.author

        if getattr(ctx, "guild", None):
            guild = ctx.guild
        else:
            guild = None

        players = []
        for (position, (user_id, account_data)) in enumerate(entries, start=start_position):
            if guild is not None:
                member = guild.get_member(user_id)
            else:
                member = None

            if member is not None:
                username = member.display_name
            else:
                user = await menu.ctx.bot.get_user_global(user_id)
                if user is None:
                    username = user_id
                else:
                    username = user.name

            username = escape(str(username), formatting=True)
            if user_id == author.id:
                # Highlight the author's position
                username = f"<<{username}>>"

            pos_str = position
            loses = humanize_number(account_data["loses"])
            wins = humanize_number(account_data["wins"])
            xp__earnings = humanize_number(account_data["xp__earnings"])
            gold__losses = humanize_number(account_data["gold__losses"])

            data = (
                f"{f'{pos_str}.':{pos_len}} "
                f"{wins:{win_len}} "
                f"{loses:{loses_len}} "
                f"{xp__earnings:{xp__len}} "
                f"{gold__losses:{gold__len}} "
                f"{username}"
            )
            players.append(data)
        msg = "Adventure Negaverse Scoreboard\n```md\n{}``` ```md\n{}``````md\n{}```".format(
            header, "\n".join(players), f"Page {menu.current_page + 1}/{self.get_max_pages()}"
        )
        return msg
Ejemplo n.º 18
0
    async def cmd_report(self, ctx: commands.Context, *, message: str = None):
        """Sends a report to the mods for possible intervention

        Example:
        - `[p]report <message>`
        """
        # Pre-emptively delete the message for privacy reasons
        await ctx.message.delete()

        author = ctx.author
        if author.bot:
            # Ignore the bot
            return

        log_id = await self.settings.guild(ctx.guild).logchannel()
        log = None
        if log_id is not None:
            log = ctx.guild.get_channel(log_id)
        if log is None:
            # Failed to get the channel
            return

        data = discord.Embed(color=discord.Color.orange())
        data.set_author(name=f"Report", icon_url=author.avatar_url)
        data.add_field(name="Reporter", value=author.mention)
        data.add_field(name="Channel", value=ctx.channel.mention)
        data.add_field(name="Timestamp", value=ctx.message.created_at)
        data.add_field(name="Message",
                       value=escape(message or "<no message>"),
                       inline=False)

        await log.send(embed=data)
Ejemplo n.º 19
0
    async def format_page(self, menu: GenericMenu, entries):
        bot = menu.ctx.bot
        position = (menu.current_page * self.per_page) + 1
        bal_len = len(humanize_number(entries[0][1]))
        pound_len = len(str(position + 9))
        header = "{pound:{pound_len}}{score:{bal_len}}{name:2}\n".format(
            pound="#",
            name=("Name"),
            score=("Score"),
            bal_len=bal_len + 6,
            pound_len=pound_len + 3,
        )
        msg = ""
        for i, data in enumerate(entries, start=position):
            try:
                server = bot.get_guild(int(data[0])).name
            except AttributeError:
                server = "<unknown server>"
            name = escape(server, formatting=True)

            balance = data[1]
            balance = humanize_number(balance)
            msg += f"{humanize_number(i)}. {balance: <{bal_len + 5}} {name}\n"

        bank_name = "Guild Command Leaderboard."
        page = discord.Embed(
            title=("{}").format(bank_name),
            color=await menu.ctx.embed_color(),
            description="{}\n{} ".format(box(header, lang="prolog"), box(msg, lang="md")),
        )
        page.set_footer(text=f"Page {menu.current_page + 1}/{self.get_max_pages()}")

        return page
Ejemplo n.º 20
0
    async def rndactivity_list(self, ctx: commands.Context):
        statuses = list(await self.config.statuses())
        if not statuses:
            return await ctx.send(
                warning(translate("no_setup_statuses", prefix=ctx.prefix)))

        pages = []
        for status in statuses:
            index = statuses.index(status) + 1
            game_type = 0
            stream_url = None
            if isinstance(status, dict):
                game_type = status.get("type", 0)
                stream_url = status.get("url")
                status = status.get("game")
            status = escape(status, formatting=True, mass_mentions=True)
            if stream_url:
                status = f"[{status}]({stream_url})"
            pages.append(
                f"**#{index}** \N{EM DASH} **{translate('game_type')[game_type]}** {status}"
            )

        colour = await ctx.embed_colour()
        pages = [
            discord.Embed(colour=colour, description=x)
            for x in pagify("\n".join(pages))
        ]
        await PaginatedMenu(pages=pages,
                            bot=ctx.bot,
                            channel=ctx.channel,
                            member=ctx.author).prompt()
Ejemplo n.º 21
0
    async def quote_create(self, ctx, *items):
        """
        If a minimum required role has been set, users must have that role or
        higher, be in the mod/admin role, or be the guild owner in order to use this command

        The quote will only be created if all information is provided properly.
        Porper format is Double quotes surrounding quote followed by double quotes surrounding where its from/who its by
        """
        items = [escape(c, mass_mentions=True) for c in items]
        if len(items) == 2:
            channel = ctx.guild.get_channel(await
                                            self.settings.guild(ctx.guild
                                                                ).channel())
            if channel is None:
                channel = guild.system_channel  # noqa: F821
            quote = items[0]
            author = items[1]
            content = quote + " # " + author
            quoteimage = self.quoteImg(content)
            imfile = discord.File(fp=quoteimage, filename="image.png")
            embed = discord.Embed(description=quote + " - " + author)
            embed.set_image(url="attachment://" + quoteimage)
            await channel.send(embed=embed, file=imfile)
            await ctx.send("Posted")

        else:
            await ctx.send(
                "Not properly formatted. Porper format is double quotes surrounding quote followed by double quotes surrounding where its from/who its by"
            )
Ejemplo n.º 22
0
    async def convert(
            self, ctx: commands.Context,
            argument: str) -> Tuple[Optional[discord.TextChannel], int]:
        if argument.isnumeric():
            return (None, int(argument))

        arg = argument.split("-")
        if len(arg) != 2 or not all(x.isnumeric() for x in arg):
            raise commands.BadArgument(
                translate("invalid_id",
                          mid=escape(argument,
                                     mass_mentions=True,
                                     formatting=True)))

        cid, mid = tuple(int(x) for x in arg)
        channel: discord.TextChannel = ctx.bot.get_channel(cid)

        # ensure the channel exists and is in a guild context
        guild: Optional[discord.Guild] = getattr(channel, "guild", None)
        if not channel or not guild or ctx.author not in guild.members:
            raise commands.BadArgument(translate("no_such_channel", id=cid))

        if not channel.permissions_for(guild.get_member(
                ctx.author.id)).read_message_history:
            # we're returning the generic no such channel string if the command invoker is not in
            # the guild the specified channel is in, so at this point it's safe to say if you're
            # determined enough, you could probably figure out that a channel exists with a given
            # ID given that the Discord API makes no real attempts to hide them, which makes
            # returning a generic not found message pointless.
            raise commands.BadArgument(translate("no_history_perms", id=cid))
        return (channel, mid)
Ejemplo n.º 23
0
    async def listguilds(self, ctx):
        """List the guilds|servers the bot is in."""
        asciidoc = lambda m: "```asciidoc\n{}\n```".format(m)
        guilds = sorted(self.bot.guilds, key=lambda g: -g.member_count)
        header = ("```\n" "The bot is in the following {} server{}:\n" "```").format(
            len(guilds), "s" if len(guilds) > 1 else ""
        )

        max_zpadding = max([len(str(g.member_count)) for g in guilds])
        form = "{gid} :: {mems:0{zpadding}} :: {name}"
        all_forms = [
            form.format(
                gid=g.id,
                mems=g.member_count,
                name=filter_invites(cf.escape(g.name)),
                zpadding=max_zpadding
            )
            for g in guilds
        ]
        final = "\n".join(all_forms)

        await ctx.send(header)
        page_list = []
        for page in cf.pagify(final, delims=["\n"], page_length=1000):
            page_list.append(asciidoc(page))

        if len(page_list) == 1:
            return await ctx.send(asciidoc(page))
        await menu(ctx, page_list, DEFAULT_CONTROLS)
Ejemplo n.º 24
0
 async def convert(self, ctx, argument: str) -> timedelta:
     # this doc string is intentionally left empty; use `from_str` instead
     # of directly calling this method.
     """"""
     try:
         return self.from_str(argument)
     except NoDuration:
         raise BadArgument(
             translate(
                 "time.fail_parse_delta",
                 input=escape(argument, mass_mentions=True, formatting=True),
             )
         )
     except BelowMinDuration:
         raise BadArgument(
             translate(
                 "time.min_duration", delta=format_timedelta(timedelta(seconds=self._min_time))
             )
         )
     except AboveMaxDuration:
         raise BadArgument(
             translate(
                 "time.max_duration", delta=format_timedelta(timedelta(seconds=self._max_time))
             )
         )
Ejemplo n.º 25
0
 async def modlog_action(
     self, message: discord.Message, trigger: Trigger, find: List[str], action: str
 ) -> None:
     modlogs = await self.config.guild(message.guild).modlog()
     guild: discord.Guild = cast(discord.Guild, message.guild)
     author: discord.Member = cast(discord.Member, message.author)
     channel: discord.TextChannel = cast(discord.TextChannel, message.channel)
     if modlogs:
         if modlogs == "default":
             # We'll get the default modlog channel setup
             # with modlogset
             try:
                 modlog_channel = await modlog.get_modlog_channel(guild)
             except RuntimeError:
                 log.debug("Error getting modlog channel", exc_info=True)
                 # Return early if no modlog channel exists
                 return
         else:
             modlog_channel = guild.get_channel(modlogs)
             if modlog_channel is None:
                 return
         infomessage = f"{author} - {action}\n"
         embed = discord.Embed(
             description=message.content,
             colour=discord.Colour.dark_red(),
             timestamp=datetime.now(),
         )
         found_regex = humanize_list(find)
         embed.add_field(name=_("Channel"), value=channel.mention)
         embed.add_field(name=_("Trigger Name"), value=trigger.name)
         if found_regex:
             embed.add_field(name=_("Found Triggers"), value=found_regex[:1024])
         embed.add_field(name=_("Trigger author"), value=f"<@{trigger.author}>")
         if message.attachments:
             files = ", ".join(a.filename for a in message.attachments)
             embed.add_field(name=_("Attachments"), value=files)
         embed.set_footer(text=_("User ID: ") + str(message.author.id))
         embed.set_author(name=infomessage, icon_url=author.avatar_url)
         try:
             if modlog_channel.permissions_for(guild.me).embed_links:
                 await modlog_channel.send(embed=embed)
             else:
                 infomessage += _(
                     "Channel: {channel}\n"
                     "Trigger Name: {trigger}\n"
                     "Trigger author: {t_author}\n"
                     "Found Triggers: {found_triggers}\n"
                 ).format(
                     channel=channel.mention,
                     trigger=trigger.name,
                     t_author=f"{trigger.author}",
                     found_triggers=humanize_list(find)[:1024],
                 )
                 msg = escape(
                     infomessage.replace("@&", ""), mass_mentions=True, formatting=True
                 )
                 await modlog_channel.send(msg)
         except Exception:
             log.error("Error posting modlog message", exc_info=True)
             pass
Ejemplo n.º 26
0
 async def rinfo(self, ctx, *, role: discord.Role):
     """Get info about role"""
     em = discord.Embed(
         title=chat.escape(role.name, formatting=True),
         color=role.color if role.color.value else discord.Embed.Empty,
     )
     em.add_field(name=_("ID"), value=role.id)
     em.add_field(
         name=_("Permissions"),
         value="[{0}](https://fixator10.ru/permissions-calculator/?v={0})".
         format(role.permissions.value),
     )
     em.add_field(
         name=_("Exists since"),
         value=role.created_at.strftime(self.TIME_FORMAT),
     )
     em.add_field(name=_("Hoist"), value=bool_emojify(role.hoist))
     em.add_field(name=_("Members"), value=str(len(role.members)))
     em.add_field(name=_("Position"), value=role.position)
     em.add_field(name=_("Color"), value=role.colour)
     em.add_field(name=_("Managed"), value=bool_emojify(role.managed))
     em.add_field(name=_("Mentionable"),
                  value=bool_emojify(role.mentionable))
     em.add_field(name=_("Mention"),
                  value=role.mention + "\n`" + role.mention + "`")
     em.set_thumbnail(
         url=
         f"https://xenforo.com/community/rgba.php?r={role.colour.r}&g={role.color.g}&b={role.color.b}&a=255"
     )
     await ctx.send(embed=em)
Ejemplo n.º 27
0
 async def get_track_description(self,
                                 track,
                                 local_folder_current_path,
                                 shorten=False) -> Optional[str]:
     """Get the user facing formatted track name."""
     string = None
     if track and getattr(track, "uri", None):
         query = Query.process_input(track.uri, local_folder_current_path)
         if query.is_local or "localtracks/" in track.uri:
             if (hasattr(track, "title") and track.title != "Unknown title"
                     and hasattr(track, "author")
                     and track.author != "Unknown artist"):
                 if shorten:
                     string = f"{track.author} - {track.title}"
                     if len(string) > 40:
                         string = f"{(string[:40]).rstrip(' ')}..."
                     string = f'**{escape(f"{string}", formatting=True)}**'
                 else:
                     string = (
                         f'**{escape(f"{track.author} - {track.title}", formatting=True)}**'
                         + escape(f"\n{query.to_string_user()} ",
                                  formatting=True))
             elif hasattr(track,
                          "title") and track.title != "Unknown title":
                 if shorten:
                     string = f"{track.title}"
                     if len(string) > 40:
                         string = f"{(string[:40]).rstrip(' ')}..."
                     string = f'**{escape(f"{string}", formatting=True)}**'
                 else:
                     string = f'**{escape(f"{track.title}", formatting=True)}**' + escape(
                         f"\n{query.to_string_user()} ", formatting=True)
             else:
                 string = query.to_string_user()
                 if shorten and len(string) > 40:
                     string = f"{(string[:40]).rstrip(' ')}..."
                 string = f'**{escape(f"{string}", formatting=True)}**'
         else:
             if track.is_stream:
                 icy = await self.icyparser(track.uri)
                 if icy:
                     title = icy
                 else:
                     title = f"{track.title} - {track.author}"
             elif track.author.lower() not in track.title.lower():
                 title = f"{track.title} - {track.author}"
             else:
                 title = track.title
             string = f"{title}"
             if shorten and len(string) > 40:
                 string = f"{(string[:40]).rstrip(' ')}..."
                 string = re.sub(RE_SQUARE, "", string)
             string = f"**[{escape(string, formatting=True)}]({track.uri}) **"
     elif hasattr(track, "to_string_user") and track.is_local:
         string = track.to_string_user() + " "
         if shorten and len(string) > 40:
             string = f"{(string[:40]).rstrip(' ')}..."
         string = f'**{escape(f"{string}", formatting=True)}**'
     return string
Ejemplo n.º 28
0
    async def build_tweet_embed(self, status: tweepy.Status) -> discord.Embed:
        username = status.user.screen_name
        post_url = "https://twitter.com/{}/status/{}".format(status.user.screen_name, status.id)
        em = discord.Embed(
            colour=discord.Colour(value=int(status.user.profile_link_color, 16)),
            url=post_url,
            timestamp=status.created_at,
        )
        em.set_footer(text=f"@{username}")
        if hasattr(status, "retweeted_status"):
            em.set_author(
                name=f"{status.user.name} Retweeted {status.retweeted_status.user.name}",
                url=post_url,
                icon_url=status.user.profile_image_url,
            )
            status = status.retweeted_status
            em.set_footer(text=f"@{username} RT @{status.user.screen_name}")
            if hasattr(status, "extended_entities"):
                em.set_image(url=status.extended_entities["media"][0]["media_url_https"])
            if hasattr(status, "extended_tweet"):
                text = status.extended_tweet["full_text"]
                if "media" in status.extended_tweet["entities"]:
                    img = status.extended_tweet["entities"]["media"][0]["media_url_https"]
                    em.set_image(url=img)
            else:
                text = status.text
        else:
            em.set_author(
                name=status.user.name, url=post_url, icon_url=status.user.profile_image_url
            )
            if hasattr(status, "extended_entities"):
                em.set_image(url=status.extended_entities["media"][0]["media_url_https"])
            if hasattr(status, "extended_tweet"):
                text = status.extended_tweet["full_text"]
                if "media" in status.extended_tweet["entities"]:
                    img = status.extended_tweet["entities"]["media"][0]["media_url_https"]
                    em.set_image(url=img)
            else:
                text = status.text
        if status.in_reply_to_screen_name:
            api = await self.authenticate()
            try:
                reply = api.statuses_lookup(id_=[status.in_reply_to_status_id])[0]
                # log.debug(reply)
                in_reply_to = _("In reply to {name} (@{screen_name})").format(
                    name=reply.user.name, screen_name=reply.user.screen_name
                )
                reply_text = unescape(reply.text)
                if hasattr(reply, "extended_tweet"):
                    reply_text = unescape(reply.extended_tweet["full_text"])
                if hasattr(reply, "extended_entities") and not em.image:
                    em.set_image(url=reply.extended_entities["media"][0]["media_url_https"])
                em.add_field(name=in_reply_to, value=reply_text)
            except IndexError:
                log.debug("Error grabbing in reply to tweet.", exc_info=True)

        em.description = escape(unescape(text), formatting=True)

        return em
Ejemplo n.º 29
0
    async def format_page(self, menu: menus.MenuPages,
                          entries: List[Tuple[int, Dict]]):
        ctx = menu.ctx
        stats_len = len(humanize_number(entries[0][1][self._stat])) + 3
        start_position = (menu.current_page * self.per_page) + 1
        pos_len = len(str(start_position + 9)) + 2
        stats_plural = self._stat if self._stat.endswith(
            "s") else f"{self._stat}s"
        stats_len = (len(stats_plural)
                     if len(stats_plural) > stats_len else stats_len) + 2
        rebirth_len = len("Rebirths") + 2
        header = f"{'#':{pos_len}}{stats_plural.title().ljust(stats_len)}{'Rebirths':{rebirth_len}}{'Adventurer':2}"
        author = ctx.author

        if getattr(ctx, "guild", None):
            guild = ctx.guild
        else:
            guild = None

        players = []
        for (position, (user_id,
                        account_data)) in enumerate(entries,
                                                    start=start_position):
            if guild is not None:
                member = guild.get_member(user_id)
            else:
                member = None

            if member is not None:
                username = member.display_name
            else:
                user = menu.ctx.bot.get_user(user_id)
                if user is None:
                    username = user_id
                else:
                    username = user.name
            username = escape(str(username), formatting=True)
            if user_id == author.id:
                # Highlight the author's position
                username = f"<<{username}>>"

            pos_str = position
            rebirths = humanize_number(account_data["rebirths"])
            stats_value = humanize_number(account_data[self._stat.lower()])

            data = f"{f'{pos_str}.':{pos_len}}" f"{stats_value:{stats_len}}" f"{rebirths:{rebirth_len}}" f"{username}"
            players.append(data)

        embed = discord.Embed(
            title=f"Adventure Weekly Scoreboard",
            color=await menu.ctx.embed_color(),
            description="```md\n{}``` ```md\n{}```".format(
                header,
                "\n".join(players),
            ),
        )
        embed.set_footer(
            text=f"Page {menu.current_page + 1}/{self.get_max_pages()}")
        return embed
Ejemplo n.º 30
0
 def __init__(
     self, service: str, http_status: int, result: bool, reason: str = "",
 ):
     """Create the base Report result."""
     self.service = service
     self.http_status = http_status
     self.result = result
     self.reason = escape(reason, mass_mentions=True)
Ejemplo n.º 31
0
    async def choose(self, ctx, *choices):
        """Choose between multiple options.

        To denote options which include whitespace, you should use
        double quotes.
        """
        choices = [escape(c, mass_mentions=True) for c in choices]
        if len(choices) < 2:
            await ctx.send(_("Not enough options to pick from."))
        else:
            await ctx.send(choice(choices))
Ejemplo n.º 32
0
    async def cc_list(self, ctx: commands.Context):
        """List all available custom commands.

        The list displays a preview of each command's response, with
        markdown escaped and newlines replaced with spaces.
        """
        cc_dict = await CommandObj.get_commands(self.config.guild(ctx.guild))

        if not cc_dict:
            await ctx.send(
                _(
                    "There are no custom commands in this server."
                    " Use `{command}` to start adding some."
                ).format(command="{}customcom create".format(ctx.prefix))
            )
            return

        results = []
        for command, body in sorted(cc_dict.items(), key=lambda t: t[0]):
            responses = body["response"]
            if isinstance(responses, list):
                result = ", ".join(responses)
            elif isinstance(responses, str):
                result = responses
            else:
                continue
            # Cut preview to 52 characters max
            if len(result) > 52:
                result = result[:49] + "..."
            # Replace newlines with spaces
            result = result.replace("\n", " ")
            # Escape markdown and mass mentions
            result = escape(result, formatting=True, mass_mentions=True)
            results.append((f"{ctx.clean_prefix}{command}", result))

        if await ctx.embed_requested():
            # We need a space before the newline incase the CC preview ends in link (GH-2295)
            content = " \n".join(map("**{0[0]}** {0[1]}".format, results))
            pages = list(pagify(content, page_length=1024))
            embed_pages = []
            for idx, page in enumerate(pages, start=1):
                embed = discord.Embed(
                    title=_("Custom Command List"),
                    description=page,
                    colour=await ctx.embed_colour(),
                )
                embed.set_footer(text=_("Page {num}/{total}").format(num=idx, total=len(pages)))
                embed_pages.append(embed)
            await menus.menu(ctx, embed_pages, menus.DEFAULT_CONTROLS)
        else:
            content = "\n".join(map("{0[0]:<12} : {0[1]}".format, results))
            pages = list(map(box, pagify(content, page_length=2000, shorten_by=10)))
            await menus.menu(ctx, pages, menus.DEFAULT_CONTROLS)
Ejemplo n.º 33
0
 async def lmgtfy(self, ctx, *, search_terms: str):
     """Create a lmgtfy link."""
     search_terms = escape(
         search_terms.replace("+", "%2B").replace(" ", "+"), mass_mentions=True
     )
     await ctx.send("https://lmgtfy.com/?q={}".format(search_terms))