323 lines
9.1 KiB
Python
323 lines
9.1 KiB
Python
from discord import TextChannel
|
|
from discord.ext import commands
|
|
from discord.utils import find
|
|
from discord_slash import SlashContext, cog_ext
|
|
from discord_slash.utils.manage_commands import create_option
|
|
from discord_slash.utils.manage_components import (
|
|
create_actionrow,
|
|
create_select,
|
|
create_select_option,
|
|
wait_for_component,
|
|
)
|
|
|
|
from jarvis.db.models import Star, Starboard
|
|
from jarvis.utils import build_embed
|
|
from jarvis.utils.permissions import admin_or_permissions
|
|
|
|
supported_images = [
|
|
"image/png",
|
|
"image/gif",
|
|
"image/jpeg",
|
|
"image/webp",
|
|
"image/svg",
|
|
]
|
|
|
|
|
|
class StarboardCog(commands.Cog):
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="starboard",
|
|
name="list",
|
|
description="Lists all Starboards",
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _list(self, ctx):
|
|
starboards = Starboard.objects(guild=ctx.guild.id)
|
|
if starboards != []:
|
|
message = "Available Starboards:\n"
|
|
for s in starboards:
|
|
message += f"<#{s.channel}>\n"
|
|
await ctx.send(message)
|
|
else:
|
|
await ctx.send("No Starboards available.")
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="starboard",
|
|
name="create",
|
|
description="Create a starboard",
|
|
options=[
|
|
create_option(
|
|
name="channel",
|
|
description="Starboard channel",
|
|
option_type=7,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _create(self, ctx, channel: TextChannel):
|
|
if channel not in ctx.guild.channels:
|
|
await ctx.send(
|
|
"Channel not in guild. Choose an existing channel.",
|
|
hidden=True,
|
|
)
|
|
return
|
|
if not isinstance(channel, TextChannel):
|
|
await ctx.send("Channel must be a TextChannel", hidden=True)
|
|
return
|
|
|
|
exists = Starboard.objects(
|
|
channel=channel.id, guild=ctx.guild.id
|
|
).first()
|
|
if exists:
|
|
await ctx.send(
|
|
f"Starboard already exists at {channel.mention}.", hidden=True
|
|
)
|
|
return
|
|
|
|
count = Starboard.objects(guild=ctx.guild.id).count()
|
|
if count >= 25:
|
|
await ctx.send("25 starboard limit reached", hidden=True)
|
|
return
|
|
|
|
_ = Starboard(
|
|
guild=ctx.guild.id,
|
|
channel=channel.id,
|
|
admin=ctx.author.id,
|
|
).save()
|
|
await ctx.send(
|
|
f"Starboard created. Check it out at {channel.mention}."
|
|
)
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="starboard",
|
|
name="delete",
|
|
description="Delete a starboard",
|
|
options=[
|
|
create_option(
|
|
name="channel",
|
|
description="Starboard channel",
|
|
option_type=7,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _delete(self, ctx, channel: TextChannel):
|
|
deleted = Starboard.objects(
|
|
channel=channel.id, guild=ctx.guild.id
|
|
).delete()
|
|
if deleted:
|
|
_ = Star.objects(starboard=channel.id).delete()
|
|
await ctx.send(
|
|
f"Starboard deleted from {channel.mention}.", hidden=True
|
|
)
|
|
else:
|
|
await ctx.send(
|
|
f"Starboard not found in {channel.mention}.", hidden=True
|
|
)
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="star",
|
|
name="add",
|
|
description="Star a message",
|
|
options=[
|
|
create_option(
|
|
name="message",
|
|
description="Message to star",
|
|
option_type=3,
|
|
required=True,
|
|
),
|
|
create_option(
|
|
name="channel",
|
|
description="Channel that has the message, "
|
|
+ "required if different than command message",
|
|
option_type=7,
|
|
required=False,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _star_add(
|
|
self,
|
|
ctx: SlashContext,
|
|
message: str,
|
|
channel: TextChannel = None,
|
|
):
|
|
if not channel:
|
|
channel = ctx.channel
|
|
starboards = Starboard.objects(guild=ctx.guild.id)
|
|
if not starboards:
|
|
await ctx.send("No starboards exist.", hidden=True)
|
|
return
|
|
|
|
await ctx.defer()
|
|
channel_list = []
|
|
for starboard in starboards:
|
|
channel_list.append(
|
|
find(lambda x: x.id == starboard.channel, ctx.guild.channels)
|
|
)
|
|
|
|
select_channels = [
|
|
create_select_option(label=x.name, value=str(idx))
|
|
for idx, x in enumerate(channel_list)
|
|
]
|
|
|
|
select = create_select(
|
|
options=select_channels,
|
|
min_values=1,
|
|
max_values=1,
|
|
)
|
|
|
|
components = [create_actionrow(select)]
|
|
|
|
msg = await ctx.send(
|
|
content="Choose a starboard", components=components
|
|
)
|
|
|
|
com_ctx = await wait_for_component(
|
|
self.bot,
|
|
messages=msg,
|
|
components=components,
|
|
check=lambda x: x.author.id == ctx.author.id,
|
|
)
|
|
|
|
starboard = channel_list[int(com_ctx.selected_options[0])]
|
|
|
|
if message.startswith("https://"):
|
|
message = message.split("/")[-1]
|
|
|
|
message = await channel.fetch_message(int(message))
|
|
|
|
exists = Star.objects(
|
|
message=message.id,
|
|
channel=message.channel.id,
|
|
guild=message.guild.id,
|
|
starboard=starboard.id,
|
|
).first()
|
|
|
|
if exists:
|
|
await ctx.send(
|
|
f"Message already sent to Starboard {starboard.mention}",
|
|
hidden=True,
|
|
)
|
|
return
|
|
|
|
count = len(
|
|
Star.get_many(guild=message.guild.id, starboard=starboard.id)
|
|
)
|
|
content = message.content
|
|
|
|
attachments = message.attachments
|
|
image_url = None
|
|
if attachments:
|
|
for attachment in attachments:
|
|
if attachment.content_type in supported_images:
|
|
image_url = attachment.url
|
|
break
|
|
if not content and image_url:
|
|
content = "\u200b"
|
|
|
|
embed = build_embed(
|
|
title=f"[#{count}] Click Here to view context",
|
|
description=content,
|
|
fields=[],
|
|
url=message.jump_url,
|
|
timestamp=message.created_at,
|
|
)
|
|
embed.set_author(
|
|
name=message.author.name,
|
|
url=message.jump_url,
|
|
icon_url=message.author.avatar_url,
|
|
)
|
|
embed.set_footer(
|
|
text=message.guild.name + " | " + message.channel.name
|
|
)
|
|
if image_url:
|
|
embed.set_image(url=image_url)
|
|
|
|
star = await starboard.send(embed=embed)
|
|
|
|
_ = Star(
|
|
index=count,
|
|
message=message.id,
|
|
channel=message.channel.id,
|
|
guild=message.guild.id,
|
|
starboard=starboard.id,
|
|
admin=ctx.author.id,
|
|
star=star.id,
|
|
active=True,
|
|
).save()
|
|
|
|
components[0]["components"][0]["disabled"] = True
|
|
|
|
await com_ctx.edit_origin(
|
|
content="Message saved to Starboard.\n"
|
|
+ f"See it in {starboard.mention}",
|
|
components=components,
|
|
)
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="star",
|
|
name="delete",
|
|
description="Delete a starred message",
|
|
options=[
|
|
create_option(
|
|
name="id",
|
|
description="Star to delete",
|
|
option_type=4,
|
|
required=True,
|
|
),
|
|
create_option(
|
|
name="starboard",
|
|
description="Starboard to delete star from",
|
|
option_type=7,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _star_delete(
|
|
self,
|
|
ctx: SlashContext,
|
|
id: int,
|
|
starboard: TextChannel,
|
|
):
|
|
if not isinstance(starboard, TextChannel):
|
|
await ctx.send("Channel must be a TextChannel", hidden=True)
|
|
return
|
|
exists = Starboard.objects(
|
|
channel=starboard.id, guild=ctx.guild.id
|
|
).first()
|
|
if not exists:
|
|
await ctx.send(
|
|
f"Starboard does not exist in {starboard.mention}. "
|
|
+ "Please create it first",
|
|
hidden=True,
|
|
)
|
|
return
|
|
|
|
star = Star.objects(
|
|
starboard=starboard.id,
|
|
index=id,
|
|
guild=ctx.guild.id,
|
|
active=True,
|
|
).first()
|
|
if not star:
|
|
await ctx.send(f"No star exists with id {id}", hidden=True)
|
|
return
|
|
|
|
message = await starboard.fetch_message(star.star)
|
|
if message:
|
|
await message.delete()
|
|
|
|
star.active = False
|
|
star.save()
|
|
|
|
await ctx.send(f"Star {id} deleted")
|
|
|
|
|
|
def setup(bot):
|
|
bot.add_cog(StarboardCog(bot))
|