async def guildinfo(self, ctx): """Display information about the current guild, such as owner, region, emojis, and roles.""" guild = ctx.guild embed = discord.Embed(title=guild.name) embed.description = guild.id if not helpers.has_scanning(ctx): embed.set_thumbnail(url=guild.icon_url) else: embed.set_footer(text="Thumbnail omitted on this channel due to image scanning.") embed.add_field(name="Owner", value=guild.owner.name) num_humans = helpers.count_humans(guild) embed.add_field(name="Humans", value=num_humans) num_bots = helpers.count_bots(guild) embed.add_field(name="Bots", value=num_bots) embed.add_field(name="Text channels", value=len(guild.text_channels)) embed.add_field(name="Voice channels", value=len(guild.voice_channels)) embed.add_field(name="Custom emojis", value=len(guild.emojis) or None) embed.add_field(name="Roles", value=len(guild.roles)-1 or None) embed.add_field(name="Region", value=str(guild.region)) embed.add_field(name="Created at", value=guild.created_at.ctime()) await ctx.send(embed=embed)
async def info(self, ctx): """Display bot info, e.g. library versions.""" uptime = str(datetime.datetime.now() - ctx.bot.time_started).split(".")[0] embed = discord.Embed() embed.description = ctx.bot.description if not helpers.has_scanning(ctx): embed.set_thumbnail(url=ctx.bot.user.avatar_url_as(format="png", size=128)) else: embed.set_footer(text="Thumbnail omitted on this channel due to image scanning.") embed.add_field(name="Version", value=app_info.VERSION_STRING) ainfo = await ctx.bot.application_info() owner = ainfo.owner.mention embed.add_field(name="Owner", value=owner) support_guild = settings.manager.get("SUPPORT_GUILD", "") if len(support_guild) > 0: embed.add_field(name="Support guild", value=support_guild) num_guilds = len(ctx.bot.guilds) num_users = len(list(filter(lambda member: not member.bot, ctx.bot.get_all_members()))) embed.add_field(name="Serving", value=f"{num_users} people in {num_guilds} guilds") embed.add_field(name="Uptime", value=uptime) embed.add_field(name="Python", value="{0}.{1}.{2}".format(*sys.version_info)) embed.add_field(name="discord.py", value=discord.__version__) usage_memory = round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1000, 2) embed.add_field(name="Cookies eaten", value=f"{usage_memory} megabites") await ctx.send(embed=embed)
async def color(self, ctx, *, color: str = None): """Display a color. * color - This represents a color. Accepts hex input.""" try: if color: color = color.lstrip("#") # Remove the pound sign. color = int(f"0x{color}", 16) else: color = systemrandom.randint(0, 16777215) color = discord.Color(color) except ValueError: raise commands.UserInputError( ("Not a valid color. " "Color must be in hex format (e.g. `808080`) " "and must be between `FFFFFF` and `000000`.")) color_hex_value = "%0.2X%0.2X%0.2X" % (color.r, color.g, color.b) embed = discord.Embed() embed.color = color image_url = BASE_URL_COLOURLOVERS_API.format(color_hex_value) if not helpers.has_scanning(ctx): embed.set_thumbnail(url=image_url) else: embed.set_footer( text="Thumbnail omitted on this channel due to image scanning." ) embed.add_field(name="RGB", value=f"{color.to_rgb()}") embed.add_field(name="Hex code", value=f"#{color_hex_value}") embed.add_field(name="Images", value=BASE_URL_TINEYE_MULTICOLR.format( color_hex_value.lower())) embed.add_field(name="Information", value=BASE_URL_COLOR_HEX.format( color_hex_value.lower())) await ctx.send(embed=embed) if helpers.has_scanning(ctx): await message.delete()
async def _xkcd(self, ctx, comic_id=""): """Helper function for xkcd comics.""" if comic_id.lower() in ("random", "r"): url = BASE_URL_XKCD_API.format("") async with ctx.bot.session.get(url) as response: if response.status == 200: data = await response.json() comic_id = random.randint(1, data["num"]) else: message = "Could not reach xkcd. x.x" await ctx.send(message) logger.info(message) return url = BASE_URL_XKCD_API.format(comic_id) async with ctx.bot.session.get(url) as response: if response.status == 200: data = await response.json() title = data["safe_title"] url = BASE_URL_XKCD.format(data["num"]) url_explanation = BASE_URL_XKCD_EXPLAIN.format(data["num"]) url_image = data["img"] alt = data.get('alt') if not helpers.has_scanning(ctx): embed = discord.Embed(title=f'{title} ({data["num"]})') embed.description = f"[Explanation]({url_explanation})" embed.url = url embed.set_image(url=url_image) if alt: embed.set_footer(text=alt) await ctx.send(embed=embed) else: message_fetching = await ctx.send( "Fetching image; please wait. :3") message = [ f"**{title}**", f"**URL:** <{url}>", f"**Explanation:** <{url_explanation}>", f"**Image URL:** {url_image}", alt ] message = "\n".join(message) await ctx.send(message) await message_fetching.delete() elif response.status == 404: message = "That comic doesn't exist. :<" await ctx.send(message) logger.info(message) else: message = "Could not reach xkcd. x.x" await ctx.send(message) logger.warning(message)
async def avatar(self, ctx, *, user:discord.Member=None): """Display a user's avatar. Defaults to displaying the avatar of the user who invoked the command. * user - A member who you can mention for avatar.""" if not user: user = ctx.author if not helpers.has_scanning(ctx): embed = discord.Embed() embed.url = user.avatar_url embed.set_image(url=user.avatar_url) embed.set_footer(text=f"Avatar for {user.name}") await ctx.send(embed=embed) else: await ctx.send(user.avatar_url)
async def _send_image(self, ctx, url_image, kind: str = None, user: discord.Member = None): """A helper function that creates an embed with an image and sends it off.""" if isinstance(url_image, (tuple, list)): url_image = systemrandom.choice(url_image) message = self._generate_message(ctx, kind, user) if not helpers.has_scanning(ctx): embed = discord.Embed(color=utils.random_color()) embed.set_image(url=url_image) await ctx.send(message, embed=embed) else: message = "\n".join([str(message), url_image]) await ctx.send(message)
async def _generic_news(self, ctx, base_url: str, *, title: str = "News", image_url: str = None, color: int = None, no_link_titles: bool = False, **attributes): async with ctx.bot.session.get(base_url) as response: if response.status == 200: text = await response.text() soup = BeautifulSoup(text) else: await ctx.send(f"Couldn't fetch {title} at this time. :<") return embed = discord.Embed(title=title, url=base_url, color=color) if image_url: if not helpers.has_scanning(ctx): embed.set_thumbnail(url=image_url) else: embed.set_footer( text= "Thumbnail omitted on this channel due to image scanning.") link_list = soup.find_all("a", href=True, **attributes) counter = 0 checked_links = [] if no_link_titles: description = [] for link in link_list: if counter == 5: break elif link['href'] not in checked_links and link.string: description.append(link['href']) counter += 1 description = "\n".join(description) embed.description = description else: for link in link_list: if counter == 5: break elif link['href'] not in checked_links and link.string: embed.add_field(name=link.string, value=link['href']) checked_links.append(link['href']) counter += 1 await ctx.send(embed=embed)
async def _ibsearch_generic(self, ctx, *, tags=""): if not self.key_ibsearch: message = "API key required for this command, but none found. Contact the bot owner?" await ctx.send(message) raise errors.KeyError(message) if hasattr(ctx.channel, "is_nsfw") and ctx.channel.is_nsfw(): base_url = BASE_URL_IBSEARCH_NSFW base_url_api = BASE_URL_IBSEARCH_API_NSFW base_url_image = BASE_URL_IBSEARCH_IMAGE_NSFW else: base_url = BASE_URL_IBSEARCH base_url_api = BASE_URL_IBSEARCH_API base_url_image = BASE_URL_IBSEARCH_IMAGE params = urllib.parse.urlencode({"key": self.key_ibsearch, "q": tags}) url = base_url_api.format(params) async with ctx.bot.session.get(url) as response: if response.status == 200: data = await response.json() if len(data) == 0: await ctx.send("Could not find any results. :<") raise errors.ZeroDataLengthError() index = random.randint(1, len(data)) - 1 result = data[index] url_image = base_url_image.format(result) if not helpers.has_scanning(ctx): tags = result["tags"] if len(tags) > MAX_LENGTH_TAGS: ellipsis = "..." else: ellipsis = "" url_ibsearch = base_url.format(result) embed = discord.Embed(title=result["id"]) embed.url = url_ibsearch embed.description = f"[Image link]({url_image})" embed.set_image(url=url_image) embed.set_footer(text=f"Tags: {tags}"[:MAX_LENGTH_TAGS] + ellipsis) await ctx.send(embed=embed) else: await ctx.send(url_image) logger.info("Image retrieved!") else: message = "Could not reach site; please wait and try again. x.x" await ctx.send(message) logger.warning(message)
async def emojiinfo(self, ctx, *, emoji:discord.Emoji): """Display information for a custom emoji. * emoji - The emoji to get information about.""" embed = discord.Embed(title=emoji.name) embed.description = f"{emoji.id} | [Full image]({emoji.url})" embed.add_field(name="Guild", value=f"{emoji.guild.name} ({emoji.guild.id})") embed.add_field(name="Managed", value=emoji.managed) embed.add_field(name="Created at", value=emoji.created_at.ctime()) if not helpers.has_scanning(ctx): embed.set_thumbnail(url=emoji.url) else: embed.set_footer(text="Thumbnail omitted on this channel due to image scanning.") await ctx.send(embed=embed)
async def ping(self, ctx): """Ping the bot.""" pingtime = int( round((datetime.datetime.utcnow() - ctx.message.created_at).total_seconds() * 1000, 0)) if ctx.invoked_with in VARIANTS: variant = VARIANTS[ctx.invoked_with] else: variant = ":ping_pong:" message = f"{variant} {pingtime} ms!" embed = None if "bang" in ctx.invoked_with: if not helpers.has_scanning(ctx): embed = discord.Embed() embed.set_image(url=systemrandom.choice(GUNS)) else: message = "\n".join((message, systemrandom.choice(GUNS))) await ctx.send(message, embed=embed) logger.info(f"Ping! False ping time: {pingtime} ms")
async def userinfo(self, ctx, *, user:discord.Member=None): """Display information about a user, such as status and roles. Defaults to the user who invoked the command. * user - Optional argument. A user in the current channel to get user information about.""" # If user is None, then it is set equal to ctx.author. if not user: user = ctx.author title = f"{user.name}#{user.discriminator}" embed = discord.Embed(title=title) embed.color = user.color embed.description = str(user.id) if user.game: embed.description += f" | Playing **{user.game}**" if not helpers.has_scanning(ctx): embed.set_thumbnail(url=user.avatar_url_as(format="png", size=128)) else: embed.set_footer(text="Thumbnail omitted on this channel due to image scanning.") embed.add_field(name="Nickname", value=user.nick) embed.add_field(name="Bot user?", value="Yes" if user.bot else "No") # This is a bit awkward. Basically we don't want the bot to just say Dnd. if user.status.name == "dnd": status = "Do Not Disturb" else: status = user.status.name.capitalize() embed.add_field(name="Status", value=status) embed.add_field(name="Joined guild at", value=user.joined_at.ctime()) embed.add_field(name="Joined Discord at", value=user.created_at.ctime()) # This is crap. roles = ", ".join((role.name for role in user.roles if not role.is_default()))[:1024] embed.add_field(name="Roles", value=roles, inline=False) await ctx.send(embed=embed)
async def _rra(self, ctx, kind: str, user: discord.Member = None): """A helper function that grabs an image and posts it in response to a user. * kind - The type of image to retrieve. * user - The member to mention in the command.""" logger.info(f"Fetching {kind} image.") hash_id_channel = utils.to_hash(str(ctx.channel.id)) url = BASE_URL_API.format(kind) async with ctx.bot.session.get(url) as response: if response.status == 200: data = await response.json() url_image = BASE_URL_IMAGE.format(data).replace("i/", "") message = self._generate_message(ctx, kind, user) if not helpers.has_scanning(ctx): embed = discord.Embed(color=utils.random_color()) embed.set_image(url=url_image) await ctx.send(message, embed=embed) else: message = "\n".join([str(message), url_image]) await ctx.send(message) else: message = "Could not retrieve image. :(" await ctx.send(message) logger.info(message)