mirror of
https://github.com/nexy7574/LCC-bot.git
synced 2024-09-19 10:03:40 +01:00
Add starboard
This commit is contained in:
parent
9d8a41ee4a
commit
93ca4386fd
5 changed files with 175 additions and 17 deletions
|
@ -370,17 +370,15 @@ class AssignmentsCog(commands.Cog):
|
|||
else:
|
||||
option = 10080
|
||||
name = textwrap.shorten(modal.create_kwargs["title"], width=100, placeholder="...")
|
||||
tag = discord.utils.get(channel.available_tags, name=modal.create_kwargs['tutor'].name.title())
|
||||
tag = discord.utils.get(channel.available_tags, name=modal.create_kwargs["tutor"].name.title())
|
||||
await channel.create_thread(
|
||||
name=name,
|
||||
content="Assignment name: {0}\nDue: {1} ({4})\nTutor: {2}\nCreated by: {3}".format(
|
||||
modal.create_kwargs["title"],
|
||||
discord.utils.format_dt(
|
||||
due_dt, style="F"
|
||||
),
|
||||
discord.utils.format_dt(due_dt, style="F"),
|
||||
modal.create_kwargs["tutor"].name,
|
||||
ctx.user.mention,
|
||||
discord.utils.format_dt(due_dt, "R")
|
||||
discord.utils.format_dt(due_dt, "R"),
|
||||
),
|
||||
auto_archive_duration=option,
|
||||
applied_tags=[tag] if tag else [],
|
||||
|
|
140
cogs/starboard.py
Normal file
140
cogs/starboard.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
import asyncio
|
||||
import textwrap
|
||||
from typing import Tuple
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from utils.db import StarBoardMessage
|
||||
|
||||
|
||||
class StarBoardCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.lock = asyncio.Lock()
|
||||
|
||||
async def generate_starboard_embed(self, message: discord.Message) -> discord.Embed:
|
||||
star_count = [x for x in message.reactions if str(x.emoji) == "\N{white medium star}"]
|
||||
if not star_count:
|
||||
star_count = 0
|
||||
else:
|
||||
star_count = star_count[0].count
|
||||
# noinspection PyUnresolvedReferences
|
||||
cap = (message.channel if "thread" in message.channel.type.name else message.guild).member_count * 0.1
|
||||
embed = discord.Embed(colour=discord.Colour.gold(), timestamp=message.created_at, description=message.content)
|
||||
embed.set_author(
|
||||
name=message.author.display_name, url=message.jump_url, icon_url=message.author.display_avatar.url
|
||||
)
|
||||
|
||||
if star_count > 5:
|
||||
stars = "\N{white medium star}x{:,}".format(star_count)
|
||||
else:
|
||||
stars = "\N{white medium star}" * star_count
|
||||
stars = stars or "\N{no entry sign}"
|
||||
|
||||
embed.add_field(
|
||||
name="Info",
|
||||
value=f"Star count: {stars}\n"
|
||||
f"Channel: {message.channel.mention}\n"
|
||||
f"Author: {message.author.mention}\n"
|
||||
f"URL: [jump]({message.jump_url})\n"
|
||||
f"Sent: {discord.utils.format_dt(message.created_at, 'R')}",
|
||||
inline=False,
|
||||
)
|
||||
if message.edited_at:
|
||||
embed.fields[0].value += "\nLast edited: " + discord.utils.format_dt(message.edited_at, "R")
|
||||
|
||||
if message.reference is not None:
|
||||
try:
|
||||
ref: discord.Message = await self.bot.get_channel(message.reference.channel_id).fetch_message(
|
||||
message.reference.message_id
|
||||
)
|
||||
except discord.HTTPException:
|
||||
pass
|
||||
else:
|
||||
embed.add_field(
|
||||
name="In reply to",
|
||||
value=f"[Message by {ref.author.display_name}]({ref.jump_url}):\n>>> ",
|
||||
inline=False,
|
||||
)
|
||||
field = embed.fields[1]
|
||||
if not ref.content:
|
||||
embed.fields[1].value = field.value.replace(":\n>>> ", "")
|
||||
else:
|
||||
embed.fields[1].value += textwrap.shorten(ref.content, 1024 - len(field.value), placeholder="...")
|
||||
|
||||
if message.attachments:
|
||||
for file in message.attachments:
|
||||
name = f"Attachment #{message.attachments.index(file)}"
|
||||
spoiler = file.is_spoiler()
|
||||
if not spoiler and file.url.lower().endswith(("png", "jpeg", "jpg", "gif", "webp")) and not embed.image:
|
||||
embed.set_image(url=file.url)
|
||||
elif spoiler:
|
||||
embed.add_field(name=name, value=f"||[{file.filename}]({file.url})||", inline=False)
|
||||
else:
|
||||
embed.add_field(name=name, value=f"[{file.filename}]({file.url})", inline=False)
|
||||
|
||||
embed.set_footer(text="Starboard threshold for this message was {:.2f}.".format(cap))
|
||||
return embed
|
||||
|
||||
@commands.Cog.listener("on_raw_reaction_add")
|
||||
@commands.Cog.listener("on_raw_reaction_remove")
|
||||
async def on_star_add(self, payload: discord.RawReactionActionEvent):
|
||||
async with self.lock:
|
||||
if str(payload.emoji) != "\N{white medium star}":
|
||||
return
|
||||
message: discord.Message = await self.bot.get_channel(payload.channel_id).fetch_message(payload.message_id)
|
||||
star_count = [x for x in message.reactions if str(x.emoji) == "\N{white medium star}"]
|
||||
if not star_count:
|
||||
star_count = 0
|
||||
else:
|
||||
star_count = star_count[0].count
|
||||
database: Tuple[StarBoardMessage, bool] = await StarBoardMessage.objects.get_or_create(
|
||||
{"channel": payload.channel_id}, id=payload.message_id
|
||||
)
|
||||
entry, created = database
|
||||
if created:
|
||||
# noinspection PyUnresolvedReferences
|
||||
cap = message.channel if "thread" in message.channel.type.name else message.guild
|
||||
if self.bot.intents.members and hasattr(cap, "members"):
|
||||
cap = len([x for x in cap.members if not x.bot]) * 0.1
|
||||
else:
|
||||
cap = cap.member_count * 0.1
|
||||
if star_count >= cap:
|
||||
channel = discord.utils.get(message.guild.text_channels, name="starboard")
|
||||
if channel and channel.can_send():
|
||||
msg = await channel.send(embed=await self.generate_starboard_embed(message))
|
||||
await entry.update(starboard_message=msg.id)
|
||||
else:
|
||||
await entry.delete()
|
||||
return
|
||||
else:
|
||||
channel = discord.utils.get(message.guild.text_channels, name="starboard")
|
||||
if channel and channel.can_send() and entry.starboard_message:
|
||||
try:
|
||||
msg = await channel.fetch_message(entry.starboard_message)
|
||||
except discord.NotFound:
|
||||
msg = await channel.send(embed=await self.generate_starboard_embed(message))
|
||||
await entry.update(starboard_message=msg.id)
|
||||
except discord.HTTPException:
|
||||
pass
|
||||
else:
|
||||
await msg.edit(embed=await self.generate_starboard_embed(message))
|
||||
|
||||
@commands.message_command(name="Starboard Info")
|
||||
@discord.guild_only()
|
||||
async def get_starboard_info(self, ctx: discord.ApplicationContext, message: discord.Message):
|
||||
return await ctx.respond(embed=await self.generate_starboard_embed(message))
|
||||
|
||||
@commands.command(name="threshold")
|
||||
@commands.guild_only()
|
||||
async def get_threshold(self, ctx: commands.Context):
|
||||
"""Shows you the current starboard threshold"""
|
||||
if self.bot.intents.members and hasattr(ctx.channel, "members"):
|
||||
cap = len([x for x in ctx.channel.members if not x.bot]) * 0.1
|
||||
else:
|
||||
cap = ctx.channel.member_count * 0.1
|
||||
return await ctx.reply(f"Messages currently need {c:.2f} stars in this channel to be posted to the starboard.")
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(StarBoardCog(bot))
|
11
main.py
11
main.py
|
@ -13,7 +13,16 @@ bot = commands.Bot(
|
|||
)
|
||||
bot.training_lock = Lock()
|
||||
|
||||
extensions = ["jishaku", "cogs.verify", "cogs.mod", "cogs.events", "cogs.assignments", "cogs.timetable", "cogs.other"]
|
||||
extensions = [
|
||||
"jishaku",
|
||||
"cogs.verify",
|
||||
"cogs.mod",
|
||||
"cogs.events",
|
||||
"cogs.assignments",
|
||||
"cogs.timetable",
|
||||
"cogs.other",
|
||||
"cogs.starboard",
|
||||
]
|
||||
for ext in extensions:
|
||||
bot.load_extension(ext)
|
||||
console.log(f"Loaded extension [green]{ext}")
|
||||
|
|
17
utils/db.py
17
utils/db.py
|
@ -119,3 +119,20 @@ class Assignments(orm.Model):
|
|||
submitted: bool
|
||||
assignees: list[int]
|
||||
# description: Optional[str]
|
||||
|
||||
|
||||
class StarBoardMessage(orm.Model):
|
||||
tablename = "starboard"
|
||||
registry = registry
|
||||
fields = {
|
||||
"entry_id": orm.UUID(primary_key=True, default=uuid.uuid4),
|
||||
"id": orm.BigInteger(unique=True),
|
||||
"channel": orm.BigInteger(),
|
||||
"starboard_message": orm.BigInteger(default=None, allow_null=True),
|
||||
}
|
||||
|
||||
if TYPE_CHECKING:
|
||||
entry_id: uuid.UUID
|
||||
id: int
|
||||
channel: int
|
||||
starboard_message: int | None
|
||||
|
|
|
@ -57,9 +57,7 @@ class VerifyView(View):
|
|||
f" (originally associated with account {ban.associated_account})"
|
||||
)
|
||||
await Student.objects.create(
|
||||
id=existing.student_id,
|
||||
user_id=interaction.user.id,
|
||||
name=existing.name
|
||||
id=existing.student_id, user_id=interaction.user.id, name=existing.name
|
||||
)
|
||||
await existing.delete()
|
||||
role = discord.utils.find(lambda r: r.name.lower() == "verified", interaction.guild.roles)
|
||||
|
@ -67,10 +65,7 @@ class VerifyView(View):
|
|||
if role and role < interaction.guild.me.top_role:
|
||||
await member.add_roles(role, reason="Verified")
|
||||
try:
|
||||
await member.edit(
|
||||
nick=f"{existing.name}",
|
||||
reason="Verified"
|
||||
)
|
||||
await member.edit(nick=f"{existing.name}", reason="Verified")
|
||||
except discord.HTTPException:
|
||||
pass
|
||||
console.log(f"[green]{interaction.user} verified ({interaction.user.id}/{existing.student_id})")
|
||||
|
@ -118,16 +113,15 @@ class VerifyView(View):
|
|||
return await interaction.followup.send(
|
||||
"\N{cross mark} Invalid student ID - Failed to verify with regex."
|
||||
" Please try again with a valid student ID. Make sure it is formatted as `BXXXXXX` "
|
||||
"(e.g. `B{}`)".format(''.join(str(random.randint(0, 9)) for _ in range(6))),
|
||||
delete_after=60
|
||||
"(e.g. `B{}`)".format("".join(str(random.randint(0, 9)) for _ in range(6))),
|
||||
delete_after=60,
|
||||
)
|
||||
|
||||
ex = await get_or_none(Student, id=st)
|
||||
if ex:
|
||||
btn.disabled = False
|
||||
return await interaction.followup.send(
|
||||
"\N{cross mark} Student ID is already associated.",
|
||||
delete_after=60
|
||||
"\N{cross mark} Student ID is already associated.", delete_after=60
|
||||
)
|
||||
|
||||
try:
|
||||
|
|
Loading…
Reference in a new issue