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

Merge pull request #33 from wlinator/patch-v2.8.11

Patch v2.8.11
This commit is contained in:
wlinator 2024-08-15 06:48:12 -04:00
commit 1fa72bda6f
15 changed files with 249 additions and 335 deletions

View file

@ -1,6 +1,4 @@
{
"lumi_exception_generic": "An error occurred.",
"lumi_exception_blacklisted": "User is blacklisted",
"admin_award_description": "awarded **${0}** to {1}.",
"admin_award_title": "Awarded Currency",
"admin_blacklist_author": "User Blacklisted",
@ -19,21 +17,23 @@
"admin_sync_error_title": "Sync Error",
"admin_sync_title": "Sync Successful",
"bet_limit": "❌ | **{0}** you cannot place any bets above **${1}**.",
"birthday_check_started": "Daily birthday check started.",
"birthday_check_skipped": "Birthday announcements in guild with ID {0} skipped: no birthday channel.",
"birthday_check_success": "Birthday announcement Success! user/guild/chan ID: {0}/{1}/{2}",
"birthday_check_error": "Birthday announcement skipped processing user/guild {0}/{1} | {2}",
"birthday_check_finished": "Daily birthday check finished. {0} birthdays processed. {1} birthdays failed.",
"birthday_add_invalid_date": "The date you entered is invalid.",
"birthday_add_success_author": "Birthday Set",
"birthday_add_success_description": "your birthday has been set to **{0} {1}**.",
"birthday_check_error": "Birthday announcement skipped processing user/guild {0}/{1} | {2}",
"birthday_check_finished": "Daily birthday check finished. {0} birthdays processed. {1} birthdays failed.",
"birthday_check_skipped": "Birthday announcements in guild with ID {0} skipped: no birthday channel.",
"birthday_check_started": "Daily birthday check started.",
"birthday_check_success": "Birthday announcement Success! user/guild/chan ID: {0}/{1}/{2}",
"birthday_delete_success_author": "Birthday Deleted",
"birthday_delete_success_description": "your birthday has been deleted from this server.",
"birthday_leap_year": "February 29",
"birthday_upcoming_author": "Upcoming Birthdays!",
"birthday_upcoming_description_line": "🎂 {0} - {1}",
"birthday_upcoming_no_birthdays_author": "No Upcoming Birthdays",
"birthday_upcoming_no_birthdays": "there are no upcoming birthdays in this server.",
"birthday_leap_year": "February 29",
"birthday_upcoming_no_birthdays_author": "No Upcoming Birthdays",
"boost_default_description": "Thanks for boosting, **{0}**!!",
"boost_default_title": "New Booster",
"case_case_field": "Case:",
"case_case_field_value": "`{0}`",
"case_duration_field": "Duration:",
@ -121,6 +121,7 @@
"error_actionable_hierarchy_bot": "I don't have permission to perform this action on this user due to role hierarchy.",
"error_actionable_hierarchy_user": "you don't have permission to perform this action on this user due to role hierarchy.",
"error_actionable_self": "you can't perform this action on yourself.",
"error_already_playing_blackjack": "you already have a game of blackjack running.",
"error_bad_argument_author": "Bad Argument",
"error_bad_argument_description": "{0}",
"error_birthdays_disabled_author": "Birthdays Disabled",
@ -146,10 +147,14 @@
"error_no_private_message_description": "this command can only be used in servers.",
"error_not_owner_author": "Owner Only",
"error_not_owner_description": "this command requires Lumi ownership permissions.",
"error_out_of_time": "you ran out of time.",
"error_out_of_time_economy": "you ran out of time. Your bet was forfeited.",
"error_private_message_only_author": "Private Message Only",
"error_private_message_only_description": "this command can only be used in private messages.",
"error_unknown_error_author": "Unknown Error",
"error_unknown_error_description": "an unknown error occurred. Please try again later.",
"greet_default_description": "_ _\n**Welcome** to **{0}**",
"greet_template_description": "↓↓↓\n{0}",
"help_use_prefix": "Please use Lumi's prefix to get help. Type `{0}help`",
"info_api_version": "**API:** v{0}\n",
"info_database_records": "**Database:** {0} records",
@ -180,6 +185,8 @@
"invite_description": "Thanks for inviting me to your server!",
"level_up": "📈 | **{0}** you have reached **Level {1}**.",
"level_up_prefix": "📈 | **{0}** ",
"lumi_exception_blacklisted": "User is blacklisted",
"lumi_exception_generic": "An error occurred.",
"mod_ban_dm": "**{0}** you have been banned from `{1}`.\n\n**Reason:** `{2}`",
"mod_banned_author": "User Banned",
"mod_banned_user": "user with ID `{0}` has been banned.",
@ -214,6 +221,31 @@
"ping_uptime": "I've been online since <t:{0}:R>.",
"stats_blackjack": "🃏 | You've played **{0}** games of BlackJack, betting a total of **${1}**. You won **{2}** of those games with a total payout of **${3}**.",
"stats_slots": "🎰 | You've played **{0}** games of Slots, betting a total of **${1}**. Your total payout was **${2}**.",
"trigger_already_exists": "Failed to add custom reaction. This text already contains another trigger. To avoid unexpected behavior, please delete it before adding a new one.",
"trigger_limit_reached": "Failed to add custom reaction. You have reached the limit of 100 custom reactions for this server.",
"triggers_add_author": "Custom Reaction Created",
"triggers_add_description": "**Trigger Text:** `{0}`\n**Reaction Type:** {1}\n**Full Match:** `{2}`\n",
"triggers_add_emoji_details": "**Emoji ID:** `{0}`",
"triggers_add_text_details": "**Response:** `{0}`",
"triggers_delete_author": "Custom Reaction Deleted",
"triggers_delete_description": "custom reaction has been successfully deleted.",
"triggers_delete_not_found_author": "Custom Reaction Not Found",
"triggers_list_custom_reaction_id": "**ID:** {0}",
"triggers_list_custom_reactions_title": "Custom Reactions",
"triggers_list_emoji_id": "**Emoji ID:** `{0}`",
"triggers_list_full_match": "**Full Match:** `{0}`",
"triggers_list_reaction_type": "**Reaction Type:** {0}",
"triggers_list_response": "**Response:** `{0}`",
"triggers_list_trigger_text": "**Trigger Text:** `{0}`",
"triggers_list_usage_count": "**Usage Count:** `{0}`",
"triggers_no_reactions_description": "There are no custom reactions set up yet.\n\nTo create a new custom reaction, use the following commands:\n`/trigger add emoji` - Add a new custom emoji reaction.\n`/trigger add response` - Add a new custom text reaction.\n\n**Emoji Reaction:**\nAn emoji reaction will react with a specific emoji when the trigger text is detected.\n\n**Text Reaction:**\nA text reaction will respond with a specific text message when the trigger text is detected.",
"triggers_no_reactions_title": "No Custom Reactions Found",
"triggers_not_added": "failed to add custom reaction. Please try again.",
"triggers_not_deleted": "something went wrong while trying to delete this trigger.",
"triggers_not_found": "no custom reaction found with the provided ID.",
"triggers_reaction_service_footer": "Reaction Service",
"triggers_type_emoji": "Emoji",
"triggers_type_text": "Text",
"xkcd_description": "[Explainxkcd]({0}) | [Webpage]({1})",
"xkcd_footer": "Xkcd Service",
"xkcd_not_found": "failed to fetch this comic.",

View file

@ -1,8 +1,7 @@
from discord.ext.commands import Cog
from loguru import logger
import lib.embeds.boost
from lib.embeds.greet import Greet
from modules.config import c_boost, c_greet
from services.blacklist_service import BlacklistUserService
from services.config_service import GuildConfig
@ -21,7 +20,7 @@ class EventHandler(Cog):
if not config.welcome_channel_id:
return
embed = Greet.message(member, config.welcome_message)
embed = c_greet.create_greet_embed(member, config.welcome_message)
try:
await member.guild.get_channel(config.welcome_channel_id).send(
@ -48,7 +47,7 @@ class EventHandler(Cog):
if not config.boost_channel_id:
return
embed = lib.embeds.boost.Boost.message(
embed = c_boost.create_boost_embed(
member,
config.boost_message,
config.boost_image_url,

View file

@ -14,7 +14,7 @@ class Constants:
TITLE = "Luminara"
AUTHOR = "wlinator"
LICENSE = "GNU General Public License v3.0"
VERSION = "2.8.10" # "Refactor JSON Handling" update
VERSION = "2.8.11" # "Embed Refactor" update
# bot credentials
TOKEN: Optional[str] = os.environ.get("TOKEN", None)

View file

@ -1,27 +0,0 @@
import discord
import lib.formatter
from lib.constants import CONST
class Boost:
@staticmethod
def message(member, template=None, image_url=None):
embed = discord.Embed(
color=discord.Color.nitro_pink(),
title="New Booster",
description=f"Thanks for boosting, **{member.name}**!!",
)
if template:
# REPLACE
embed.description = lib.formatter.template(template, member.name)
embed.set_author(name=member.name, icon_url=member.display_avatar)
embed.set_image(url=image_url if image_url else CONST.BOOST_ICON)
embed.set_footer(
text=f"Total server boosts: {member.guild.premium_subscription_count}",
icon_url=CONST.EXCLAIM_ICON,
)
return embed

View file

@ -1,41 +0,0 @@
import discord
from lib.constants import CONST
def clean_error_embed(ctx):
return discord.Embed(
color=discord.Color.red(),
description=f"**{ctx.author.name}** ",
)
class EconErrors:
@staticmethod
def out_of_time(ctx):
embed = clean_error_embed(ctx)
if embed.description is None:
embed.description = "you ran out of time."
else:
embed.description += "you ran out of time."
embed.set_footer(text="Your bet was forfeited", icon_url=CONST.EXCLAIM_ICON)
return embed
@staticmethod
def already_playing(ctx):
embed = clean_error_embed(ctx)
if embed.description is None:
embed.description = (
f"you already have a game of {ctx.command.name} running."
)
else:
embed.description += (
f"you already have a game of {ctx.command.name} running."
)
embed.set_footer(
text="Please finish this game first",
icon_url=CONST.EXCLAIM_ICON,
)
return embed

View file

@ -1,19 +0,0 @@
import discord
from lib import formatter
class Greet:
@staticmethod
def message(member, template=None):
embed = discord.Embed(
color=discord.Color.embed_background(),
description=f"_ _\n**Welcome** to **{member.guild.name}**",
)
if template:
embed.description = (
f"{embed.description}\n↓↓↓\n{formatter.template(template, member.name)}"
)
embed.set_thumbnail(url=member.display_avatar.url)
return embed

View file

@ -1,118 +0,0 @@
import datetime
from typing import Optional
from lib.constants import CONST
import discord
from lib import formatter
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=CONST.LUMI_LOGO_TRANSPARENT)
embed.timestamp = datetime.datetime.now(datetime.timezone.utc)
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,
CONST.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,
0xFF4500,
CONST.CROSS_ICON,
)
def create_deletion_embed(trigger_text: str, is_emoji: bool) -> discord.Embed:
trigger_text = formatter.shorten(trigger_text, 50)
description = f"**Trigger Text:** `{trigger_text}`\n"
description += "Custom reaction has been successfully deleted."
return create_embed(
"Custom Reaction Deleted",
description,
0xFF8C00,
CONST.CHECK_ICON,
)
def create_not_found_embed(reaction_id: int) -> discord.Embed:
description = f"**Reaction ID:** `{reaction_id}`\n"
description += "No custom reaction found with the provided ID."
return create_embed(
"Custom Reaction Not Found",
description,
0xFF4500,
CONST.CROSS_ICON,
)
def create_no_triggers_embed() -> discord.Embed:
description = (
"There are no custom reactions set up yet.\n\n"
"To create a new custom reaction, use the following commands:\n"
"`/trigger add emoji` - Add a new custom emoji reaction.\n"
"`/trigger add response` - Add a new custom text reaction.\n\n"
"**Emoji Reaction:**\n"
"An emoji reaction will react with a specific emoji when the trigger text is detected.\n\n"
"**Text Reaction:**\n"
"A text reaction will respond with a specific text message when the trigger text is detected."
)
return create_embed(
"No Custom Reactions Found",
description,
0xFF8C00,
CONST.EXCLAIM_ICON,
)

View file

@ -69,11 +69,10 @@ class IntroductionFinishButtons(View):
self.stop()
async def interaction_check(self, interaction: discord.Interaction) -> bool:
if interaction.user != self.ctx.author:
await interaction.response.send_message(
"You can't use these buttons.",
ephemeral=True,
)
return False
else:
if interaction.user == self.ctx.author:
return True
await interaction.response.send_message(
"You can't use these buttons.",
ephemeral=True,
)
return False

View file

@ -10,7 +10,6 @@ from services.birthday_service import Birthday
async def add(ctx, month, month_index, day):
"""Set a user's birthday in a specific guild."""
leap_year = 2020
max_days = calendar.monthrange(leap_year, month_index)[1]
@ -35,7 +34,6 @@ async def add(ctx, month, month_index, day):
async def delete(ctx):
"""Delete a user's birthday in a specific server."""
Birthday(ctx.author.id, ctx.guild.id).delete()
embed = EmbedBuilder.create_success_embed(
@ -48,7 +46,6 @@ async def delete(ctx):
async def upcoming(ctx):
"""Get the upcoming birthdays for a specific server."""
upcoming_birthdays = Birthday.get_upcoming_birthdays(ctx.guild.id)
if not upcoming_birthdays:

View file

@ -3,7 +3,7 @@ from lib.embed_builder import EmbedBuilder
from lib.constants import CONST
from services.config_service import GuildConfig
from lib.exceptions.LumiExceptions import LumiException
from lib.embeds.boost import Boost
import lib.formatter
async def set_boost_channel(ctx, channel: discord.TextChannel):
@ -61,7 +61,7 @@ async def set_boost_template(ctx, text: str):
await ctx.respond(embed=embed)
example_embed = Boost.message(ctx.author, text, guild_config.boost_image_url)
example_embed = create_boost_embed(ctx.author, text, guild_config.boost_image_url)
return await ctx.send(embed=example_embed, content=ctx.author.mention)
@ -94,5 +94,31 @@ async def set_boost_image(ctx, image_url: str | None):
await ctx.respond(embed=embed)
example_embed = Boost.message(ctx.author, guild_config.boost_message, image_url)
example_embed = create_boost_embed(
ctx.author,
guild_config.boost_message,
image_url,
)
return await ctx.send(embed=example_embed, content=ctx.author.mention)
async def create_boost_embed(
member: discord.Member,
template: str | None = None,
image_url: str | None = None,
):
embed = discord.Embed(
color=discord.Color.nitro_pink(),
title=CONST.STRINGS["boost_default_title"],
description=CONST.STRINGS["boost_default_description"].format(member.name),
)
if template:
embed.description = lib.formatter.template(template, member.name)
embed.set_author(name=member.name, icon_url=member.display_avatar)
embed.set_image(url=image_url or CONST.BOOST_ICON)
embed.set_footer(
text=f"Total server boosts: {member.guild.premium_subscription_count}",
icon_url=CONST.EXCLAIM_ICON,
)

View file

@ -1,29 +1,37 @@
from typing import Optional
import discord
from lib.embed_builder import EmbedBuilder
from discord.ext.commands import MemberConverter
from lib import formatter
from lib.constants import CONST
from lib.embed_builder import EmbedBuilder
from lib.exceptions.LumiExceptions import LumiException
from services.config_service import GuildConfig
from lib.embeds.greet import Greet
async def set_welcome_channel(ctx, channel: discord.TextChannel):
guild_config = GuildConfig(ctx.guild.id)
async def set_welcome_channel(ctx, channel: discord.TextChannel) -> None:
if not ctx.guild:
raise LumiException()
guild_config: GuildConfig = GuildConfig(ctx.guild.id)
guild_config.welcome_channel_id = channel.id
guild_config.push()
embed = EmbedBuilder().create_success_embed(
embed: discord.Embed = EmbedBuilder().create_success_embed(
ctx=ctx,
author_text=CONST.STRINGS["config_author"],
description=CONST.STRINGS["config_welcome_channel_set"].format(channel.mention),
)
return await ctx.respond(embed=embed)
await ctx.respond(embed=embed)
async def disable_welcome_module(ctx):
guild_config = GuildConfig(ctx.guild.id)
async def disable_welcome_module(ctx) -> None:
guild_config: GuildConfig = GuildConfig(ctx.guild.id)
if not guild_config.welcome_channel_id:
embed = EmbedBuilder().create_warning_embed(
embed: discord.Embed = EmbedBuilder().create_warning_embed(
ctx=ctx,
author_text=CONST.STRINGS["config_author"],
description=CONST.STRINGS["config_welcome_module_already_disabled"],
@ -32,21 +40,24 @@ async def disable_welcome_module(ctx):
guild_config.welcome_channel_id = None
guild_config.welcome_message = None
guild_config.push()
embed = EmbedBuilder().create_success_embed(
embed: discord.Embed = EmbedBuilder().create_success_embed(
ctx=ctx,
author_text=CONST.STRINGS["config_author"],
description=CONST.STRINGS["config_welcome_module_disabled"],
)
return await ctx.respond(embed=embed)
await ctx.respond(embed=embed)
async def set_welcome_template(ctx, text: str):
guild_config = GuildConfig(ctx.guild.id)
async def set_welcome_template(ctx, text: str) -> None:
if not ctx.guild:
raise LumiException()
guild_config: GuildConfig = GuildConfig(ctx.guild.id)
guild_config.welcome_message = text
guild_config.push()
embed = EmbedBuilder().create_success_embed(
embed: discord.Embed = EmbedBuilder().create_success_embed(
ctx=ctx,
author_text=CONST.STRINGS["config_author"],
description=CONST.STRINGS["config_welcome_template_updated"],
@ -60,5 +71,26 @@ async def set_welcome_template(ctx, text: str):
await ctx.respond(embed=embed)
example_embed = Greet.message(ctx.author, text)
return await ctx.send(embed=example_embed, content=ctx.author.mention)
greet_member: discord.Member = await MemberConverter().convert(ctx, str(ctx.author))
example_embed: discord.Embed = create_greet_embed(greet_member, text)
await ctx.send(embed=example_embed, content=ctx.author.mention)
def create_greet_embed(
member: discord.Member,
template: Optional[str] = None,
) -> discord.Embed:
embed: discord.Embed = discord.Embed(
color=discord.Color.embed_background(),
description=CONST.STRINGS["greet_default_description"].format(
member.guild.name,
),
)
if template and embed.description is not None:
embed.description += CONST.STRINGS["greet_template_description"].format(
formatter.template(template, member.name),
)
embed.set_thumbnail(url=member.display_avatar.url)
return embed

View file

@ -7,9 +7,9 @@ from discord.ext import commands
from loguru import logger
from lib import interaction
from lib.embeds.error import EconErrors
from services.currency_service import Currency
from services.stats_service import BlackJackStats
from lib.exceptions.LumiExceptions import LumiException
from lib.constants import CONST
est = pytz.timezone("US/Eastern")
@ -25,13 +25,11 @@ async def cmd(ctx, bet: int):
3 = dealer busted
4 = dealer won
5 = player won with 21 (blackjack)
6 = timed out
"""
# check if the player already has an active blackjack going
if ctx.author.id in active_blackjack_games:
await ctx.respond(embed=EconErrors.already_playing(ctx))
return
raise LumiException(CONST.STRINGS["error_already_playing_blackjack"])
# Currency handler
ctx_currency = Currency(ctx.author.id)
@ -99,8 +97,10 @@ async def cmd(ctx, bet: int):
status = 3 if dealer_hand_value > 21 else 4
break
else:
status = 6
break
# timed out
ctx_currency.take_balance(bet)
ctx_currency.push()
raise LumiException(CONST.STRINGS["error_out_of_time_economy"])
# refresh
view = interaction.BlackJackButtons(ctx)
@ -118,7 +118,8 @@ async def cmd(ctx, bet: int):
"""
At this point the game has concluded, generate a final output & backend
"""
payout = bet * 2 if status == 5 else bet * multiplier
payout = bet * multiplier if status != 5 else bet * 2
is_won = status not in [1, 4]
embed = blackjack_finished(
@ -150,15 +151,6 @@ async def cmd(ctx, bet: int):
hand_player=player_hand,
hand_dealer=dealer_hand,
)
stats.push()
elif status == 6:
await ctx.send(
embed=EconErrors.out_of_time(ctx),
content=ctx.author.mention,
)
ctx_currency.take_balance(bet)
ctx_currency.push()
else:
ctx_currency.add_balance(payout)
@ -173,7 +165,8 @@ async def cmd(ctx, bet: int):
hand_player=player_hand,
hand_dealer=dealer_hand,
)
stats.push()
stats.push()
except Exception as e:
# await ctx.respond(embed=GenericErrors.default_exception(ctx))

View file

@ -1,9 +1,11 @@
from typing import Optional
from discord.ext import bridge
from lib.embeds.triggers import create_creation_embed, create_failure_embed
from services.reactions_service import CustomReactionsService
from lib.exceptions.LumiExceptions import LumiException
from lib.constants import CONST
from lib.embed_builder import EmbedBuilder
from lib import formatter
async def add_reaction(
@ -22,20 +24,15 @@ async def add_reaction(
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
@ -47,51 +44,63 @@ async def add_reaction(
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
is_global=False,
)
if success:
embed = create_creation_embed(
trigger_text,
response,
if not success:
raise LumiException(CONST.STRINGS["triggers_not_added"])
trigger_text = formatter.shorten(trigger_text, 50)
if response:
response = formatter.shorten(response, 50)
embed = EmbedBuilder.create_success_embed(
ctx,
author_text=CONST.STRINGS["triggers_add_author"],
description="",
footer_text=CONST.STRINGS["triggers_reaction_service_footer"],
show_name=False,
)
embed.description += CONST.STRINGS["triggers_add_description"].format(
trigger_text,
CONST.STRINGS["triggers_type_emoji"]
if is_emoji
else CONST.STRINGS["triggers_type_text"],
is_full_match,
)
if is_emoji:
embed.description += CONST.STRINGS["triggers_add_emoji_details"].format(
emoji_id,
is_emoji,
is_full_match,
)
else:
embed = create_failure_embed(trigger_text, is_emoji)
embed.description += CONST.STRINGS["triggers_add_text_details"].format(response)
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
limit_reached = await reaction_service.count_custom_reactions(guild_id) >= 100
if limit_reached:
raise LumiException(CONST.STRINGS["trigger_limit_reached"])
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
raise LumiException(CONST.STRINGS["trigger_already_exists"])
return True

View file

@ -1,11 +1,8 @@
from discord.ext import bridge
from lib.embeds.triggers import (
create_deletion_embed,
create_failure_embed,
create_not_found_embed,
)
from services.reactions_service import CustomReactionsService
from lib.embed_builder import EmbedBuilder
from lib.constants import CONST
from lib.exceptions.LumiExceptions import LumiException
async def delete_reaction(ctx: bridge.Context, reaction_id: int) -> None:
@ -14,23 +11,18 @@ async def delete_reaction(ctx: bridge.Context, reaction_id: int) -> None:
reaction_service = CustomReactionsService()
guild_id: int = ctx.guild.id
# Check if the reaction exists and belongs to the guild
reaction = await reaction_service.find_id(reaction_id)
if reaction is None or reaction["guild_id"] != guild_id or reaction["is_global"]:
embed = create_not_found_embed(reaction_id)
await ctx.respond(embed=embed)
return
raise LumiException(CONST.STRINGS["triggers_not_found"])
trigger_text = reaction["trigger_text"]
is_emoji = reaction["is_emoji"]
await reaction_service.delete_custom_reaction(reaction_id)
# Attempt to delete the reaction
success: bool = await reaction_service.delete_custom_reaction(reaction_id)
embed = EmbedBuilder.create_success_embed(
ctx,
author_text=CONST.STRINGS["triggers_delete_author"],
description=CONST.STRINGS["triggers_delete_description"],
footer_text=CONST.STRINGS["triggers_reaction_service_footer"],
)
if success:
embed = create_deletion_embed(trigger_text, is_emoji)
await ctx.respond(embed=embed)
else:
embed = create_failure_embed(trigger_text, is_emoji)
await ctx.respond(embed=embed)
await ctx.respond(embed=embed)

View file

@ -1,39 +1,79 @@
import datetime
import discord
from discord.ext import bridge, pages
from lib.constants import CONST
from lib.embeds.triggers import create_no_triggers_embed
from lib.embed_builder import EmbedBuilder
from services.reactions_service import CustomReactionsService
from typing import Any, Dict, List
from lib import formatter
import discord
async def list_reactions(ctx: bridge.Context) -> None:
if ctx.guild is None:
return
reaction_service = CustomReactionsService()
reaction_service: CustomReactionsService = CustomReactionsService()
guild_id: int = ctx.guild.id
# Fetch all reactions for the guild
reactions = await reaction_service.find_all_by_guild(guild_id)
reactions: List[Dict[str, Any]] = await reaction_service.find_all_by_guild(guild_id)
if not reactions:
embed = create_no_triggers_embed()
embed: discord.Embed = EmbedBuilder.create_warning_embed(
ctx,
author_text=CONST.STRINGS["triggers_no_reactions_title"],
description=CONST.STRINGS["triggers_no_reactions_description"],
footer_text=CONST.STRINGS["triggers_reaction_service_footer"],
show_name=False,
)
await ctx.respond(embed=embed)
return
# Create pages for pagination
pages_list = []
for reaction in reactions:
description = f"""**Trigger Text:** `{reaction['trigger_text']}`\n**Reaction Type:** {'Emoji' if reaction['is_emoji'] else 'Text'}\n{f"**Emoji ID:** `{str(reaction['emoji_id'])}`" if reaction['is_emoji'] else f"**Response:** `{reaction['response']}`"}\n**Full Match:** `{'True' if reaction['is_full_match'] else 'False'}`\n**Usage Count:** `{reaction['usage_count']}`"""
embed = discord.Embed(
title=f"ID: {reaction['id']}",
description=description,
color=0xFF8C00,
embed = EmbedBuilder.create_success_embed(
ctx,
title=CONST.STRINGS["triggers_list_custom_reaction_id"].format(
reaction["id"],
),
author_text=CONST.STRINGS["triggers_list_custom_reactions_title"],
footer_text=CONST.STRINGS["triggers_reaction_service_footer"],
show_name=False,
)
embed.set_author(name="Custom Reactions", icon_url=CONST.CHECK_ICON)
embed.set_footer(text="Reaction Service", icon_url=CONST.LUMI_LOGO_TRANSPARENT)
embed.timestamp = datetime.datetime.now(datetime.timezone.utc)
description_lines = [
CONST.STRINGS["triggers_list_trigger_text"].format(
formatter.shorten(reaction["trigger_text"], 50),
),
CONST.STRINGS["triggers_list_reaction_type"].format(
CONST.STRINGS["triggers_type_emoji"]
if reaction["is_emoji"]
else CONST.STRINGS["triggers_type_text"],
),
]
if reaction["is_emoji"]:
description_lines.append(
CONST.STRINGS["triggers_list_emoji_id"].format(reaction["emoji_id"]),
)
else:
description_lines.append(
CONST.STRINGS["triggers_list_response"].format(
formatter.shorten(reaction["response"], 50),
),
)
description_lines.extend(
[
CONST.STRINGS["triggers_list_full_match"].format(
"True" if reaction["is_full_match"] else "False",
),
CONST.STRINGS["triggers_list_usage_count"].format(
reaction["usage_count"],
),
],
)
embed.description = "\n".join(description_lines)
pages_list.append(embed)
paginator = pages.Paginator(pages=pages_list, timeout=180.0)
paginator: pages.Paginator = pages.Paginator(pages=pages_list, timeout=180.0)
await paginator.respond(ctx, ephemeral=False)