1
Fork 0
mirror of https://github.com/wlinator/luminara.git synced 2024-10-02 18:23:12 +00:00

Add and remove custom reactions with commands

This commit is contained in:
wlinator 2024-07-11 12:47:46 -04:00
parent 26db690687
commit 4ffcf473ae
5 changed files with 161 additions and 9 deletions

View file

@ -7,7 +7,8 @@
"exclaim": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_exclaim.png?_=3",
"question": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_question.png?_=2",
"hammer": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_hammer.png?_=1",
"cross": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_cross.png?_=1",
"cross": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_cross.png?_=2",
"check": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_check.png?_=1",
"streak": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_streak.png?_=2",
"streak_bronze": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_streak_bronze.png?_=1",
"streak_silver": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_streak_silver.png?_=1",

49
lib/embeds/triggers.py Normal file
View file

@ -0,0 +1,49 @@
import discord
from typing import Optional
from config.parser import JsonCache
from lib import formatter
import datetime
resources = JsonCache.read_json("art")
check_icon = resources["icons"]["check"]
cross_icon = resources["icons"]["cross"]
logo = resources["logo"]["transparent"]
def create_embed(title: str, description: str, color: int, icon_url: str) -> discord.Embed:
embed = discord.Embed(
color=color,
description=description
)
embed.set_author(name=title, icon_url=icon_url)
embed.set_footer(text="Reaction Service", icon_url=logo)
embed.timestamp = datetime.datetime.utcnow()
return embed
def create_creation_embed(trigger_text: str, response: Optional[str], emoji_id: Optional[int], is_emoji: bool, is_full_match: bool) -> discord.Embed:
trigger_text = formatter.shorten(trigger_text, 50)
if response:
response = formatter.shorten(response, 50)
description = (
f"**Trigger Text:** `{trigger_text}`\n"
f"**Reaction Type:** {'Emoji' if is_emoji else 'Text'}\n"
f"{f'**Emoji ID:** `{str(emoji_id)}`' if is_emoji else f'**Response:** `{response}`'}\n"
f"**Full Match:** `{is_full_match}`"
)
return create_embed("Custom Reaction Created", description, 0xFF8C00, check_icon)
def create_failure_embed(trigger_text: str, is_emoji: bool, limit_reached: bool = False, trigger_already_exists: bool = False) -> discord.Embed:
trigger_text = formatter.shorten(trigger_text, 50)
description = f"**Trigger Text:** `{trigger_text}`\n"
if limit_reached:
description += "Failed to add custom reaction. You have reached the limit of 100 custom reactions for this server."
elif trigger_already_exists:
description += "Failed to add custom reaction. This text already contains another trigger. To avoid unexpected behavior, please delete it before adding a new one."
else:
description += "Failed to add custom reaction."
return create_embed("Custom Reaction Creation Failed", description, 0xFF0000, cross_icon)

View file

@ -0,0 +1,53 @@
from discord.commands import SlashCommandGroup
from discord.ext import commands
import discord
from lib import checks
from Client import LumiBot
from modules.triggers.add import add_reaction
class Triggers(commands.Cog):
def __init__(self, client: LumiBot):
self.client = client
trigger = SlashCommandGroup(
"trigger", "Manage custom reactions.", guild_only=True
)
add = trigger.create_subgroup("add", "Add new custom reactions.")
@add.command(
name="response",
description="Add a new custom text reaction.",
help="Add a new custom text reaction to the database.",
)
@commands.guild_only()
@checks.allowed_in_channel()
async def add_text_reaction_command(
self,
ctx,
trigger_text: str,
response: str,
is_full_match: bool
):
await add_reaction(ctx, trigger_text, response, None, False, is_full_match)
@add.command(
name="emoji",
description="Add a new custom emoji reaction.",
help="Add a new custom emoji reaction to the database.",
)
@commands.guild_only()
@checks.allowed_in_channel()
async def add_emoji_reaction_command(
self,
ctx,
trigger_text: str,
emoji: discord.Emoji,
is_full_match: bool
):
await add_reaction(ctx, trigger_text, None, emoji.id, True, is_full_match)
def setup(client: LumiBot):
client.add_cog(Triggers(client))

51
modules/triggers/add.py Normal file
View file

@ -0,0 +1,51 @@
from discord.ext import bridge
from typing import Optional
from services.reactions_service import CustomReactionsService
from lib.embeds.triggers import create_creation_embed, create_failure_embed
async def add_reaction(ctx: bridge.Context, trigger_text: str, response: Optional[str], emoji_id: Optional[int], is_emoji: bool, is_full_match: bool) -> None:
if ctx.guild is None:
return
reaction_service = CustomReactionsService()
guild_id: int = ctx.guild.id
creator_id: int = ctx.author.id
if not await check_reaction_limit(ctx, reaction_service, guild_id, trigger_text, is_emoji):
return
if not await check_existing_trigger(ctx, reaction_service, guild_id, trigger_text, is_emoji):
return
success: bool = await reaction_service.create_custom_reaction(
guild_id=guild_id,
creator_id=creator_id,
trigger_text=trigger_text,
response=response,
emoji_id=emoji_id,
is_emoji=is_emoji,
is_full_match=is_full_match,
is_global=False, # only bot admins can create global custom reactions
)
if success:
embed = create_creation_embed(trigger_text, response, emoji_id, is_emoji, is_full_match)
await ctx.respond(embed=embed)
else:
embed = create_failure_embed(trigger_text, is_emoji)
await ctx.respond(embed=embed)
async def check_reaction_limit(ctx: bridge.Context, reaction_service: CustomReactionsService, guild_id: int, trigger_text: str, is_emoji: bool) -> bool:
if await reaction_service.count_custom_reactions(guild_id) >= 100:
embed = create_failure_embed(trigger_text, is_emoji, limit_reached=True)
await ctx.respond(embed=embed)
return False
return True
async def check_existing_trigger(ctx: bridge.Context, reaction_service: CustomReactionsService, guild_id: int, trigger_text: str, is_emoji: bool) -> bool:
existing_trigger = await reaction_service.find_trigger(guild_id, trigger_text)
if existing_trigger:
embed = create_failure_embed(trigger_text, is_emoji, trigger_already_exists=True)
await ctx.respond(embed=embed)
return False
return True

View file

@ -76,8 +76,7 @@ class CustomReactionsService:
async def edit_custom_reaction(
self,
guild_id: int,
trigger_text: str,
reaction_id: int,
new_response: Optional[str] = None,
new_emoji_id: Optional[int] = None,
is_emoji: Optional[bool] = None,
@ -92,7 +91,7 @@ class CustomReactionsService:
is_full_match = COALESCE(?, is_full_match),
is_global = COALESCE(?, is_global),
updated_at = ?
WHERE guild_id = ? AND trigger_text = ?
WHERE id = ?
"""
database.execute_query(
query,
@ -103,18 +102,17 @@ class CustomReactionsService:
is_full_match,
is_global,
datetime.utcnow(),
guild_id,
trigger_text,
reaction_id,
),
)
return True
async def delete_custom_reaction(self, guild_id: int, trigger_text: str) -> bool:
async def delete_custom_reaction(self, reaction_id: int) -> bool:
query = """
DELETE FROM custom_reactions
WHERE guild_id = ? AND trigger_text = ?
WHERE id = ?
"""
database.execute_query(query, (guild_id, trigger_text))
database.execute_query(query, (reaction_id,))
return True
async def count_custom_reactions(self, guild_id: int) -> int: