fix(bot): ✨ Improve p.stats.
This commit is contained in:
@@ -51,9 +51,11 @@ async def ReplyEmbed(
|
||||
|
||||
embed = discord.Embed(
|
||||
color=constants.EMBED_COLOR,
|
||||
description=formatting.trim(last_content.content)
|
||||
description=(
|
||||
formatting.trim(last_content.content)
|
||||
if last_content.was_propagated or is_this_channel
|
||||
else "*This message was censored.*",
|
||||
else "*This message was censored.*"
|
||||
),
|
||||
author=discord.EmbedAuthor(
|
||||
name=f"Replied to {author_name}",
|
||||
icon_url=author_avatar_url,
|
||||
|
||||
+90
-17
@@ -1,3 +1,5 @@
|
||||
from typing import Awaitable
|
||||
|
||||
from datetime import datetime, timezone, timedelta
|
||||
|
||||
import sys
|
||||
@@ -13,7 +15,7 @@ from payphone import bot
|
||||
from payphone.db import models, utils
|
||||
from payphone.cogs import base
|
||||
from payphone.cogs.mods import embeds, views
|
||||
from payphone.core import checks, converters, constants
|
||||
from payphone.core import checks, converters, constants, formatting as fmt
|
||||
|
||||
|
||||
class Mods(base.Cog):
|
||||
@@ -291,29 +293,100 @@ class Mods(base.Cog):
|
||||
|
||||
@commands.command()
|
||||
@commands.is_owner()
|
||||
async def stats(self, ctx: commands.Context) -> None:
|
||||
async def stats(
|
||||
self, ctx: commands.Context, iterations: int = 5, wait: int = 5
|
||||
) -> None:
|
||||
"""
|
||||
Shows all Payphone's stats.
|
||||
|
||||
Options:
|
||||
- `<iterations>`: The amount of iterations (to display progress). Defaults to 5.
|
||||
- `<wait>`: The amount of seconds to wait between iterations. Defaults to 5.
|
||||
"""
|
||||
|
||||
stats = [
|
||||
f"On-call Channels: {await self.bot.redis.scard(constants.CHANNELS_ONCALL_SET)}",
|
||||
f"Searching Channels: {await self.bot.redis.scard(constants.CHANNELS_SEARCH_QUEUE)}",
|
||||
f"Messages: {await models.Message.all().count()}",
|
||||
f"Message Contents: {await models.MessageContent.all().count()}",
|
||||
f"Calls: {await models.Call.all().count()}",
|
||||
f"Ongoing Calls: {await models.Call.filter(ended_at=None).count()}",
|
||||
f"Bans: {await models.Ban.all().count()}",
|
||||
f"Reports: {await models.Report.all().count()}",
|
||||
f"On-review Reports: {await models.Report.filter(status=models.ReportStatus.ON_REVIEW).count()}",
|
||||
f"Users: {await models.User.all().count()}",
|
||||
f"Profiles: {await models.Profile.all().count()}",
|
||||
f"Servers: {await models.Server.all().count()}",
|
||||
f"Shards: {self.bot.shard_count}",
|
||||
f"Current Shard: {ctx.guild.shard_id + 1}",
|
||||
(
|
||||
"On-call Channels",
|
||||
lambda: self.bot.redis.scard(constants.CHANNELS_ONCALL_SET),
|
||||
),
|
||||
(
|
||||
"Searching Channels",
|
||||
lambda: self.bot.redis.scard(constants.CHANNELS_SEARCH_QUEUE),
|
||||
),
|
||||
(
|
||||
"Messages",
|
||||
lambda: models.Message.all().count(),
|
||||
),
|
||||
(
|
||||
"Message Contents",
|
||||
lambda: models.MessageContent.all().count(),
|
||||
),
|
||||
("Calls", lambda: models.Call.all().count()),
|
||||
(
|
||||
"Ongoing Calls",
|
||||
lambda: models.Call.filter(ended_at=None).count(),
|
||||
),
|
||||
("Bans", lambda: models.Ban.all().count()),
|
||||
("Reports", lambda: models.Report.all().count()),
|
||||
(
|
||||
"On-review Reports",
|
||||
lambda: models.Report.filter(
|
||||
status=models.ReportStatus.ON_REVIEW
|
||||
).count(),
|
||||
),
|
||||
("Users", lambda: models.User.all().count()),
|
||||
(
|
||||
"Profiles",
|
||||
lambda: models.Profile.all().count(),
|
||||
),
|
||||
("Servers", lambda: models.Server.all().count()),
|
||||
("Shards", lambda: self.bot.shard_count),
|
||||
("Current Shards", lambda: ctx.guild.shard_id + 1),
|
||||
]
|
||||
|
||||
await ctx.send(f"```\n{"\n".join(stats)}\n```")
|
||||
rows = [[stat[0]] for stat in stats]
|
||||
rows_with_diff = [[stat[0]] for stat in stats]
|
||||
|
||||
i = 0
|
||||
message = None
|
||||
|
||||
while i < iterations:
|
||||
i += 1
|
||||
|
||||
for stat_i, stat in enumerate(stats):
|
||||
value = stat[1]()
|
||||
|
||||
if isinstance(value, Awaitable):
|
||||
value = await value
|
||||
|
||||
rows[stat_i].append(value)
|
||||
prev_value = rows[stat_i][-2]
|
||||
|
||||
if isinstance(prev_value, str):
|
||||
rows_with_diff[stat_i].append(value)
|
||||
|
||||
else:
|
||||
diff = value - prev_value
|
||||
|
||||
rows_with_diff[stat_i].append(
|
||||
str(value)
|
||||
+ (f" ({"+" if diff > 0 else ""}{diff})" if diff != 0 else "")
|
||||
)
|
||||
|
||||
table = fmt.monospace_table(
|
||||
rows_with_diff,
|
||||
[""] + [f"{wait * j}s" for j in range(i)],
|
||||
padding=2,
|
||||
)
|
||||
|
||||
if message is None:
|
||||
message = await ctx.send(f"```\n{table}\n```")
|
||||
|
||||
else:
|
||||
message = await message.edit(f"```\n{table}\n```")
|
||||
|
||||
if i < iterations:
|
||||
await asyncio.sleep(wait)
|
||||
|
||||
|
||||
def setup(b: bot.Payphone) -> None:
|
||||
|
||||
@@ -28,15 +28,19 @@ class BanNotificationEmbed(discord.Embed):
|
||||
),
|
||||
discord.EmbedField(
|
||||
name="Expires At",
|
||||
value=f"<t:{int(ban.expires_at.timestamp())}:F> (<t:{int(ban.expires_at.timestamp())}:R>)"
|
||||
value=(
|
||||
f"<t:{int(ban.expires_at.timestamp())}:F> (<t:{int(ban.expires_at.timestamp())}:R>)"
|
||||
if ban.expires_at
|
||||
else "*Does not expire.*",
|
||||
else "*Does not expire.*"
|
||||
),
|
||||
),
|
||||
discord.EmbedField(
|
||||
name="Appeal",
|
||||
value="*You haven't appealed this ban.*"
|
||||
value=(
|
||||
"*You haven't appealed this ban.*"
|
||||
if ban.appeal is None
|
||||
else ban.appeal,
|
||||
else ban.appeal
|
||||
),
|
||||
),
|
||||
],
|
||||
author=bot.embed_author,
|
||||
|
||||
@@ -186,7 +186,7 @@ class ReportView(discord.ui.View):
|
||||
await interaction.response.edit_message(
|
||||
content="✅ You're up to date! No reports left to check.",
|
||||
embed=None,
|
||||
view=None
|
||||
view=None,
|
||||
)
|
||||
return
|
||||
|
||||
@@ -218,7 +218,7 @@ class ReportView(discord.ui.View):
|
||||
await interaction.response.edit_message(
|
||||
content="✅ You're up to date! No reports left to check.",
|
||||
embed=None,
|
||||
view=None
|
||||
view=None,
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@@ -175,9 +175,11 @@ class Users(base.Cog):
|
||||
logs += f"- `{call_id}`: "
|
||||
|
||||
participant_names = ", ".join(
|
||||
(
|
||||
call_rs.display_name
|
||||
if call_rs.channel_id != data["user_rs"].channel_id
|
||||
else call_rs.profile.name
|
||||
)
|
||||
for call_rs in data["others_rs"] + [data["user_rs"]]
|
||||
)
|
||||
|
||||
|
||||
@@ -246,16 +246,16 @@ def moderate(message: str) -> str:
|
||||
match = next(PATTERN.finditer(message), None)
|
||||
|
||||
if match is not None:
|
||||
return message[match.start():match.end()]
|
||||
return message[match.start() : match.end()]
|
||||
|
||||
match = next(URL_PATTERN.finditer(message), None)
|
||||
|
||||
if match is not None:
|
||||
return message[match.start():match.end()]
|
||||
return message[match.start() : match.end()]
|
||||
|
||||
match = next(INVITES_PATTERN.finditer(message), None)
|
||||
|
||||
if match is not None:
|
||||
return message[match.start():match.end()]
|
||||
return message[match.start() : match.end()]
|
||||
|
||||
return None
|
||||
|
||||
@@ -56,6 +56,68 @@ def monospace_grid(values: list[str], space: int = 14) -> str:
|
||||
return "```" + "".join([v + " " * (space - len(v)) for v in values]) + "```"
|
||||
|
||||
|
||||
def monospace_table(
|
||||
rows: list[tuple],
|
||||
headers: list | None = None,
|
||||
column_separator: str = "|",
|
||||
header_separator: str = "-",
|
||||
intersection: str = "+",
|
||||
padding: int = 1,
|
||||
) -> str:
|
||||
"""Creates a monospace table.
|
||||
|
||||
Args:
|
||||
rows (list[tuple]): The rows.
|
||||
headers (list | None, optional): The headers.
|
||||
column_separator (str, optional): The column separator. Defaults to "|".
|
||||
header_separator (str, optional): The header separator. Defaults to "-".
|
||||
intersection (str, optional): The intersection character where column and row separators meet.
|
||||
padding (int, optional): The padding that each column has at its sides.
|
||||
|
||||
Returns:
|
||||
str: The monospace table.
|
||||
"""
|
||||
|
||||
max_sizes = [
|
||||
max(
|
||||
*(
|
||||
[len(str(row[i])) for row in rows]
|
||||
+ ([len(headers[i])] if headers is not None else [])
|
||||
)
|
||||
)
|
||||
for i in range(len(rows[0]))
|
||||
]
|
||||
|
||||
def format_row(row: list) -> str:
|
||||
return column_separator.join(
|
||||
[
|
||||
(" " * padding)
|
||||
+ str(col)
|
||||
+ (" " * (max_sizes[i] - len(str(col))))
|
||||
+ (" " * padding)
|
||||
for i, col in enumerate(row)
|
||||
]
|
||||
)
|
||||
|
||||
formatted_rows = []
|
||||
|
||||
for row in rows:
|
||||
formatted_rows.append(format_row(row))
|
||||
|
||||
table = "\n".join(formatted_rows)
|
||||
|
||||
if headers is not None:
|
||||
header = format_row(headers)
|
||||
|
||||
separator = intersection.join(
|
||||
[header_separator * (size + padding * 2) for size in max_sizes]
|
||||
)
|
||||
|
||||
table = f"{header}\n{separator}\n{table}"
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def clean(
|
||||
message: discord.Message, call_rss: list[models.CallUserChannelRelationship]
|
||||
) -> str:
|
||||
@@ -75,9 +137,11 @@ def clean(
|
||||
for call_rs in call_rss:
|
||||
cleaned_message = cleaned_message.replace(
|
||||
f"<@{call_rs.user_id}>",
|
||||
(
|
||||
f"@**{call_rs.display_name}**"
|
||||
if message.channel.id == call_rs.channel_id
|
||||
else f"@**{call_rs.profile.name}**",
|
||||
else f"@**{call_rs.profile.name}**"
|
||||
),
|
||||
)
|
||||
|
||||
for user in message.mentions:
|
||||
|
||||
@@ -82,9 +82,11 @@ class HelpCommand(commands.HelpCommand):
|
||||
[f" <{option.name}>" for option in command.options]
|
||||
if isinstance(command, discord.SlashCommand)
|
||||
else [
|
||||
(
|
||||
f" [<{name}>]"
|
||||
if typing_utils.is_optional(info.annotation)
|
||||
else f" <{name}>"
|
||||
)
|
||||
for name, info in command.params.items()
|
||||
if name not in ["self", "ctx"]
|
||||
]
|
||||
|
||||
@@ -7,8 +7,7 @@ from payphone.core import config
|
||||
|
||||
|
||||
async def init() -> None:
|
||||
"""Initialize the database and it's connections.
|
||||
"""
|
||||
"""Initialize the database and it's connections."""
|
||||
|
||||
await tortoise.Tortoise.init(config.TORTOISE_ORM, use_tz=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user