310 lines
9.4 KiB
Python
310 lines
9.4 KiB
Python
"""J.A.R.V.I.S. Starboard Cog."""
|
|
from discord import TextChannel
|
|
from discord.ext import commands
|
|
from discord.utils import find
|
|
from discord_slash import SlashContext, cog_ext
|
|
from discord_slash.context import MenuContext
|
|
from discord_slash.model import ContextMenuType, SlashMessage
|
|
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):
|
|
"""J.A.R.V.I.S. Starboard Cog."""
|
|
|
|
def __init__(self, bot: commands.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: SlashContext) -> None:
|
|
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: SlashContext, channel: TextChannel) -> None:
|
|
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: SlashContext, channel: TextChannel) -> None:
|
|
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_context_menu(name="Star Message", target=ContextMenuType.MESSAGE)
|
|
async def _star_message(self, ctx: MenuContext) -> None:
|
|
await self._star_add.invoke(ctx, ctx.target_message)
|
|
|
|
@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,
|
|
) -> 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 not isinstance(message, SlashMessage):
|
|
if message.startswith("https://"):
|
|
message = message.split("/")[-1]
|
|
message = await channel.fetch_message(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 = Star.objects(guild=message.guild.id, starboard=starboard.id).count()
|
|
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.display_avatar,
|
|
)
|
|
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=f"Message saved to Starboard.\nSee 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,
|
|
) -> None:
|
|
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: commands.Bot) -> None:
|
|
"""Add StarboardCog to J.A.R.V.I.S."""
|
|
bot.add_cog(StarboardCog(bot))
|
|
bot.add_cog(StarboardCog(bot))
|