Skip to content
Open
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
1 change: 1 addition & 0 deletions discord/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ __pycache__
registered_log.txt
schedule.json
pretix_cache.json
.vscode/
7 changes: 3 additions & 4 deletions discord/PyLadiesBot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
import sys
from pathlib import Path

import discord
from discord.ext import commands
from dotenv import load_dotenv

import configuration
import discord
from cogs.ping import Ping
from cogs.pretix_donations import PretixDonations
from discord.ext import commands
from dotenv import load_dotenv
from program_notifications.cog import ProgramNotificationsCog
from registration.cog import RegistrationCog

Expand Down
4 changes: 3 additions & 1 deletion discord/PyLadiesBot/cogs/ping.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging

from discord.ext import commands
from helpers import DiscordLogger

_logger = logging.getLogger(f"bot.{__name__}")

Expand All @@ -9,8 +10,9 @@ class Ping(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot: commands.Bot = bot
_logger.info("Cog 'Ping' has been initialized")
self.discord_logger = DiscordLogger(__name__, self.bot)

@commands.hybrid_command(name="ping", description="Ping the bot")
async def ping_command(self, ctx: commands.Context) -> None:
_logger.debug("The 'ping' command has been triggered!")
await self.discord_logger.info("The 'ping' command has been triggered!")
await ctx.send("Pong!")
1 change: 1 addition & 0 deletions discord/PyLadiesBot/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ DONATIONS_CHANNEL_ID = 1314028552223457471

[logging]
LOG_LEVEL = "INFO"
channel_id = "TO SET"

[program_notifications]
# UTC offset in hours (e.g. 2 for CEST)
Expand Down
4 changes: 3 additions & 1 deletion discord/PyLadiesBot/configuration.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import logging
import sys
import tomllib
from datetime import datetime, timedelta, timezone
from pathlib import Path

import tomllib

_logger = logging.getLogger(f"bot.{__name__}")


Expand Down Expand Up @@ -76,6 +77,7 @@ def __init__(self):

# Logging
self.LOG_LEVEL = config.get("logging", {}).get("LOG_LEVEL", "INFO")
self.log_channel = config["logging"]["channel_id"]

except KeyError:
_logger.exception(
Expand Down
78 changes: 78 additions & 0 deletions discord/PyLadiesBot/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import logging
import textwrap

from configuration import Config
from discord import Message
from discord.abc import Messageable
from discord.ext.commands import Bot

config = Config()


async def safe_send_message(target: Messageable, text: str) -> list[Message]:
"""Safely send a message to the given messageable target.
The utility of this is function, is that the message will be split into multiple parts
if its too long.
"""
messages = []
for part in textwrap.wrap(
text,
width=2000,
expand_tabs=False,
replace_whitespace=False,
drop_whitespace=False,
):
message = await target.send(part)
messages.append(message)
return messages


class DiscordLogger:
"""Wrapper for the configured project logger, that also sends the same logs to discord.

Use any of the logging level methods, just like in the standard library on the
instantiated object.

Automatically prefixes `bot.` to the name provided for the logger.

Requires a bot object to be instantiated and passed into it.

For example:
```python
discord_logger = DiscordLogger(__name__, self.bot)
discord_logger.info("The 'ping' command has been triggered!")
discord_logger.error("A problem has occurred!")
```
"""

def __init__(self, name: str, bot: Bot):
self.name = f"bot.{name}"
self.bot = bot
self.logger = logging.getLogger(self.name)

def __getattr__(self, method_name: str):
logging_types = {
"debug",
"info",
"warning",
"warn",
"error",
"exception",
"critical",
"fatal",
}
if method_name not in logging_types:
raise AttributeError(f"Logging type must be one of {logging_types}")

def _log(message: str):

async def inner():
logging_method = getattr(self.logger, method_name)
logging_method(message)
channel = self.bot.get_channel(config.log_channel)
prefix = f"{self.name} - {method_name.upper()} - "
await safe_send_message(channel, f"{prefix}{message}")

return inner()

return _log
1 change: 1 addition & 0 deletions discord/PyLadiesBot/staging-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ PRETIX_CACHE_FILE = "pretix_cache.json"

[logging]
LOG_LEVEL = "INFO"
channel_id = "TO SET"

[program_notifications]
# UTC offset in hours (e.g. 2 for CEST)
Expand Down