From c86aaba2ab174304b04fce124681adf85ef0d322 Mon Sep 17 00:00:00 2001 From: Neuro Assassin Date: Thu, 9 Mar 2023 20:08:00 -0500 Subject: [PATCH] feature/fix(dashboard): Working state for addressing PRs --- dashboard/__init__.py | 7 ++- dashboard/abc/mixin.py | 11 ++-- dashboard/abc/roles.py | 3 +- dashboard/abc/settings.py | 93 +++++------------------------ dashboard/abc/webserver.py | 3 +- dashboard/baserpc.py | 116 ++++++++++++++++++++++++++----------- 6 files changed, 109 insertions(+), 124 deletions(-) diff --git a/dashboard/__init__.py b/dashboard/__init__.py index 63a74c1f..f5a5a50a 100644 --- a/dashboard/__init__.py +++ b/dashboard/__init__.py @@ -1,3 +1,5 @@ +import inspect + from redbot.core.bot import Red from .dashboard import Dashboard @@ -5,5 +7,8 @@ async def setup(bot: Red): cog = Dashboard(bot) - bot.add_cog(cog) + if inspect.iscoroutinefunction(bot.add_cog): + await bot.add_cog(cog) + else: + bot.add_cog(cog) await cog.initialize() diff --git a/dashboard/abc/mixin.py b/dashboard/abc/mixin.py index d473fe4a..4a145b94 100644 --- a/dashboard/abc/mixin.py +++ b/dashboard/abc/mixin.py @@ -1,13 +1,10 @@ from redbot.core import commands -@commands.group(name="dashboard") -async def dashboard(self, ctx: commands.Context): - """Group command for controlling the web dashboard for Red.""" - pass - - class DBMixin: """ This is mostly here to easily mess with things... """ - c = dashboard + @commands.group(name="dashboard") + async def dashboard(self, ctx: commands.Context): + """Group command for controlling the web dashboard for Red.""" + pass \ No newline at end of file diff --git a/dashboard/abc/roles.py b/dashboard/abc/roles.py index cf9b12de..6e51331b 100644 --- a/dashboard/abc/roles.py +++ b/dashboard/abc/roles.py @@ -3,10 +3,11 @@ import discord from dashboard.abc.abc import MixinMeta -from dashboard.abc.mixin import dashboard +from dashboard.abc.mixin import DBMixin from dashboard.baserpc import HUMANIZED_PERMISSIONS +dashboard = DBMixin.dashboard class DashboardRolesMixin(MixinMeta): @checks.guildowner() diff --git a/dashboard/abc/settings.py b/dashboard/abc/settings.py index 65f01f43..a5c53a74 100644 --- a/dashboard/abc/settings.py +++ b/dashboard/abc/settings.py @@ -1,7 +1,6 @@ from redbot.core import commands, checks from redbot.core.utils.chat_formatting import box, humanize_list, inline from redbot import __version__ as red_version -from typing import Optional import discord import platform import socket @@ -10,12 +9,13 @@ import os from dashboard.abc.abc import MixinMeta -from dashboard.abc.mixin import dashboard +from dashboard.abc.mixin import DBMixin from dashboard.baserpc import HUMANIZED_PERMISSIONS THEME_COLORS = ["red", "primary", "blue", "green", "greener", "yellow"] +dashboard = DBMixin.dashboard class DashboardSettingsMixin(MixinMeta): @checks.is_owner() @@ -186,16 +186,9 @@ async def color_settings(self, ctx, color: str): """Set the default color for a new user. The webserver version must be at least 0.1.3a.dev in order for this to work.""" - color = color.lower() - if color == "purple": - color = "primary" - if color not in THEME_COLORS: - return await ctx.send( - "Unrecognized color. Please choose one of the following:\n" - f"{humanize_list(tuple(map(lambda x: inline(x).title(), THEME_COLORS)))}" - ) - await self.config.defaultcolor.set(color) - await ctx.tick() + return await ctx.send( + "This command has been migrated to the webserver in the admin panel." + ) @settings.command() async def support(self, ctx: commands.Context, url: str = ""): @@ -203,80 +196,22 @@ async def support(self, ctx: commands.Context, url: str = ""): Leaving it blank will remove it. """ - await self.config.support.set(url) - await ctx.tick() + return await ctx.send( + "This command has been migrated to the webserver in the admin panel." + ) - @settings.group() + @settings.command() async def meta(self, ctx: commands.Context): """Control meta tags that are rendered by a service. For example, Discord rendering a link with an embed""" - pass - - @meta.command() - async def title(self, ctx, *, title: str = ""): - """Set the meta title tag for the rendered UI from link. - - For Discord, this is the larger text hyperlinked to the url. - - The following arguments will be replaced if they are in the title: - {name} | The bot's username""" - await self.config.meta.title.set(title) - if not title: - return await ctx.send("Meta title reset to default.") - await ctx.tick() - - @meta.command() - async def icon(self, ctx, link: Optional[str] = ""): - """Set the meta icon tag for the rendered UI from link. - - For Discord, this is the large icon in the top right of the embed.""" - await self.config.meta.icon.set(link) - if not link: - return await ctx.send("Meta icon reset to default.") - await ctx.tick() - - @meta.command() - async def description(self, ctx, *, description: str = ""): - """Set the meta description tag for the rendered UI from link. - - For Discord, this is the smaller text under the title. - - The following arguments will be replaced if they are in the title: - {name} | The bot's username""" - await self.config.meta.description.set(description) - if not description: - return await ctx.send("Meta description reset to default.") - await ctx.tick() - - @meta.command(name="color") - async def color_meta(self, ctx, *, color: discord.Colour = ""): - """Set the meta color tag for the rendered UI from link. - - For Discord, this is the colored bar that appears in the left of the embed.""" - await self.config.meta.color.set(str(color)) - if not color: - return await ctx.send("Meta color reset to default.") - await ctx.tick() + return await ctx.send( + "This command has been migrated to the webserver in the admin panel." + ) @settings.command() async def view(self, ctx: commands.Context): """View the current dashboard settings.""" - data = await self.config.all() - redirect = data["redirect"] - secret = data["secret"] - support = data["support"] - color = data["defaultcolor"] - if not support: - support = "[Not set]" - description = ( - f"Client Secret: | {secret}\n" - f"Redirect URI: | {redirect}\n" - f"Support Server: | {support}\n" - f"Default theme: | {color}" + return await ctx.send( + "This command has been migrated to the webserver in the admin panel." ) - embed = discord.Embed(title="Red V3 Dashboard Settings", color=0x0000FF) - embed.description = box(description, lang="ini") - embed.add_field(name="Dashboard Version", value=box(f"[{self.__version__}]", lang="ini")) - embed.set_footer(text="Dashboard created by Neuro Assassin.") - await ctx.author.send(embed=embed) diff --git a/dashboard/abc/webserver.py b/dashboard/abc/webserver.py index 905ccf46..43fc295f 100644 --- a/dashboard/abc/webserver.py +++ b/dashboard/abc/webserver.py @@ -4,11 +4,12 @@ import discord from dashboard.abc.abc import MixinMeta -from dashboard.abc.mixin import dashboard +from dashboard.abc.mixin import DBMixin from dashboard.baserpc import HUMANIZED_PERMISSIONS from dashboard.menus import ClientList, ClientMenu +dashboard = DBMixin.dashboard class DashboardWebserverMixin(MixinMeta): @checks.is_owner() diff --git a/dashboard/baserpc.py b/dashboard/baserpc.py index 90874c52..95f1f7c3 100644 --- a/dashboard/baserpc.py +++ b/dashboard/baserpc.py @@ -2,6 +2,7 @@ from typing import List from html import escape import random +import time import re import discord @@ -56,6 +57,7 @@ def __init__(self, cog: commands.Cog): # Caches; you can thank trusty for the cog info one self.cog_info_cache = {} + self.guild_cache = {} self.invite_url = None self.owner = None @@ -146,7 +148,15 @@ async def get_variables(self): p for p in await self.bot.get_valid_prefixes() if not re.match(r"<@!?([0-9]+)>", p) ] - count = len(self.bot.users) + user_count = len(self.bot.users) + + text_channel_count = 0 + voice_channel_count = 0 + category_count = 0 + for guild in self.bot.guilds: + text_channel_count += len(guild.text_channels) + voice_channel_count += len(guild.voice_channels) + category_count += len(guild.categories) if self.invite_url is None: core = self.bot.get_cog("Core") @@ -158,23 +168,39 @@ async def get_variables(self): data = await self.cog.config.all() client_id = data["clientid"] or self.bot.user.id + try: + botavatar = str(self.bot.user.avatar_url_as(static_format="png")) + except AttributeError: + botavatar = str(self.bot.user.avatar) + returning = { - "botname": self.bot.user.name, - "botavatar": str(self.bot.user.avatar_url_as(static_format="png")), - "botid": self.bot.user.id, - "clientid": client_id, - "botinfo": markdown2.markdown(botinfo), - "prefix": prefixes, - "redirect": data["redirect"], - "support": data["support"], - "color": data["defaultcolor"], - "servers": humanize_number(len(self.bot.guilds)), - "users": humanize_number(count), - "blacklisted": data["blacklisted"], - "uptime": uptime_str, - "invite": self.invite_url, - "meta": data["meta"], + "bot": { + "name": self.bot.user.name, + "avatar": botavatar, + "id": self.bot.user.id, + "clientid": client_id, + "info": markdown2.markdown(botinfo), + "prefix": prefixes, + "owners": [str(x) for x in self.bot.owner_ids], + }, + "oauth": { + "redirect": data["redirect"], + "secret": await self.cog.config.secret(), + "blacklisted": data["blacklisted"], + }, + "ui": { + "invite": self.invite_url, + "stats": { + "servers": humanize_number(len(self.bot.guilds)), + "text": humanize_number(text_channel_count), + "voice": humanize_number(voice_channel_count), + "categories": humanize_number(category_count), + "users": humanize_number(user_count), + "uptime": uptime_str, + }, + }, } + if self.owner is None: app_info = await self.bot.application_info() if app_info.team: @@ -182,7 +208,7 @@ async def get_variables(self): else: self.owner = str(app_info.owner) - returning["owner"] = self.owner + returning["bot"]["owner"] = self.owner return returning @rpccheck() @@ -243,8 +269,18 @@ async def get_commands(self): return returning @rpccheck() - async def get_users_servers(self, userid: int): + async def get_users_servers(self, userid: int, page: int): userid = int(userid) + page = int(page) + + if userid in self.guild_cache: + cached = self.guild_cache[userid] + if (cached["time"] + 60) > time.time(): + # return cached["guilds"][page] + return cached["guilds"] + else: + del self.guild_cache[userid] + guilds = [] is_owner = False try: @@ -257,13 +293,19 @@ async def get_users_servers(self, userid: int): # This could take a while async for guild in AsyncIter(self.bot.guilds, steps=1300): + try: + icon = str(guild.icon_url_as(format="png"))[:-13] + except AttributeError: + icon = str(guild.icon)[:-13] + sgd = { "name": escape(guild.name), "id": str(guild.id), "owner": escape(str(guild.owner)), - "icon": str(guild.icon_url_as(format="png"))[:-13] - or "https://cdn.discordapp.com/embed/avatars/1.", - "animated": guild.is_icon_animated(), + "icon": icon or "https://cdn.discordapp.com/embed/avatars/1.", + "animated": getattr( + guild.icon, "is_animated", getattr(guild, "is_icon_animated", lambda: False) + )(), "go": False, } if is_owner: @@ -287,6 +329,14 @@ async def get_users_servers(self, userid: int): continue # User doesn't have view permission + # This needs expansion on it before it's ready to be put in. As such, it's low priority + """ + guilds = [ + guilds[i : i + 12] # noqa: E203 + for i in range(0, len(sorted(guilds, key=lambda x: x["name"])), 12) + ] + """ + self.guild_cache[userid] = {"guilds": guilds, "time": time.time()} return guilds @rpccheck() @@ -346,20 +396,11 @@ async def get_server(self, userid: int, serverid: int): vl = "2 - Medium" elif guild.verification_level is discord.VerificationLevel.high: vl = "3 - High" - elif guild.verification_level is discord.VerificationLevel.extreme: + elif guild.verification_level is discord.VerificationLevel.highest: vl = "4 - Extreme" else: vl = "Unknown" - region = getattr(guild.region, "name", guild.region) - parts = region.split("_") - for i, p in enumerate(parts): - if p in ["eu", "us", "vip"]: - parts[i] = p.upper() - else: - parts[i] = p.title() - region = " ".join(parts) - if not self.cog.configcache.get(serverid, {"roles": []})["roles"]: warn = True else: @@ -381,14 +422,20 @@ async def get_server(self, userid: int, serverid: int): all_roles = [(r.id, r.name) for r in guild.roles] + try: + icon = str(guild.icon_url_as(format="png"))[:-13] + except AttributeError: + icon = str(guild.icon)[:-13] + guild_data = { "status": 1, "name": escape(guild.name), "id": guild.id, "owner": escape(str(guild.owner)), - "icon": str(guild.icon_url_as(format="png"))[:-13] - or "https://cdn.discordapp.com/embed/avatars/1.", - "animated": guild.is_icon_animated(), + "icon": icon or "https://cdn.discordapp.com/embed/avatars/1.", + "animated": getattr( + guild.icon, "is_animated", getattr(guild, "is_icon_animated", lambda: False) + )(), "members": humanize_number(len(guild.members)), "online": humanize_number(stats["o"]), "idle": humanize_number(stats["i"]), @@ -402,7 +449,6 @@ async def get_server(self, userid: int, serverid: int): "joined": joined, "roleswarn": warn, "vl": vl, - "region": region, "prefixes": await self.bot.get_valid_prefixes(guild), "adminroles": adminroles, "modroles": modroles,