diff --git a/galaxy/galaxy.py b/galaxy/galaxy.py index 0ba9bc8..5851d35 100644 --- a/galaxy/galaxy.py +++ b/galaxy/galaxy.py @@ -67,46 +67,6 @@ class Galaxy(commands.Cog): embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Coco has been reset.") await ctx.send(embed=embed) - @commands.command() - @commands.guild_only() - async def userinfo(self, ctx, member: discord.Member): - """Gives information on a specific person.""" - if member.color.value == 0: - colorint = 10070709 - else: - colorint = member.color.value - avatarurl = str(member.avatar_url) - timestamp_create = int(datetime.timestamp(member.created_at)) - timestamp_join = int(datetime.timestamp(member.joined_at)) - embed = discord.Embed(title=f"{member.name}#{member.discriminator}", color=colorint) - embed.add_field(name="Joined At", value=f"") - embed.add_field(name="Created At", value=f"") - embed.add_field(name="Avatar", value=f"[Click Here]({avatarurl})") - embed.add_field(name="Roles", value=f"{member.roles}") - embed.set_thumbnail(url=f"{avatarurl}") - embed.set_footer(text=f"ID: {member.id}") - await ctx.send(embed=embed) - - @commands.command() - @commands.guild_only() - async def roleinfo(self, ctx, role: discord.Role): - """Gives information on a specific role.""" - permissions = role.permissions - if role.color.value == 0: - colorint = 10070709 - color = "99aab5" - else: - colorint = role.color.value - color = re.sub('#',"",str(role.color)) - colorcodelink = f"https://www.color-hex.com/color/{color}" - timestamp = int(datetime.timestamp(role.created_at)) - if permissions.administrator: - embed = discord.Embed(title=f"{role.name}", color=colorint, description=f"**ID:** {role.id}\n**Mention:** {role.mention}\n**Creation Date:** \n**Color:** [#{color}]({colorcodelink})\n**Hoisted:** {role.hoist}\n**Position:** {role.position}\n**Managed:** {role.managed}\n**Mentionable:** {role.mentionable}\n**Administrator:** {role.permissions.administrator}") - else: - embed = discord.Embed(title=f"{role.name}", color=colorint, description=f"**ID:** {role.id}\n**Mention:** {role.mention}\n**Creation Date:** \n**Color:** [#{color}]({colorcodelink})\n**Hoisted:** {role.hoist}\n**Position:** {role.position}\n**Managed:** {role.managed}\n**Mentionable:** {role.mentionable}\n**Administrator:** {role.permissions.administrator}") - embed.add_field(name="Permissions", value=f"**Manage Server:** {permissions.manage_guild}\n**Manage Webhooks:** {permissions.manage_webhooks}\n**Manage Channels:** {permissions.manage_channels}\n**Manage Roles:** {permissions.manage_roles}\n**Manage Emojis:** {permissions.manage_emojis}\n**Manage Messages:** {permissions.manage_messages}\n**Manage Nicknames:** {permissions.manage_nicknames}\n**Mention @everyone**: {permissions.mention_everyone}\n**Ban Members:** {permissions.ban_members}\n**Kick Members:** {permissions.kick_members}") - await ctx.send(embed=embed) - @commands.command() async def unix(self, ctx): diff --git a/info/__init__.py b/info/__init__.py new file mode 100644 index 0000000..d3fe16b --- /dev/null +++ b/info/__init__.py @@ -0,0 +1,5 @@ +from .info import Info + + +def setup(bot): + bot.add_cog(Info(bot)) \ No newline at end of file diff --git a/info/info.json b/info/info.json new file mode 100644 index 0000000..5817ffa --- /dev/null +++ b/info/info.json @@ -0,0 +1,9 @@ +{ + "author" : ["SeaswimmerTheFsh"], + "install_msg" : "Thank you for installing Galaxy!\nYou can find the source code of this cog here: https://github.com/SeaswimmerTheFsh/GalaxyCogs", + "name" : "Info", + "short" : "Provides information on Discord objects.", + "description" : "Provides information on Discord objects. Most of this code is shamelessly ripped from .", + "end_user_data_statement" : "This cog does not store any End User Data." + } + \ No newline at end of file diff --git a/info/info.py b/info/info.py new file mode 100644 index 0000000..06c7a82 --- /dev/null +++ b/info/info.py @@ -0,0 +1,285 @@ +import discord +from redbot.core import commands +from redbot.core.bot import Red +from redbot.core.i18n import Translator, cog_i18n +from datetime import datetime +import re +from redbot.core.utils.chat_formatting import ( + bold, + humanize_number, + humanize_timedelta, +) + +_ = T_ = Translator("General", __file__) + +@cog_i18n(_) +class Info(commands.Cog): + """Provides information on Discord objects.""" + + def __init__(self, bot: Red) -> None: + super().__init__() + self.bot = bot + + async def red_delete_data_for_user(self, **kwargs): + """Nothing to delete.""" + return + + @commands.command() + @commands.guild_only() + @commands.bot_has_permissions(embed_links=True) + async def serverinfo(self, ctx, details: bool = False): + """ + Show server information. + + `details`: Shows more information when set to `True`. + Default to False. + """ + guild = ctx.guild + created_at = _("Created on {date_and_time}. That's {relative_time}!").format( + date_and_time=discord.utils.format_dt(guild.created_at), + relative_time=discord.utils.format_dt(guild.created_at, "R"), + ) + online = humanize_number( + len([m.status for m in guild.members if m.status != discord.Status.offline]) + ) + total_users = guild.member_count and humanize_number(guild.member_count) + text_channels = humanize_number(len(guild.text_channels)) + voice_channels = humanize_number(len(guild.voice_channels)) + stage_channels = humanize_number(len(guild.stage_channels)) + if not details: + data = discord.Embed(description=created_at, colour=await ctx.embed_colour()) + data.add_field( + name=_("Users online"), + value=f"{online}/{total_users}" if total_users else _("Not available"), + ) + data.add_field(name=_("Text Channels"), value=text_channels) + data.add_field(name=_("Voice Channels"), value=voice_channels) + data.add_field(name=_("Roles"), value=humanize_number(len(guild.roles))) + data.add_field(name=_("Owner"), value=str(guild.owner)) + data.set_footer( + text=_("Server ID: ") + + str(guild.id) + + _(" • Use {command} for more info on the server.").format( + command=f"{ctx.clean_prefix}serverinfo 1" + ) + ) + if guild.icon: + data.set_author(name=guild.name, url=guild.icon) + data.set_thumbnail(url=guild.icon) + else: + data.set_author(name=guild.name) + else: + + def _size(num: int): + for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]: + if abs(num) < 1024.0: + return "{0:.1f}{1}".format(num, unit) + num /= 1024.0 + return "{0:.1f}{1}".format(num, "YB") + + def _bitsize(num: int): + for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]: + if abs(num) < 1000.0: + return "{0:.1f}{1}".format(num, unit) + num /= 1000.0 + return "{0:.1f}{1}".format(num, "YB") + + shard_info = ( + _("\nShard ID: **{shard_id}/{shard_count}**").format( + shard_id=humanize_number(guild.shard_id + 1), + shard_count=humanize_number(ctx.bot.shard_count), + ) + if ctx.bot.shard_count > 1 + else "" + ) + # Logic from: https://github.com/TrustyJAID/Trusty-cogs/blob/master/serverstats/serverstats.py#L159 + online_stats = { + _("Humans: "): lambda x: not x.bot, + _(" • Bots: "): lambda x: x.bot, + "\N{LARGE GREEN CIRCLE}": lambda x: x.status is discord.Status.online, + "\N{LARGE ORANGE CIRCLE}": lambda x: x.status is discord.Status.idle, + "\N{LARGE RED CIRCLE}": lambda x: x.status is discord.Status.do_not_disturb, + "\N{MEDIUM WHITE CIRCLE}\N{VARIATION SELECTOR-16}": lambda x: ( + x.status is discord.Status.offline + ), + "\N{LARGE PURPLE CIRCLE}": lambda x: any( + a.type is discord.ActivityType.streaming for a in x.activities + ), + "\N{MOBILE PHONE}": lambda x: x.is_on_mobile(), + } + member_msg = _("Users online: **{online}/{total_users}**\n").format( + online=online, total_users=total_users + ) + count = 1 + for emoji, value in online_stats.items(): + try: + num = len([m for m in guild.members if value(m)]) + except Exception as error: + print(error) + continue + else: + member_msg += f"{emoji} {bold(humanize_number(num))} " + ( + "\n" if count % 2 == 0 else "" + ) + count += 1 + + verif = { + "none": _("0 - None"), + "low": _("1 - Low"), + "medium": _("2 - Medium"), + "high": _("3 - High"), + "highest": _("4 - Highest"), + } + + joined_on = _( + "{bot_name} joined this server on {bot_join}. That's over {since_join} days ago!" + ).format( + bot_name=ctx.bot.user.name, + bot_join=guild.me.joined_at.strftime("%d %b %Y %H:%M:%S"), + since_join=humanize_number((ctx.message.created_at - guild.me.joined_at).days), + ) + + data = discord.Embed( + description=(f"{guild.description}\n\n" if guild.description else "") + created_at, + colour=await ctx.embed_colour(), + ) + data.set_author( + name=guild.name, + icon_url="https://cdn.discordapp.com/emojis/457879292152381443.png" + if "VERIFIED" in guild.features + else "https://cdn.discordapp.com/emojis/508929941610430464.png" + if "PARTNERED" in guild.features + else None, + ) + if guild.icon: + data.set_thumbnail(url=guild.icon) + data.add_field(name=_("Members:"), value=member_msg) + data.add_field( + name=_("Channels:"), + value=_( + "\N{SPEECH BALLOON} Text: {text}\n" + "\N{SPEAKER WITH THREE SOUND WAVES} Voice: {voice}\n" + "\N{STUDIO MICROPHONE} Stage: {stage}" + ).format( + text=bold(text_channels), + voice=bold(voice_channels), + stage=bold(stage_channels), + ), + ) + data.add_field( + name=_("Utility:"), + value=_( + "Owner: {owner}\nVerif. level: {verif}\nServer ID: {id}{shard_info}" + ).format( + owner=bold(str(guild.owner)), + verif=bold(verif[str(guild.verification_level)]), + id=bold(str(guild.id)), + shard_info=shard_info, + ), + inline=False, + ) + data.add_field( + name=_("Misc:"), + value=_( + "AFK channel: {afk_chan}\nAFK timeout: {afk_timeout}\nCustom emojis: {emoji_count}\nRoles: {role_count}" + ).format( + afk_chan=bold(str(guild.afk_channel)) + if guild.afk_channel + else bold(_("Not set")), + afk_timeout=bold(humanize_timedelta(seconds=guild.afk_timeout)), + emoji_count=bold(humanize_number(len(guild.emojis))), + role_count=bold(humanize_number(len(guild.roles))), + ), + inline=False, + ) + + excluded_features = { + # available to everyone since forum channels private beta + "THREE_DAY_THREAD_ARCHIVE", + "SEVEN_DAY_THREAD_ARCHIVE", + # rolled out to everyone already + "NEW_THREAD_PERMISSIONS", + "TEXT_IN_VOICE_ENABLED", + "THREADS_ENABLED", + # available to everyone sometime after forum channel release + "PRIVATE_THREADS", + } + custom_feature_names = { + "VANITY_URL": "Vanity URL", + "VIP_REGIONS": "VIP regions", + } + features = sorted(guild.features) + if "COMMUNITY" in features: + features.remove("NEWS") + feature_names = [ + custom_feature_names.get(feature, " ".join(feature.split("_")).capitalize()) + for feature in features + if feature not in excluded_features + ] + if guild.features: + data.add_field( + name=_("Server features:"), + value="\n".join( + f"\N{WHITE HEAVY CHECK MARK} {feature}" for feature in feature_names + ), + ) + + if guild.premium_tier != 0: + nitro_boost = _( + "Tier {boostlevel} with {nitroboosters} boosts\n" + "File size limit: {filelimit}\n" + "Emoji limit: {emojis_limit}\n" + "VCs max bitrate: {bitrate}" + ).format( + boostlevel=bold(str(guild.premium_tier)), + nitroboosters=bold(humanize_number(guild.premium_subscription_count)), + filelimit=bold(_size(guild.filesize_limit)), + emojis_limit=bold(str(guild.emoji_limit)), + bitrate=bold(_bitsize(guild.bitrate_limit)), + ) + data.add_field(name=_("Nitro Boost:"), value=nitro_boost) + if guild.splash: + data.set_image(url=guild.splash.replace(format="png")) + data.set_footer(text=joined_on) + + await ctx.send(embed=data) + + @commands.command() + @commands.guild_only() + async def userinfo(self, ctx, member: discord.Member): + """Gives information on a specific person.""" + if member.color.value == 0: + colorint = 10070709 + else: + colorint = member.color.value + avatarurl = str(member.avatar_url) + timestamp_create = int(datetime.timestamp(member.created_at)) + timestamp_join = int(datetime.timestamp(member.joined_at)) + embed = discord.Embed(title=f"{member.name}#{member.discriminator}", color=colorint) + embed.add_field(name="Joined At", value=f"") + embed.add_field(name="Created At", value=f"") + embed.add_field(name="Avatar", value=f"[Click Here]({avatarurl})") + embed.add_field(name="Roles", value=f"{member.roles}") + embed.set_thumbnail(url=f"{avatarurl}") + embed.set_footer(text=f"ID: {member.id}") + await ctx.send(embed=embed) + + @commands.command() + @commands.guild_only() + async def roleinfo(self, ctx, role: discord.Role): + """Gives information on a specific role.""" + permissions = role.permissions + if role.color.value == 0: + colorint = 10070709 + color = "99aab5" + else: + colorint = role.color.value + color = re.sub('#',"",str(role.color)) + colorcodelink = f"https://www.color-hex.com/color/{color}" + timestamp = int(datetime.timestamp(role.created_at)) + if permissions.administrator: + embed = discord.Embed(title=f"{role.name}", color=colorint, description=f"**ID:** {role.id}\n**Mention:** {role.mention}\n**Creation Date:** \n**Color:** [#{color}]({colorcodelink})\n**Hoisted:** {role.hoist}\n**Position:** {role.position}\n**Managed:** {role.managed}\n**Mentionable:** {role.mentionable}\n**Administrator:** {role.permissions.administrator}") + else: + embed = discord.Embed(title=f"{role.name}", color=colorint, description=f"**ID:** {role.id}\n**Mention:** {role.mention}\n**Creation Date:** \n**Color:** [#{color}]({colorcodelink})\n**Hoisted:** {role.hoist}\n**Position:** {role.position}\n**Managed:** {role.managed}\n**Mentionable:** {role.mentionable}\n**Administrator:** {role.permissions.administrator}") + embed.add_field(name="Permissions", value=f"**Manage Server:** {permissions.manage_guild}\n**Manage Webhooks:** {permissions.manage_webhooks}\n**Manage Channels:** {permissions.manage_channels}\n**Manage Roles:** {permissions.manage_roles}\n**Manage Emojis:** {permissions.manage_emojis}\n**Manage Messages:** {permissions.manage_messages}\n**Manage Nicknames:** {permissions.manage_nicknames}\n**Mention @everyone**: {permissions.mention_everyone}\n**Ban Members:** {permissions.ban_members}\n**Kick Members:** {permissions.kick_members}") + await ctx.send(embed=embed) \ No newline at end of file