Fix starboard (use redis)

This commit is contained in:
Nexus 2024-05-05 01:10:33 +01:00
parent 991d66786f
commit cd45dc4844
Signed by: nex
GPG key ID: 0FA334385D0B689F
2 changed files with 44 additions and 23 deletions

View file

@ -1,21 +1,20 @@
import asyncio import asyncio
import io import io
import textwrap import textwrap
from typing import Tuple import redis
import json
from urllib.parse import urlparse from urllib.parse import urlparse
import discord import discord
import httpx import httpx
import orm
from discord.ext import commands from discord.ext import commands
from utils.db import StarBoardMessage
class StarBoardCog(commands.Cog): class StarBoardCog(commands.Cog):
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
self.lock = asyncio.Lock() self.lock = asyncio.Lock()
self.redis = redis.asyncio.Redis(decode_responses=True)
@staticmethod @staticmethod
async def archive_image(starboard_message: discord.Message): async def archive_image(starboard_message: discord.Message):
@ -115,7 +114,7 @@ class StarBoardCog(commands.Cog):
embed.add_field(name=name, value=f"||[{file.filename}]({file.url})||", inline=False) embed.add_field(name=name, value=f"||[{file.filename}]({file.url})||", inline=False)
else: else:
if file.content_type.startswith("image"): if file.content_type.startswith("image"):
if embed.image.url is discord.Embed.Empty: if embed.image is not None:
embed.set_image(url=file.url) embed.set_image(url=file.url)
embed.add_field(name=name, value=f"[{file.filename}]({file.url})", inline=False) embed.add_field(name=name, value=f"[{file.filename}]({file.url})", inline=False)
@ -130,41 +129,56 @@ class StarBoardCog(commands.Cog):
async with self.lock: async with self.lock:
if str(payload.emoji) != "\N{white medium star}": if str(payload.emoji) != "\N{white medium star}":
return return
message: discord.Message = await self.bot.get_channel(payload.channel_id).fetch_message(payload.message_id) _channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
message: discord.Message = await _channel.fetch_message(payload.message_id)
if message.author.id == payload.user_id and payload.event_type == "REACTION_ADD": if message.author.id == payload.user_id and payload.event_type == "REACTION_ADD":
if message.channel.permissions_for(message.guild.me).manage_messages: if message.channel.permissions_for(message.guild.me).manage_messages:
await message.remove_reaction(payload.emoji, message.author) await message.remove_reaction(payload.emoji, message.author)
return await message.reply( return await message.reply(
f"You can't star your own messages you pretentious dick, {message.author.mention}." f"You can't star your own messages you pretentious dick, {message.author.mention}."
) )
star_count = [x for x in message.reactions if str(x.emoji) == "\N{white medium star}"] star_count = [x for x in message.reactions if str(x.emoji) == "\N{white medium star}"]
if not star_count: if not star_count:
star_count = 0 star_count = 0
else: else:
star_count = star_count[0].count star_count = star_count[0].count
entry = await self.redis.get(str(message.id))
if entry:
entry = json.loads(entry)
channel = discord.utils.get(message.guild.text_channels, name="starboard")
if not channel:
return
if star_count == 0: if star_count == 0:
try: if not entry:
database: StarBoardMessage = await StarBoardMessage.objects.get(id=payload.message_id)
except orm.NoMatch:
return return
else: else:
channel = discord.utils.get(message.guild.text_channels, name="starboard") entry = json.loads(entry)
if channel: if channel:
try: try:
message = await channel.fetch_message(database.id) message = await channel.fetch_message(entry["starboard_msg_id"])
await message.delete(delay=0.1, reason="Starboard message lost all stars.") await message.delete(delay=0.1, reason="Starboard message lost all stars.")
except discord.HTTPException: except discord.HTTPException:
pass pass
finally: finally:
await database.delete() return await self.redis.delete(str(message.id))
else: else:
await database.delete() return await self.redis.delete(str(message.id))
if not entry:
created = True
entry = {
"message_id": payload.message_id,
"channel_id": payload.channel_id,
"guild_id": payload.guild_id,
"starboard_channel_id": channel.id,
"starboard_message_id": None
}
else:
created = False
database: Tuple[StarBoardMessage, bool] = await StarBoardMessage.objects.get_or_create(
{"channel": payload.channel_id}, id=payload.message_id
)
entry, created = database
if created: if created:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
cap = message.channel cap = message.channel
@ -173,15 +187,15 @@ class StarBoardCog(commands.Cog):
else: else:
cap = cap.member_count * 0.1 cap = cap.member_count * 0.1
if star_count >= cap: if star_count >= cap:
channel = discord.utils.get(message.guild.text_channels, name="starboard") if channel and channel.can_send(discord.Embed()):
if channel and channel.can_send():
embed = await self.generate_starboard_embed(message) embed = await self.generate_starboard_embed(message)
embeds = [embed, *tuple(filter(lambda x: x.type == "rich", message.embeds))][:10] embeds = [embed, *tuple(filter(lambda x: x.type == "rich", message.embeds))][:10]
msg = await channel.send(embeds=embeds) msg = await channel.send(embeds=embeds)
await entry.update(starboard_message=msg.id) entry["starboard_message_id"] = msg.id
await self.redis.set(str(payload.message_id), json.dumps(entry))
self.bot.loop.create_task(self.archive_image(msg)) self.bot.loop.create_task(self.archive_image(msg))
else: else:
await entry.delete() await self.redis.delete(str(payload.message_id))
return return
else: else:
channel = discord.utils.get(message.guild.text_channels, name="starboard") channel = discord.utils.get(message.guild.text_channels, name="starboard")
@ -192,7 +206,9 @@ class StarBoardCog(commands.Cog):
msg = await channel.fetch_message(entry.starboard_message) msg = await channel.fetch_message(entry.starboard_message)
except discord.NotFound: except discord.NotFound:
msg = await channel.send(embeds=embeds) msg = await channel.send(embeds=embeds)
await entry.update(starboard_message=msg.id) # await entry.update(starboard_message=msg.id)
entry["starboard_message_id"] = msg.id
await self.redis.set(str(payload.message_id), json.dumps(entry))
self.bot.loop.create_task(self.archive_image(msg)) self.bot.loop.create_task(self.archive_image(msg))
except discord.HTTPException: except discord.HTTPException:
pass pass
@ -203,7 +219,11 @@ class StarBoardCog(commands.Cog):
@commands.message_command(name="Starboard Info") @commands.message_command(name="Starboard Info")
@discord.guild_only() @discord.guild_only()
async def get_starboard_info(self, ctx: discord.ApplicationContext, message: discord.Message): async def get_starboard_info(self, ctx: discord.ApplicationContext, message: discord.Message):
return await ctx.respond(embed=await self.generate_starboard_embed(message)) data = await self.redis.get(str(message.id))
return await ctx.respond(
'```json\n%s\n```' % json.dumps(data, indent=4),
embed=await self.generate_starboard_embed(message)
)
def setup(bot): def setup(bot):

View file

@ -23,3 +23,4 @@ humanize>=4.6.0
blend-modes>=2.1.0 blend-modes>=2.1.0
openai>=1.3.7 openai>=1.3.7
pydub>=0.25.1 pydub>=0.25.1
redis~=5.0