feat(bot): ✨ Add servers leaderboard.
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from tortoise import transactions
|
||||
import discord
|
||||
from discord import errors
|
||||
from discord.ext import commands, tasks
|
||||
|
||||
from tortoise import transactions, functions, exceptions
|
||||
|
||||
from payphone import bot
|
||||
from payphone.db import models, utils
|
||||
@@ -12,6 +15,82 @@ class Admin(base.Cog):
|
||||
def __init__(self, bot_instance: bot.Payphone):
|
||||
self.bot = bot_instance
|
||||
|
||||
self.update_leaderboard.add_exception_type(exceptions.ConfigurationError)
|
||||
self.update_leaderboard.start()
|
||||
|
||||
def cog_unload(self) -> None:
|
||||
self.update_leaderboard.cancel()
|
||||
|
||||
@tasks.loop(minutes=15)
|
||||
async def update_leaderboard(self) -> None:
|
||||
"""Updates the leaderboard."""
|
||||
|
||||
calls = (
|
||||
await models.Call.annotate(messages_count=functions.Count("messages"))
|
||||
.filter(
|
||||
started_at__month=datetime.now(timezone.utc).month,
|
||||
started_at__year=datetime.now(timezone.utc).year,
|
||||
messages_count__gte=25,
|
||||
)
|
||||
.prefetch_related(
|
||||
"call_rss", "call_rss__channel", "call_rss__channel__server"
|
||||
)
|
||||
)
|
||||
|
||||
# ID to count
|
||||
servers_count_map: dict[int, int] = {}
|
||||
|
||||
servers_map: dict[int, models.Server] = {
|
||||
rs.channel.server_id: rs.channel.server
|
||||
for call in calls
|
||||
for rs in call.call_rss
|
||||
}
|
||||
|
||||
for call in calls:
|
||||
for rs in call.call_rss:
|
||||
if rs.channel.server_id in servers_count_map:
|
||||
servers_count_map[rs.channel.server.id] += 1
|
||||
|
||||
else:
|
||||
servers_count_map[rs.channel.server_id] = 0
|
||||
|
||||
server_counts = list(servers_count_map.items())
|
||||
|
||||
server_counts.sort(key=lambda i: i[1], reverse=True)
|
||||
|
||||
for server_map in server_counts[:10]:
|
||||
if servers_map[server_map[0]].name is None:
|
||||
try:
|
||||
servers_map[server_map[0]].name = (
|
||||
await self.bot.fetch_guild(server_map[0])
|
||||
).name
|
||||
|
||||
except errors.DiscordException:
|
||||
pass
|
||||
|
||||
for i, server_map in enumerate(server_counts):
|
||||
servers_map[server_map[0]].leaderboard_position = i + 1
|
||||
servers_map[server_map[0]].leaderboard_calls_count = server_map[1]
|
||||
|
||||
await models.Server.bulk_update(
|
||||
servers_map.values(),
|
||||
["name", "leaderboard_position", "leaderboard_calls_count"],
|
||||
500,
|
||||
)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_guild_update(
|
||||
self, _before: discord.Guild, after: discord.Guild
|
||||
) -> None:
|
||||
"""Updates a server.
|
||||
|
||||
Args:
|
||||
_before (discord.Guild): The server before it being updated.
|
||||
after (discord.Guild): The server after it being updated.
|
||||
"""
|
||||
|
||||
await models.Server.update_or_create({"name": after.name}, id=after.id)
|
||||
|
||||
@commands.group(invoke_without_command=True)
|
||||
@commands.guild_only()
|
||||
@commands.has_guild_permissions(manage_guild=True)
|
||||
|
||||
Reference in New Issue
Block a user