mirror of
https://github.com/wlinator/luminara.git
synced 2024-10-02 20:23:12 +00:00
Rework client handlers
This commit is contained in:
parent
5229df0af2
commit
b15fc98259
6 changed files with 185 additions and 136 deletions
|
@ -1,21 +0,0 @@
|
|||
import random
|
||||
|
||||
from config.parser import JsonCache
|
||||
|
||||
|
||||
class ReactionHandler:
|
||||
def __init__(self):
|
||||
self.reactions = JsonCache.read_json("reactions")
|
||||
self.eightball = self.reactions["eightball"]
|
||||
self.full_content_reactions = self.reactions["full_content_reactions"]
|
||||
|
||||
async def handle_message(self, message):
|
||||
content = message.content.lower()
|
||||
|
||||
if (content.startswith("racu ") or content.startswith("racu, ")) and content.endswith("?"):
|
||||
response = random.choice(self.eightball)
|
||||
await message.reply(content=response)
|
||||
|
||||
for trigger, response in self.full_content_reactions.items():
|
||||
if trigger.lower() == content:
|
||||
await message.reply(response)
|
|
@ -4,11 +4,13 @@ import traceback
|
|||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord.ext.commands import Cog
|
||||
|
||||
from lib.embeds.error import GenericErrors, BdayErrors
|
||||
from lib.exceptions import RacuExceptions
|
||||
|
||||
logs = logging.getLogger('Racu.Core')
|
||||
_logs = logging.getLogger('Racu.Core')
|
||||
|
||||
|
||||
async def on_command_error(ctx, error):
|
||||
|
@ -56,10 +58,45 @@ async def on_command_error(ctx, error):
|
|||
await ctx.respond(embed=GenericErrors.default_exception(ctx))
|
||||
traceback.print_tb(error.__traceback__)
|
||||
|
||||
logs.error(f"[CommandHandler] on_command_error: {error}")
|
||||
|
||||
|
||||
async def on_error(event: str, *args, **kwargs) -> None:
|
||||
logs.error(f"[EventHandler] on_error INFO: errors.event.{event} | '*args': {args} | '**kwargs': {kwargs}")
|
||||
logs.error(f"[EventHandler] on_error EXCEPTION: {sys.exc_info()}")
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
class ErrorListener(Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@Cog.listener()
|
||||
async def on_command_error(self, ctx, error) -> None:
|
||||
await on_command_error(ctx, error)
|
||||
log_msg = '[CommandHandler] %s executed .%s | PREFIX' % (ctx.author.name, ctx.command.qualified_name)
|
||||
|
||||
if ctx.guild is not None:
|
||||
log_msg += f" | guild: {ctx.guild.name} "
|
||||
else:
|
||||
log_msg += f" | in DMs"
|
||||
|
||||
_logs.info(f"{log_msg} | FAILED: {error}")
|
||||
|
||||
@Cog.listener()
|
||||
async def on_application_command_error(self, ctx, error) -> None:
|
||||
await on_command_error(ctx, error)
|
||||
log_msg = '[CommandHandler] %s executed /%s | SLASH' % (ctx.author.name, ctx.command.qualified_name)
|
||||
|
||||
if ctx.guild is not None:
|
||||
log_msg += f" | guild: {ctx.guild.name} "
|
||||
else:
|
||||
log_msg += f" | in DMs"
|
||||
|
||||
_logs.info(f"{log_msg} | FAILED: {error}")
|
||||
|
||||
@Cog.listener()
|
||||
async def on_error(self, event: str, *args, **kwargs) -> None:
|
||||
await on_error(event, *args, **kwargs)
|
||||
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(ErrorListener(client))
|
49
handlers/event_handler.py
Normal file
49
handlers/event_handler.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
import logging
|
||||
|
||||
from discord.ext.commands import Cog
|
||||
|
||||
from lib.embeds.greet import Greet
|
||||
from services.GuildConfig import GuildConfig
|
||||
|
||||
_logs = logging.getLogger('Racu.Core')
|
||||
|
||||
|
||||
class EventHandler(Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@Cog.listener()
|
||||
async def on_member_join(self, member):
|
||||
config = GuildConfig(member.guild.id)
|
||||
|
||||
if not config.welcome_channel_id:
|
||||
return
|
||||
|
||||
embed = Greet.message(member, config.welcome_message)
|
||||
|
||||
try:
|
||||
await member.guild.get_channel(config.welcome_channel_id).send(embed=embed, content=member.mention)
|
||||
except Exception as e:
|
||||
_logs.info(f"[GreetingHandler] Message not sent in '{member.guild.name}'. Channel ID may be invalid. {e}")
|
||||
|
||||
@Cog.listener()
|
||||
async def on_command_completion(self, ctx) -> None:
|
||||
log_msg = '[CommandHandler] %s executed .%s | PREFIX' % (ctx.author.name, ctx.command.qualified_name)
|
||||
|
||||
if ctx.guild is not None:
|
||||
_logs.info(f"{log_msg} | guild: {ctx.guild.name} ")
|
||||
else:
|
||||
_logs.info(f"{log_msg} | in DMs")
|
||||
|
||||
@Cog.listener()
|
||||
async def on_application_command_completion(self, ctx) -> None:
|
||||
log_msg = '[CommandHandler] %s executed /%s | SLASH' % (ctx.author.name, ctx.command.qualified_name)
|
||||
|
||||
if ctx.guild is not None:
|
||||
_logs.info(f"{log_msg} | guild: {ctx.guild.name} ")
|
||||
else:
|
||||
_logs.info(f"{log_msg} | in DMs")
|
||||
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(EventHandler(client))
|
37
handlers/reaction_handler.py
Normal file
37
handlers/reaction_handler.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
import random
|
||||
|
||||
from config.parser import JsonCache
|
||||
from discord.ext.commands import Cog
|
||||
|
||||
_reactions = JsonCache.read_json("reactions")
|
||||
_8ball = _reactions["eightball"]
|
||||
_full = _reactions["full_content_reactions"]
|
||||
|
||||
|
||||
class ReactionHandler:
|
||||
|
||||
@staticmethod
|
||||
async def respond(message):
|
||||
content = message.content.lower()
|
||||
|
||||
if (content.startswith("racu ") or content.startswith("racu, ")) and content.endswith("?"):
|
||||
response = random.choice(_8ball)
|
||||
await message.reply(content=response)
|
||||
|
||||
for trigger, response in _full.items():
|
||||
if trigger.lower() == content:
|
||||
await message.reply(response)
|
||||
|
||||
|
||||
class ReactionListener(Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@Cog.listener('on_message')
|
||||
async def reaction_listener(self, message):
|
||||
if not message.author.bot:
|
||||
await ReactionHandler.respond(message)
|
||||
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(ReactionListener(client))
|
|
@ -1,10 +1,12 @@
|
|||
import logging
|
||||
import random
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
import discord
|
||||
|
||||
from config.parser import JsonCache
|
||||
from discord.ext.commands import Cog
|
||||
from lib import formatter
|
||||
from services.GuildConfig import GuildConfig
|
||||
from services.xp_service import XpService, XpRewardService
|
||||
|
@ -139,3 +141,30 @@ class XPHandler:
|
|||
random_message = random.choice(message_list)
|
||||
start_string = _strings["level_up_prefix"].format(author.name)
|
||||
return start_string + random_message.format(level)
|
||||
|
||||
|
||||
class XpListener(Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@Cog.listener('on_message')
|
||||
async def xp_listener(self, message):
|
||||
if (
|
||||
message.author.bot or
|
||||
message.guild is None
|
||||
):
|
||||
return
|
||||
|
||||
_xp = XPHandler(message)
|
||||
leveled_up = _xp.process()
|
||||
|
||||
if leveled_up:
|
||||
coros = [
|
||||
asyncio.create_task(_xp.notify()),
|
||||
asyncio.create_task(_xp.reward())
|
||||
]
|
||||
await asyncio.wait(coros)
|
||||
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(XpListener(client))
|
||||
|
|
140
main.py
140
main.py
|
@ -1,138 +1,56 @@
|
|||
import asyncio
|
||||
import os
|
||||
import traceback
|
||||
|
||||
import discord
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from handlers import LoggingHandler, ErrorHandler
|
||||
from handlers.ReactionHandler import ReactionHandler
|
||||
from handlers.xp_handler import XPHandler
|
||||
from lib.embeds.greet import Greet
|
||||
from services.Client import RacuBot
|
||||
from services.GuildConfig import GuildConfig
|
||||
from services.Help import RacuHelp
|
||||
import services.Client
|
||||
import services.GuildConfig
|
||||
import services.Help
|
||||
import services.logging_service
|
||||
|
||||
load_dotenv('.env')
|
||||
instance = os.getenv("INSTANCE")
|
||||
_logs = services.logging_service.setup_logger()
|
||||
|
||||
|
||||
def get_prefix(bot, message):
|
||||
async def get_prefix(bot, message):
|
||||
try:
|
||||
return GuildConfig.get_prefix(message.guild.id)
|
||||
return services.GuildConfig.GuildConfig.get_prefix(message.guild.id)
|
||||
except AttributeError:
|
||||
return "."
|
||||
|
||||
|
||||
client = RacuBot(
|
||||
client = services.Client.RacuBot(
|
||||
owner_id=int(os.getenv('OWNER_ID')),
|
||||
command_prefix=get_prefix,
|
||||
intents=discord.Intents.all(),
|
||||
status=discord.Status.online,
|
||||
help_command=RacuHelp()
|
||||
help_command=services.Help.RacuHelp()
|
||||
)
|
||||
|
||||
logs = LoggingHandler.setup_logger()
|
||||
|
||||
|
||||
@client.listen()
|
||||
async def on_message(message):
|
||||
if (
|
||||
message.author.bot or
|
||||
message.guild is None
|
||||
):
|
||||
return
|
||||
|
||||
try:
|
||||
_xp = XPHandler(message)
|
||||
leveled_up = _xp.process()
|
||||
|
||||
if leveled_up:
|
||||
coros = [
|
||||
asyncio.create_task(_xp.notify()),
|
||||
asyncio.create_task(_xp.reward())
|
||||
]
|
||||
await asyncio.wait(coros)
|
||||
|
||||
reaction_handler = ReactionHandler()
|
||||
await reaction_handler.handle_message(message)
|
||||
|
||||
except Exception as error:
|
||||
logs.error(f"[EventHandler] on_message (check debug log): {error}", exc_info=True)
|
||||
traceback.print_tb(error.__traceback__)
|
||||
|
||||
|
||||
@client.event
|
||||
async def on_member_join(member):
|
||||
config = GuildConfig(member.guild.id)
|
||||
|
||||
if not config.welcome_channel_id:
|
||||
return
|
||||
|
||||
embed = Greet.message(member, config.welcome_message)
|
||||
|
||||
try:
|
||||
await member.guild.get_channel(config.welcome_channel_id).send(embed=embed, content=member.mention)
|
||||
except Exception as e:
|
||||
logs.info(f"[GreetingHandler] Message not sent in '{member.guild.name}'. Channel ID may be invalid. {e}")
|
||||
|
||||
|
||||
@client.listen()
|
||||
async def on_command_completion(ctx) -> None:
|
||||
"""
|
||||
This code is executed when a slash_command has been successfully executed.
|
||||
This technically serves as a CommandHandler function
|
||||
:param ctx:
|
||||
:return:
|
||||
"""
|
||||
full_command_name = ctx.command.qualified_name
|
||||
split = full_command_name.split(" ")
|
||||
executed_command = str(split[0])
|
||||
|
||||
if ctx.guild is not None:
|
||||
# logs.info(
|
||||
# f"Executed {executed_command} command in {ctx.guild.name} (ID: {ctx.guild.id}) "
|
||||
# f"by {ctx.author} (ID: {ctx.author.id})"
|
||||
# )
|
||||
logs.info(f"[CommandHandler] {ctx.author.name} successfully did \"/{executed_command}\". "
|
||||
f"| guild: {ctx.guild.name} ")
|
||||
else:
|
||||
# logs.info(
|
||||
# f"Executed {executed_command} command by {ctx.author} (ID: {ctx.author.id}) in DMs."
|
||||
# )
|
||||
logs.info(f"[CommandHandler] {ctx.author.name} successfully did \"/{executed_command}\". | direct message")
|
||||
|
||||
|
||||
@client.listen()
|
||||
async def on_command_error(ctx, error) -> None:
|
||||
await ErrorHandler.on_command_error(ctx, error)
|
||||
|
||||
|
||||
@client.listen()
|
||||
async def on_application_command_error(ctx, error) -> None:
|
||||
await ErrorHandler.on_command_error(ctx, error)
|
||||
|
||||
|
||||
@client.event
|
||||
async def on_error(event: str, *args, **kwargs) -> None:
|
||||
await ErrorHandler.on_error(event, *args, **kwargs)
|
||||
|
||||
|
||||
def load_modules():
|
||||
module_list = [d for d in os.listdir("modules") if os.path.isdir(os.path.join("modules", d))]
|
||||
loaded_modules = set()
|
||||
loaded = set()
|
||||
|
||||
for module in module_list:
|
||||
if module in loaded_modules:
|
||||
continue # module is already loaded
|
||||
# Load event listeners (handlers) and command cogs (modules)
|
||||
for directory in ["handlers", "modules"]:
|
||||
directory_path = os.path.join(os.getcwd(), directory)
|
||||
if not os.path.isdir(directory_path):
|
||||
continue
|
||||
|
||||
items = [d for d in os.listdir(directory_path) if os.path.isdir(os.path.join(directory_path, d))] \
|
||||
if directory == "modules" else [f[:-3] for f in os.listdir(directory_path) if f.endswith('.py')]
|
||||
|
||||
for item in items:
|
||||
if item in loaded:
|
||||
continue
|
||||
|
||||
try:
|
||||
client.load_extension(f"modules.{module}")
|
||||
loaded_modules.add(module)
|
||||
logs.info(f"[MODULE] {module.upper()} loaded.")
|
||||
client.load_extension(f"{directory}.{item}")
|
||||
loaded.add(item)
|
||||
_logs.info(f'[{directory.upper()}] {item.upper()} loaded.')
|
||||
|
||||
except Exception as e:
|
||||
logs.error(f"[MODULE] Failed to load module {module.upper()}: {e}")
|
||||
_logs.error(f'[{directory.upper()}] Failed to load {item.upper()}: {e}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -141,12 +59,12 @@ if __name__ == '__main__':
|
|||
thus NOT when main is imported from a cog. (sys.modules)
|
||||
"""
|
||||
|
||||
logs.info("RACU IS BOOTING")
|
||||
logs.info("\n")
|
||||
_logs.info("RACU IS BOOTING")
|
||||
_logs.info("\n")
|
||||
|
||||
load_modules()
|
||||
|
||||
# empty line to separate modules from system info in logs
|
||||
logs.info("\n")
|
||||
_logs.info("\n")
|
||||
|
||||
client.run(os.getenv('TOKEN'))
|
||||
|
|
Loading…
Reference in a new issue