Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rubbergod.py refactor #992

Merged
merged 2 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions cogs/system/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import logging

import disnake
from disnake.ext import commands

Expand All @@ -7,6 +9,8 @@
from . import features
from .messages_cz import MessagesCZ

rubbergod_logger = logging.getLogger("rubbergod")


class View(BaseView):
def __init__(self, bot: commands.Bot, cogs: list[list[tuple[str, str]]]):
Expand Down Expand Up @@ -107,26 +111,26 @@ async def callback(self, inter: disnake.MessageInteraction) -> None:
if cog in self.unloaded_cogs():
try:
self.bot.load_extension(f"cogs.{cog}")
print(MessagesCZ.success_load(cog=cog))
rubbergod_logger.info(MessagesCZ.success_load(cog=cog))
except Exception as e:
await inter.send(f"Loading error\n`{e}`")
else:
try:
self.bot.unload_extension(f"cogs.{cog}")
print(MessagesCZ.success_unload(cog=cog))
rubbergod_logger.info(MessagesCZ.success_unload(cog=cog))
except Exception as e:
await inter.send(f"Unloading error\n`{e}`")
else:
cogs = set()
for cog in self.values:
try:
self.bot.reload_extension(f"cogs.{cog}")
print(MessagesCZ.success_reload(cog=cog))
rubbergod_logger.info(MessagesCZ.success_reload(cog=cog))
cogs.add(cog)
except Exception as e:
await inter.send(f"Reloading error\n`{e}`")
if cogs:
await inter.send(MessagesCZ.success_reload(cogs=", ".join(cogs)))
await inter.send(MessagesCZ.success_reload(cog=", ".join(cogs)))

self.options = self.create_select()
await self.message.edit(embed=features.create_embed(self.bot), view=self._view)
4 changes: 3 additions & 1 deletion cogs/warden/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

# stolen from rubbergoddess
import asyncio
import logging
import time

import dhash
Expand All @@ -19,6 +20,7 @@
from .messages_cz import MessagesCZ

dhash.force_pil()
rubbegod_logger = logging.getLogger("rubbergod")


class Warden(Base, commands.Cog):
Expand Down Expand Up @@ -84,7 +86,7 @@ async def handle_reaction(self, ctx):
await orig.remove_reaction("🤷🏻", self.bot.user)
await orig.remove_reaction("🤔", self.bot.user)
except Exception as e:
print("Warden:on_raw_reaction_add", "Could not remove bot's emote", e)
rubbegod_logger.warning("Warden:handle_reaction", "Could not remove bot's emote", e)
try:
await message.delete()
except disnake.errors.NotFound:
Expand Down
11 changes: 7 additions & 4 deletions database/db_migrations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import re

from config.app_config import config
Expand All @@ -21,6 +22,8 @@
from database.verification import PermitDB, ValidPersonDB
from database.vote import VoteDB # noqa: F401

rubbergod_logger = logging.getLogger("rubbergod")


def init_db(commit: bool = True):
# database.base.metadata.drop_all(database.db)
Expand All @@ -40,11 +43,11 @@ def load_dump(filename: str):
session.query(HugsTableDB).delete()
session.commit()

print(f"Loading dump from {filename}")
rubbergod_logger.info(f"Loading dump from {filename}")

data = database.base.metadata.tables.keys()
for row in data:
print(row)
rubbergod_logger.info(row)

with open(filename, "r", encoding="utf-8") as backup_file:
data = backup_file.readlines()
Expand Down Expand Up @@ -113,6 +116,6 @@ def load_subjects():
subjects = list(set(config.subjects))

for subject in subjects:
print(f"Importing subject {subject}")
rubbergod_logger.info(f"Importing subject {subject}")
SubjectDB.add(subject)
print("Import complete")
rubbergod_logger.info("Import complete")
5 changes: 4 additions & 1 deletion features/error.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import datetime
import logging
import sys
import traceback
from functools import cached_property
Expand All @@ -22,6 +23,8 @@
from database.stats import ErrorEvent
from permissions import custom_errors, permission_check

rubbegod_logger = logging.getLogger("rubbergod")


class ContextMock:
"""Create event context similar to commands.Context
Expand Down Expand Up @@ -98,7 +101,7 @@ def set_image(self, embed: disnake.Embed, user: disnake.User, count: int):
embed.set_image(file=file)
except Exception as error:
output = "".join(traceback.format_exception(type(error), error, error.__traceback__))
print(output)
rubbegod_logger.warning(output)

def log_error_time(self, set=True) -> int:
"""Log details of last exception and return number of days since last exception"""
Expand Down
50 changes: 50 additions & 0 deletions features/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import logging


class CustomFormatter(logging.Formatter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.GREY = "\x1b[38;2;192;192;192m"
self.BLUE = "\x1b[38;2;50;175;255m"
self.ORANGE = "\x1b[38;2;255;140;0m"
self.RED = "\x1b[38;2;255;0;0m"
self.BG_RED = "\x1b[41;37;97m"
self.RESET = "\x1b[0m"

self._colors = {
logging.DEBUG: self.GREY,
logging.INFO: self.BLUE,
logging.WARNING: self.ORANGE,
logging.ERROR: self.RED,
logging.CRITICAL: self.BG_RED,
}

def format(self, record):
record.msg = self._colors[record.levelno] + record.msg + self.RESET
return logging.Formatter.format(self, record)


def setup_logging():
"""Set up logging for disnake and rubbergod loggers."""
output_fmt = "[{asctime}] [{levelname:<8}] {name}: {message}"
dt_fmt = "%Y-%m-%d %H:%M:%S"
style = "{"

disnake_logger = logging.getLogger("disnake")
disnake_logger.setLevel(logging.INFO)

rubbergod_logger = logging.getLogger("rubbergod")
rubbergod_logger.setLevel(logging.INFO)

# These two handlers need to be in this exact order or the log file will contain escape sequences
file_handler = logging.FileHandler(filename="rubbergod.log", encoding="utf-8", mode="w")
file_formatter = logging.Formatter(output_fmt, dt_fmt, style)
file_handler.setFormatter(file_formatter)
disnake_logger.addHandler(file_handler)
rubbergod_logger.addHandler(file_handler)

cli_handler = logging.StreamHandler()
cli_formatter = CustomFormatter(output_fmt, dt_fmt, style)
cli_handler.setFormatter(cli_formatter)
disnake_logger.addHandler(cli_handler)
rubbergod_logger.addHandler(cli_handler)
144 changes: 70 additions & 74 deletions rubbergod.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@
from config.app_config import config
from config.messages import Messages
from features.error import ErrorLogger
from features.logger import setup_logging
from features.presence import Presence

logger = logging.getLogger("disnake")
logger.setLevel(logging.WARNING)
handler = logging.FileHandler(filename="discord.log", encoding="utf-8", mode="w")
handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s"))
logger.addHandler(handler)
setup_logging()
rubbergod_logger = logging.getLogger("rubbergod")

parser = argparse.ArgumentParser()
parser.add_argument(
Expand All @@ -35,7 +33,7 @@
exit(0)
elif args.init_db:
migrations.init_db()
print("Init complete")
rubbergod_logger.info("Init complete")
exit(0)

is_initialized = False
Expand All @@ -51,72 +49,70 @@
intents.moderation = True
intents.automod_execution = True

command_sync_flags = commands.CommandSyncFlags()
command_sync_flags.sync_commands_debug = False

bot = commands.Bot(
command_prefix=commands.when_mentioned_or(*config.command_prefix),
help_command=None,
case_insensitive=True,
allowed_mentions=AllowedMentions(roles=False, everyone=False, users=True),
intents=intents,
command_sync_flags=command_sync_flags,
)

presence = Presence(bot)
err_logger = ErrorLogger(bot)


@bot.event
async def on_ready() -> None:
"""If RubberGod is ready"""
# Inspired from https://github.com/sinus-x/rubbergoddess/blob/master/rubbergoddess.py
global is_initialized
if is_initialized:
return
is_initialized = True

views = [
ReportGeneralView(bot),
ReportMessageView(bot),
ReportAnonymView(bot),
ReportAnswerOnlyView(bot),
ContestVoteView(bot),
]
for view in views:
bot.add_view(view)

bot_room: TextChannel = bot.get_channel(config.bot_room)
if bot_room is not None:
await bot_room.send(Messages.on_ready_message)

await bot.application_info()
await presence.set_presence()
print("Ready")


@bot.event
async def on_button_click(inter: disnake.MessageInteraction):
if inter.component.custom_id in [Messages.trash_delete_id, "bookmark:delete"]:
try:
await inter.message.delete()
except disnake.NotFound:
pass


@bot.event
async def on_error(event, *args, **kwargs):
return await err_logger.handle_event_error(event, args)


# Create missing tables at start
migrations.init_db()

bot.load_extension("cogs.system")
print("System cog loaded")

for extension in config.extensions:
bot.load_extension(f"cogs.{extension}")
print(f"{extension} loaded")

bot.run(config.key)
class Rubbergod(commands.Bot):
def __init__(self):
super().__init__(
command_prefix=commands.when_mentioned_or(*config.command_prefix),
help_command=None,
case_insensitive=True,
allowed_mentions=AllowedMentions(roles=False, everyone=False, users=True),
intents=intents,
command_sync_flags=commands.CommandSyncFlags(sync_commands_debug=False),
)
# Create missing tables at start
migrations.init_db()

# Features
self.presence = Presence(self)
self.err_logger = ErrorLogger(self)

self.init_cogs()

async def on_ready(self) -> None:
"""If RubberGod is ready"""
# Inspired from https://github.com/sinus-x/rubbergoddess/blob/master/rubbergoddess.py
global is_initialized
if is_initialized:
return
is_initialized = True

self.init_views()
bot_room: TextChannel = self.get_channel(config.bot_room)
if bot_room is not None:
await bot_room.send(Messages.on_ready_message)

await self.application_info()
await self.presence.set_presence()
rubbergod_logger.info("Ready")

async def on_button_click(self, inter: disnake.MessageInteraction):
if inter.component.custom_id in [Messages.trash_delete_id, "bookmark:delete"]:
try:
await inter.message.delete()
except disnake.NotFound:
pass

async def on_error(self, event, *args, **kwargs):
return await self.err_logger.handle_event_error(event, args)

def init_cogs(self) -> None:
self.load_extension("cogs.system")
rubbergod_logger.info("SYSTEM loaded")

for extension in config.extensions:
self.load_extension(f"cogs.{extension}")
rubbergod_logger.info(f"{extension.upper()} loaded")

def init_views(self) -> None:
"""Instantiate views for persistent interactions with bot"""
self.add_view(ReportAnonymView(self))
self.add_view(ReportAnswerOnlyView(self))
self.add_view(ReportGeneralView(self))
self.add_view(ReportMessageView(self))
self.add_view(ContestVoteView(self))
solumath marked this conversation as resolved.
Show resolved Hide resolved


rubbergod = Rubbergod()

rubbergod.run(config.key)