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

Refactor trigger column name in custom_reactions table

This commit is contained in:
wlinator 2024-07-10 22:11:12 +02:00
parent b8f707e8f8
commit e9a7603a19
3 changed files with 65 additions and 92 deletions

View file

@ -1,7 +1,7 @@
-- Create a table to store custom reactions
CREATE TABLE custom_reactions (
id SERIAL PRIMARY KEY, -- Unique identifier for each custom reaction
trigger TEXT NOT NULL, -- The text that triggers the custom reaction
trigger_text TEXT NOT NULL, -- The text that triggers the custom reaction
response TEXT, -- The response text for the custom reaction (nullable for emoji reactions)
emoji TEXT, -- The emoji for the custom reaction (nullable for text responses)
is_emoji BOOLEAN DEFAULT FALSE, -- Indicates if the reaction is a discord emoji reaction
@ -12,10 +12,10 @@ CREATE TABLE custom_reactions (
usage_count INT DEFAULT 0, -- The number of times a custom reaction has been used
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Timestamp when the custom reaction was created
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Timestamp when the custom reaction was last updated
CONSTRAINT unique_trigger_guild UNIQUE (trigger, guild_id) -- Ensure that the combination of trigger, guild_id, and is_full_match is unique
CONSTRAINT unique_trigger_guild UNIQUE (trigger_text, guild_id) -- Ensure that the combination of trigger_text, guild_id, and is_full_match is unique
);
-- Create indexes to speed up lookups
CREATE INDEX idx_custom_reactions_guild_id ON custom_reactions(guild_id);
CREATE INDEX idx_custom_reactions_creator_id ON custom_reactions(creator_id);
CREATE INDEX idx_custom_reactions_trigger ON custom_reactions(trigger);
CREATE INDEX idx_custom_reactions_trigger_text ON custom_reactions(trigger_text);

View file

@ -1,11 +1,8 @@
import random
import asyncio
from typing import List, Dict, Any
from discord.ext.commands import Cog
from discord import Message
from discord.ext.commands import Cog
from loguru import logger
from config.parser import JsonCache
from services.reactions_service import CustomReactionsService
from services.blacklist_service import BlacklistUserService
@ -13,68 +10,53 @@ class ReactionHandler:
"""
Handles reactions to messages based on predefined triggers and responses.
"""
def __init__(self, client, message: Message) -> None:
self.reactions: Dict[str, Any] = JsonCache.read_json("reactions")
self.eightball: List[str] = self.reactions["eightball"]
self.full_response: Dict[str, str] = self.reactions["full_content_responses"]
self.partial_react: Dict[str, str] = self.reactions["partial_content_reactions"]
self.client = client
self.message: Message = message
self.content: str = self.message.content.lower()
self.client = client
self.reaction_service = CustomReactionsService()
async def run_all_checks(self) -> None:
"""
Runs all checks for reactions and responses.
"""
await asyncio.gather(
self.check_eightball(self.eightball),
self.check_full_response(),
self.react()
)
async def check_eightball(self, choices: List[str]) -> None:
"""
Checks if the message is a question directed at Lumi and responds with a random choice.
:param choices: List of possible responses.
"""
if (self.content.startswith("lumi ") or self.content.startswith("lumi, ")) and self.content.endswith("?"):
response: str = random.choice(choices)
await self.message.reply(content=response)
async def check_full_response(self) -> None:
"""
Checks if the message content matches any full content triggers and responds accordingly.
"""
for trigger, response in self.full_response.items():
if trigger.lower() == self.content:
await self.message.reply(response)
guild_id = self.message.guild.id if self.message.guild else None
async def react(self) -> None:
"""
Adds reactions to the message based on partial content triggers.
"""
ctx = await self.client.get_context(self.message)
for trigger, emoji in self.partial_react.items():
if trigger.lower() in self.content:
emoji = await self.client.convert_to_emoji(ctx, emoji)
if emoji:
await self.message.add_reaction(emoji)
if guild_id:
reaction = await self.reaction_service.find_trigger(guild_id, self.content)
if reaction:
processed = False
try:
if reaction["type"] == "text":
await self.message.reply(reaction["response"])
processed = True
elif reaction["type"] == "emoji":
await self.message.add_reaction(reaction["response"])
processed = True
except Exception as e:
logger.warning(f"Failed to process reaction: {e}")
if processed:
await self.reaction_service.increment_reaction_usage(
int(reaction["id"])
)
class ReactionListener(Cog):
def __init__(self, client) -> None:
self.client = client
@Cog.listener('on_message')
@Cog.listener("on_message")
async def reaction_listener(self, message: Message) -> None:
"""
Listens for new messages and processes them if the author is not a bot and not blacklisted.
:param message: The message to process.
"""
if not message.author.bot and not BlacklistUserService.is_user_blacklisted(message.author.id):
if not message.author.bot and not BlacklistUserService.is_user_blacklisted(
message.author.id
):
await ReactionHandler(self.client, message).run_all_checks()

View file

@ -1,20 +1,3 @@
"""
TABLE custom_reactions:
id SERIAL PRIMARY KEY
trigger TEXT NOT NULL
response TEXT
emoji TEXT
is_emoji BOOLEAN DEFAULT FALSE
is_full_match BOOLEAN DEFAULT FALSE
is_global BOOLEAN DEFAULT TRUE
guild_id BIGINT
creator_id BIGINT NOT NULL
usage_count INT DEFAULT 0
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
CONSTRAINT unique_trigger_guild UNIQUE (trigger, guild_id)
"""
from typing import Optional, Dict, Any
from datetime import datetime
from db import database
@ -31,18 +14,29 @@ class CustomReactionsService:
query = """
SELECT * FROM custom_reactions
WHERE (guild_id = ? OR is_global = TRUE) AND (
(is_full_match = TRUE AND trigger = ?) OR
(is_full_match = FALSE AND ? LIKE CONCAT('%', trigger, '%'))
(is_full_match = TRUE AND trigger_text = ?) OR
(is_full_match = FALSE AND ? LIKE CONCAT('%', trigger_text, '%'))
)
ORDER BY guild_id = ? DESC, is_global ASC
LIMIT 1
"""
result = database.select_query_one(query, (guild_id, message_content, message_content, guild_id))
result = database.select_query(query, (guild_id, message_content, message_content, guild_id))
if result:
reaction = dict(result)
reaction = result[0] # Get the first result from the list
return {
"response": reaction.get("response"),
"type": "emoji" if reaction.get("is_emoji") else "text"
"id": reaction[0],
"trigger_text": reaction[1],
"response": reaction[2],
"emoji": reaction[3],
"is_emoji": reaction[4],
"is_full_match": reaction[5],
"is_global": reaction[6],
"guild_id": reaction[7],
"creator_id": reaction[8],
"usage_count": reaction[9],
"created_at": reaction[10],
"updated_at": reaction[11],
"type": "emoji" if reaction[4] else "text"
}
return None
@ -50,7 +44,7 @@ class CustomReactionsService:
self,
guild_id: int,
creator_id: int,
trigger: str,
trigger_text: str,
response: Optional[str] = None,
emoji: Optional[str] = None,
is_emoji: bool = False,
@ -61,14 +55,14 @@ class CustomReactionsService:
return False
query = """
INSERT INTO custom_reactions (trigger, response, emoji, is_emoji, is_full_match, is_global, guild_id, creator_id)
INSERT INTO custom_reactions (trigger_text, response, emoji, is_emoji, is_full_match, is_global, guild_id, creator_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE trigger=trigger
ON DUPLICATE KEY UPDATE trigger_text=trigger_text
"""
database.execute_query(
query,
(
trigger,
trigger_text,
response,
emoji,
is_emoji,
@ -83,7 +77,7 @@ class CustomReactionsService:
async def edit_custom_reaction(
self,
guild_id: int,
trigger: str,
trigger_text: str,
new_response: Optional[str] = None,
new_emoji: Optional[str] = None,
is_emoji: Optional[bool] = None,
@ -98,7 +92,7 @@ class CustomReactionsService:
is_full_match = COALESCE(?, is_full_match),
is_global = COALESCE(?, is_global),
updated_at = ?
WHERE guild_id = ? AND trigger = ?
WHERE guild_id = ? AND trigger_text = ?
"""
database.execute_query(
query,
@ -110,17 +104,17 @@ class CustomReactionsService:
is_global,
datetime.utcnow(),
guild_id,
trigger,
trigger_text,
),
)
return True
async def delete_custom_reaction(self, guild_id: int, trigger: str) -> bool:
async def delete_custom_reaction(self, guild_id: int, trigger_text: str) -> bool:
query = """
DELETE FROM custom_reactions
WHERE guild_id = ? AND trigger = ?
WHERE guild_id = ? AND trigger_text = ?
"""
database.execute_query(query, (guild_id, trigger))
database.execute_query(query, (guild_id, trigger_text))
return True
async def count_custom_reactions(self, guild_id: int) -> int:
@ -131,19 +125,16 @@ class CustomReactionsService:
count = database.select_query_one(query, (guild_id,))
return count if count else 0
async def increment_reaction_usage(self, guild_id: int, trigger: str) -> bool:
async def increment_reaction_usage(self, reaction_id: int) -> bool:
query = """
UPDATE custom_reactions
SET usage_count = usage_count + 1,
updated_at = ?
WHERE guild_id = ? AND trigger = ?
SET usage_count = usage_count + 1
WHERE id = ?
"""
database.execute_query(
query,
(
datetime.utcnow(),
guild_id,
trigger,
reaction_id,
),
)
return True