Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22a3b14edd | |||
| 55ef585bdb | |||
| a9cf3af487 | |||
| 01e3138f29 | |||
| 46fc7d0d60 | |||
| a41a483041 | |||
| 917e90b48b | |||
| 467aebc3af | |||
| 818f4dfdae | |||
| 0db5d4d31c | |||
| 6967fa5358 | |||
| 70363033c1 | |||
| baf774f4b0 | |||
| 64215ffda5 | |||
| 13a9075376 | |||
| 05e72bf0dc | |||
| 654274f632 | |||
| 56d7a8155c | |||
| b82d6fa518 | |||
| c4cb477637 | |||
| 2f33d840f3 | |||
| f01b942818 | |||
| 8e1b4269d1 | |||
| e1455de14b | |||
| e6195d9a88 | |||
| 1221035369 | |||
| 796f43d629 | |||
| 0b031d20f9 | |||
| bfd497898e | |||
| 077f845b94 | |||
| 26e3a4bb8e | |||
| f56636c1ff | |||
| f427d06e61 | |||
| 42bd226a60 | |||
| 4dd578c9a8 | |||
| 01d90e6625 |
@@ -0,0 +1,15 @@
|
|||||||
|
name: Code Analysis (Bandit)
|
||||||
|
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
bandit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: mdegis/bandit-action@v1.0
|
||||||
|
with:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
path: "src/"
|
||||||
|
level: high
|
||||||
|
confidence: high
|
||||||
|
exit_zero: true
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
name: Release Multi-Arch Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push-docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Transform 'github.repository' to lowercase
|
||||||
|
id: lowercase_repo
|
||||||
|
shell: bash
|
||||||
|
run: echo "repository=${GITHUB_REPOSITORY,,}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Build and push multi-arch image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: |
|
||||||
|
ghcr.io/${{ steps.lowercase_repo.outputs.repository }}:${{ github.event.release.tag_name }}
|
||||||
|
ghcr.io/${{ steps.lowercase_repo.outputs.repository }}:latest
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
name: Linting (Ruff)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
ruff:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: astral-sh/ruff-action@v3
|
||||||
+1
-2
@@ -4,9 +4,8 @@ config/*.ini
|
|||||||
pastebin.txt
|
pastebin.txt
|
||||||
.DS_Store
|
.DS_Store
|
||||||
test*.py
|
test*.py
|
||||||
.dockerignore
|
|
||||||
docker-*
|
docker-*
|
||||||
.vscode
|
.vscode/settings.json
|
||||||
|
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
[DISCORD]
|
|
||||||
TOKEN = <PLACE YOUR DISCORD TOKEN FROM THE DEV PORTAL HERE>
|
|
||||||
OWNER_ID = <PLACE THE USER ID OF THE OWNER HERE>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
; Create an script on the reddit developer page (https://www.reddit.com/prefs/apps)
|
|
||||||
[REDDIT]
|
|
||||||
CLIENT_ID = <PASTE YOUR CLIENT ID HERE>
|
|
||||||
CLIENT_SECRET = <PASTE YOUR CLIENT SECRET HERE>
|
|
||||||
USER_AGENT = Small discord bot to embed posts (given by url) into an standardized format
|
|
||||||
EMBED_COLOR = 0xff4500
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
discord.py==2.4.0
|
|
||||||
colorama==0.4.6
|
|
||||||
python-dotenv==1.1.1
|
|
||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
from discord.ext import commands
|
|
||||||
import discord
|
|
||||||
from utils.datetime_tools import get_elapsed_time_small
|
|
||||||
from logging import Logger
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
class PostIt_Bot(commands.Bot):
|
|
||||||
"""Class to extend the built-in bot class"""
|
|
||||||
def __init__(self, startup_time:float, program_version:str, app_logger:Logger):
|
|
||||||
intents = discord.Intents.default()
|
|
||||||
intents.messages = True
|
|
||||||
super().__init__(command_prefix=None, help_command=None, intents=intents)
|
|
||||||
|
|
||||||
self.startup_time = startup_time
|
|
||||||
self.PROGRAM_VERSION = program_version
|
|
||||||
self.__logger = app_logger
|
|
||||||
|
|
||||||
async def setup_hook(self):
|
|
||||||
# Register cogs to handle commands
|
|
||||||
for cog_name in ["post", "reload"]:
|
|
||||||
await self.load_extension(f"cogs.{cog_name}")
|
|
||||||
await self.tree.sync()
|
|
||||||
|
|
||||||
async def on_ready(self):
|
|
||||||
self.__logger.info(f"Successfully logged in (after {get_elapsed_time_small(datetime.now().timestamp() - self.startup_time)}) as {self.user}")
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
"""Contains the BaseCog"""
|
|
||||||
|
|
||||||
from discord.ext import commands
|
|
||||||
import logging
|
|
||||||
|
|
||||||
class BaseCog(commands.Cog):
|
|
||||||
def __init__(self, bot:commands.Bot, logger:logging.Logger):
|
|
||||||
self._bot = bot
|
|
||||||
self._logger = logger
|
|
||||||
|
|
||||||
async def cog_load(self):
|
|
||||||
self._logger.debug(f"Cog for the '{self.__class__.__name__}' command got loaded")
|
|
||||||
|
|
||||||
async def cog_unload(self):
|
|
||||||
self._logger.debug(f"Cog for the '{self.__class__.__name__}' command got unloaded")
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
"""Contains the implementation for the /post command"""
|
|
||||||
|
|
||||||
from .base import BaseCog
|
|
||||||
import logging
|
|
||||||
from discord import app_commands, Interaction
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
class PostCommand(BaseCog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
logger = logging.getLogger("cmds.post")
|
|
||||||
super().__init__(bot, logger)
|
|
||||||
|
|
||||||
@app_commands.command(name = "post", description = "Post an embed in the Current Channel with a link to the content")
|
|
||||||
@app_commands.describe(url = "URL to the post", custom_note = "Describe the post with your own note", use_title = "Display the title of the post", quality = "Specifies the quality of the converted image, closer to 100 is better")
|
|
||||||
@app_commands.choices(quality = [
|
|
||||||
app_commands.Choice(name = "Poor (60)", value = 60),
|
|
||||||
app_commands.Choice(name = "Fair (70)", value = 70),
|
|
||||||
app_commands.Choice(name = "Good (80)", value = 80),
|
|
||||||
app_commands.Choice(name = "Very Good (85)", value = 85),
|
|
||||||
app_commands.Choice(name = "Excellent (90)", value = 90),
|
|
||||||
app_commands.Choice(name = "Superior (95)", value = 95),
|
|
||||||
app_commands.Choice(name = "Perfect (100)", value = 100)
|
|
||||||
])
|
|
||||||
async def post(self, ctx:Interaction, url:str, custom_note:str = None, use_title:bool = True, quality:app_commands.Choice[int] = 95):
|
|
||||||
print("Hallo")
|
|
||||||
|
|
||||||
async def setup(bot:commands.Bot):
|
|
||||||
await bot.add_cog(PostCommand(bot))
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
from .base import BaseCog
|
|
||||||
|
|
||||||
import logging
|
|
||||||
from datetime import datetime
|
|
||||||
from utils.datetime_tools import get_elapsed_time_milliseconds
|
|
||||||
|
|
||||||
class ReloadCommand(BaseCog):
|
|
||||||
def __init__(self, bot:commands.Bot):
|
|
||||||
self.__bot = bot
|
|
||||||
self.__cached_cog_names:list[str] = None
|
|
||||||
self.__reload_running = False
|
|
||||||
super().__init__(bot, logging.getLogger("cmds.reload"))
|
|
||||||
|
|
||||||
async def autocomplete_cog(self, ctx: discord.Interaction, cog_name_stw:str):
|
|
||||||
"""Helpermethod to recommend the right cog name to the user"""
|
|
||||||
# Cache the cog names if not cached yet
|
|
||||||
if not self.__cached_cog_names:
|
|
||||||
self.__cached_cog_names = list(self.__bot.extensions.keys())
|
|
||||||
|
|
||||||
if cog_name_stw == "":
|
|
||||||
# Return first 25 cog names, if provided name is empty
|
|
||||||
matching_cogs = sorted(self.__cached_cog_names)
|
|
||||||
else:
|
|
||||||
matching_cogs = []
|
|
||||||
for cog_name in self.__cached_cog_names:
|
|
||||||
if cog_name.startswith(cog_name_stw.lower()):
|
|
||||||
matching_cogs.append(cog_name)
|
|
||||||
|
|
||||||
choices = []
|
|
||||||
for matching_cog in matching_cogs[:25]:
|
|
||||||
choices.append(app_commands.Choice(name = matching_cog.removeprefix("cogs.").capitalize(), value = matching_cog))
|
|
||||||
|
|
||||||
return choices
|
|
||||||
|
|
||||||
@app_commands.command(name = "reload_all", description = "Reloads all cogs")
|
|
||||||
async def reload_all(self, ctx: discord.Interaction):
|
|
||||||
if self.__reload_running:
|
|
||||||
await ctx.response.send_message("Reload is allready being executed", ephemeral = True)
|
|
||||||
else:
|
|
||||||
self.__reload_running = True
|
|
||||||
task_start = datetime.now().timestamp()
|
|
||||||
cog_names = list(self.__bot.extensions.keys())
|
|
||||||
stepped_over = 0
|
|
||||||
self._logger.debug(f"Reloading all {len(cog_names)} cogs / extensions ...")
|
|
||||||
try:
|
|
||||||
embed_cog_stats = "Reloaded the following cogs:\n"
|
|
||||||
for extension_name in cog_names:
|
|
||||||
if "impls" in extension_name:
|
|
||||||
stepped_over += 1
|
|
||||||
else:
|
|
||||||
start_reload = datetime.now().timestamp()
|
|
||||||
await self.__bot.reload_extension(extension_name)
|
|
||||||
embed_cog_stats += f"- {extension_name.removeprefix('cogs.').capitalize()} (`{get_elapsed_time_milliseconds(datetime.now().timestamp() - start_reload)}`)\n"
|
|
||||||
|
|
||||||
except Exception as error:
|
|
||||||
embed_cog_stats += f"- {extension_name.removeprefix('cogs.').capitalize()} <--"
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
title = "Reloading All Cogs",
|
|
||||||
description = f"{embed_cog_stats} \n\nDuring the reload an exception occured",
|
|
||||||
color = 0xED4337)
|
|
||||||
|
|
||||||
raise error
|
|
||||||
else:
|
|
||||||
elapsed_time = get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)
|
|
||||||
embed = discord.Embed(
|
|
||||||
title = "Reloading All Cogs",
|
|
||||||
description = f"{embed_cog_stats}Total time spend: `{elapsed_time}`",
|
|
||||||
color = 0x4BB543)
|
|
||||||
|
|
||||||
self._logger.info(f"Cogs successfully reloaded after {elapsed_time} (Ignored )")
|
|
||||||
finally:
|
|
||||||
await ctx.response.send_message(embed = embed, ephemeral = True)
|
|
||||||
self.__reload_running = False
|
|
||||||
|
|
||||||
|
|
||||||
@app_commands.command(name = "reload", description = "Reload specific cog")
|
|
||||||
@app_commands.autocomplete(cog_name = autocomplete_cog)
|
|
||||||
async def reload(self, ctx: discord.Interaction, cog_name:str):
|
|
||||||
if self.__reload_running:
|
|
||||||
await ctx.response.send_message("Reload is allready being executed", ephemeral = True)
|
|
||||||
else:
|
|
||||||
self.__reload_running = True
|
|
||||||
task_start = datetime.now().timestamp()
|
|
||||||
self._logger.debug(f"Reloading {cog_name} cog ...")
|
|
||||||
try:
|
|
||||||
await self.__bot.reload_extension(cog_name)
|
|
||||||
except Exception as error:
|
|
||||||
embed = discord.Embed(
|
|
||||||
title = f"Reloading `{cog_name.removeprefix('cogs.').capitalize()}` cog",
|
|
||||||
description = "Reload failed with an exception",
|
|
||||||
color = 0xED4337)
|
|
||||||
|
|
||||||
raise error
|
|
||||||
else:
|
|
||||||
embed = discord.Embed(
|
|
||||||
title = f"Reloading `{cog_name.removeprefix('cogs.').capitalize()}` cog",
|
|
||||||
description = f"Total time spend: `{get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)}`",
|
|
||||||
color = 0x4BB543)
|
|
||||||
|
|
||||||
self._logger.info(f"Cog {cog_name} successfully reloaded after {get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)}")
|
|
||||||
finally:
|
|
||||||
await ctx.response.send_message(embed = embed, ephemeral = True)
|
|
||||||
self.__reload_running = False
|
|
||||||
|
|
||||||
# Clear the cache
|
|
||||||
self.__cached_cog_names = None
|
|
||||||
|
|
||||||
async def setup(bot:commands.Bot):
|
|
||||||
await bot.add_cog(ReloadCommand(bot))
|
|
||||||
-115
@@ -1,115 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
from datetime import datetime
|
|
||||||
from utils.logger.custom_logging import Custom_Logger
|
|
||||||
import logging
|
|
||||||
from pathlib import Path
|
|
||||||
import sys, signal
|
|
||||||
import os
|
|
||||||
import dotenv
|
|
||||||
from bot import PostIt_Bot
|
|
||||||
from utils.datetime_tools import get_elapsed_time_milliseconds, get_elapsed_time_big
|
|
||||||
import discord
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
PROGRAM_VERSION = "1.0"
|
|
||||||
print(" ____ ____ ___________ __________")
|
|
||||||
print(" / __ \/ __ \/ ___/_ __/ / _/_ __/")
|
|
||||||
print(" / /_/ / / / /\__ \ / /_____ / / / / ")
|
|
||||||
print(" / ____/ /_/ /___/ // /_____// / / / ")
|
|
||||||
print(f" /_/ \____//____//_/ /___/ /_/ v{PROGRAM_VERSION}")
|
|
||||||
print(" Copyright (c) 2024-2025 Lars Winzer")
|
|
||||||
print()
|
|
||||||
print(" Source: https://github.com/official-Cromatin/Post-It")
|
|
||||||
print(" Report an Issue: https://github.com/official-Cromatin/Post-It/issues/new?assignees=&labels=bug&projects=&template=issue_report.yml")
|
|
||||||
print("\n")
|
|
||||||
|
|
||||||
# Get timestamp for begin of actual execution
|
|
||||||
startup_time = datetime.now().timestamp()
|
|
||||||
|
|
||||||
# Initialize the logger
|
|
||||||
Custom_Logger.initialize()
|
|
||||||
app_logger = logging.getLogger("app")
|
|
||||||
app_startup_logger = logging.getLogger("app.startup")
|
|
||||||
app_startup_logger.info(f"Starting Post-It v{PROGRAM_VERSION} ...")
|
|
||||||
|
|
||||||
# Detect entrypoint
|
|
||||||
source_path = Path(__file__).resolve()
|
|
||||||
base_path = source_path.parents[1]
|
|
||||||
app_startup_logger.info(f"Using the following path as entrypoint: '{base_path}'")
|
|
||||||
|
|
||||||
# Detect operating system and attach
|
|
||||||
shutdown_event = asyncio.Event()
|
|
||||||
def signal_handler(*args):
|
|
||||||
app_logger.info("Shutdown signal recieved, shutting down")
|
|
||||||
shutdown_event.set()
|
|
||||||
|
|
||||||
match sys.platform:
|
|
||||||
case "linux":
|
|
||||||
app_startup_logger.info("Detected platform: Linux")
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
|
||||||
|
|
||||||
case "darwin":
|
|
||||||
app_startup_logger.info("Detected platform: MacOS (Darwin)")
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
|
||||||
|
|
||||||
case "win32":
|
|
||||||
app_startup_logger.info("Detected platform: Windows (Win32)")
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
|
||||||
|
|
||||||
case _:
|
|
||||||
app_startup_logger.fatal(f"Detected unsupported platform: {sys.platform}")
|
|
||||||
quit(1)
|
|
||||||
|
|
||||||
# Load environment variables
|
|
||||||
if (os.getenv("skip_dotenv", False)):
|
|
||||||
app_startup_logger.warning("Skipped import of dotenv file")
|
|
||||||
else:
|
|
||||||
dotenv.load_dotenv(base_path / ".env")
|
|
||||||
app_startup_logger.warning("Imported dotenv file")
|
|
||||||
|
|
||||||
# Check if required environment variables are present
|
|
||||||
check_ok = True
|
|
||||||
required_variables = [
|
|
||||||
"DISCORD_TOKEN",
|
|
||||||
]
|
|
||||||
|
|
||||||
for variable_name in required_variables:
|
|
||||||
if os.getenv(variable_name) is None:
|
|
||||||
app_startup_logger.error(f"Environment variable '{variable_name}' is missing")
|
|
||||||
check_ok = False
|
|
||||||
|
|
||||||
if not check_ok:
|
|
||||||
app_startup_logger.critical("Multiple required variables are missing. Aborting startup")
|
|
||||||
quit(1)
|
|
||||||
|
|
||||||
# Create bot instance and start bot
|
|
||||||
app_startup_logger.info(f"Preperations complete after {get_elapsed_time_milliseconds(datetime.now().timestamp() - startup_time)}, launching bot")
|
|
||||||
try:
|
|
||||||
bot_instance = PostIt_Bot(startup_time, PROGRAM_VERSION, app_logger)
|
|
||||||
|
|
||||||
bot_task = asyncio.create_task(bot_instance.start(os.getenv("DISCORD_TOKEN")))
|
|
||||||
shutdown_task = asyncio.create_task(shutdown_event.wait())
|
|
||||||
|
|
||||||
# Wait if either the bot disconnects or the shutdown event is detected
|
|
||||||
finished_task, _ = await asyncio.wait(
|
|
||||||
[shutdown_task, bot_task],
|
|
||||||
return_when = asyncio.FIRST_COMPLETED
|
|
||||||
)
|
|
||||||
|
|
||||||
if shutdown_task in finished_task:
|
|
||||||
await bot_instance.close()
|
|
||||||
app_logger.info("Bot closed connection successfully")
|
|
||||||
|
|
||||||
except discord.errors.LoginFailure:
|
|
||||||
app_logger.critical("Improper token has been passed. Aborting startup")
|
|
||||||
quit(1)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
app_logger.info(f"Exiting. Application ran for {get_elapsed_time_big(datetime.now().timestamp() - startup_time)}")
|
|
||||||
|
|
||||||
# Entry point for execution
|
|
||||||
if __name__ == "__main__":
|
|
||||||
asyncio.run(main())
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
|
|
||||||
def get_elapsed_time(timestamp:float) -> str:
|
|
||||||
"""Convert an timestamp into an predefined elapsed time format (00min 00sec), without miliseconds"""
|
|
||||||
time_elapsed = datetime.fromtimestamp(timestamp)
|
|
||||||
return f"{time_elapsed.minute // 60}min {time_elapsed.second:02}sec"
|
|
||||||
|
|
||||||
def get_elapsed_time_ms(timestamp:float) -> str:
|
|
||||||
"""Convert an timestamp into an predefined elapsed time format (00min 00sec 000ms), with miliseconds"""
|
|
||||||
time_elapsed = datetime.fromtimestamp(timestamp)
|
|
||||||
return f"{time_elapsed.minute // 60}min {time_elapsed.second:02}sec {time_elapsed.microsecond // 1000}ms"
|
|
||||||
|
|
||||||
def get_elapsed_time_small(timestamp:float) -> str:
|
|
||||||
"""Convert an timestamp into an predefined elapsed time format (00sec 000ms)"""
|
|
||||||
time_elapsed = datetime.fromtimestamp(timestamp)
|
|
||||||
return f"{time_elapsed.second:02}sec {time_elapsed.microsecond // 1000:03}ms"
|
|
||||||
|
|
||||||
def get_elapsed_time_big(timestamp:float) -> str:
|
|
||||||
"""Convert an timestamp into an predefined elapsed time format (00days 00hrs 00min)"""
|
|
||||||
time_elapsed = datetime.fromtimestamp(timestamp)
|
|
||||||
return f"{time_elapsed.day - 1}days {time_elapsed.hour - 1}hrs {1 if time_elapsed.minute == 0 else time_elapsed.minute}min"
|
|
||||||
|
|
||||||
def get_elapsed_time_milliseconds(timestamp:float) -> str:
|
|
||||||
"""Convert an timestamp into an predefined elapsed time format (0000ms)"""
|
|
||||||
time_elapsed = datetime.fromtimestamp(timestamp)
|
|
||||||
return f"{time_elapsed.second * 1000 + time_elapsed.microsecond // 1000}ms"
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import logging
|
|
||||||
from utils.logger.formatter import Colored_Formatter
|
|
||||||
|
|
||||||
class Custom_Logger:
|
|
||||||
console_handler: logging.StreamHandler
|
|
||||||
colored_formatter: Colored_Formatter
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def initialize(cls):
|
|
||||||
# Create the handler for logging to the console
|
|
||||||
cls.console_handler = logging.StreamHandler()
|
|
||||||
cls.console_handler.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
# Create the colorful formatter
|
|
||||||
cls.colored_formatter = Colored_Formatter()
|
|
||||||
cls.console_handler.setFormatter(cls.colored_formatter)
|
|
||||||
|
|
||||||
# Create the loggers for the different sections of the app
|
|
||||||
discordpy_logger = logging.getLogger("discord")
|
|
||||||
discordpy_logger.addHandler(cls.console_handler)
|
|
||||||
discordpy_logger.setLevel(logging.INFO)
|
|
||||||
|
|
||||||
app_logger = logging.getLogger("app")
|
|
||||||
app_logger.addHandler(cls.console_handler)
|
|
||||||
app_logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
utils_logger = logging.getLogger("utils")
|
|
||||||
utils_logger.addHandler(cls.console_handler)
|
|
||||||
utils_logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
commands_logger = logging.getLogger("cmds")
|
|
||||||
commands_logger.addHandler(cls.console_handler)
|
|
||||||
commands_logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
logging.getLogger('discord.app_commands.tree').setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
app_logger.debug("Logging successfully initialized")
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
from functools import wraps
|
|
||||||
import discord
|
|
||||||
|
|
||||||
def log_command_execution(func):
|
|
||||||
"""Wraps an command function to print execution logs to the console"""
|
|
||||||
@wraps(func)
|
|
||||||
async def wrapper(self, interaction:discord.Interaction, *args, **kwargs):
|
|
||||||
self._logger.debug(f"User {interaction.user} in channel {interaction.channel} on guild {interaction.guild} executed the {func.__name__} command")
|
|
||||||
|
|
||||||
return await func(self, interaction, *args, **kwargs)
|
|
||||||
return wrapper
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
from logging import Formatter
|
|
||||||
from colorama import Style, Fore
|
|
||||||
|
|
||||||
class Colored_Formatter(Formatter):
|
|
||||||
def __init__(self, fmt=None, datefmt='%Y-%m-%d %H:%M:%S', style='%'):
|
|
||||||
super().__init__(fmt, datefmt, style)
|
|
||||||
|
|
||||||
def format(self, record):
|
|
||||||
# Formatieren des Zeitstempels fett
|
|
||||||
date = f"{Style.BRIGHT}{Fore.BLACK}{self.formatTime(record, self.datefmt)}{Style.RESET_ALL}"
|
|
||||||
|
|
||||||
# Färben des Log-Levels mit fester Breite
|
|
||||||
levelname_color = {
|
|
||||||
'DEBUG': Fore.CYAN,
|
|
||||||
'INFO': Fore.BLUE,
|
|
||||||
'WARNING': Fore.YELLOW,
|
|
||||||
'ERROR': Fore.RED,
|
|
||||||
'CRITICAL': f"{Style.BRIGHT}{Fore.RED}"
|
|
||||||
}
|
|
||||||
levelname = f"{levelname_color.get(record.levelname, Fore.WHITE)}{record.levelname:<8}{Fore.RESET}{Style.RESET_ALL}"
|
|
||||||
|
|
||||||
# Färben des Logger-Namens in Magenta mit fester Breite
|
|
||||||
name = f"{Fore.MAGENTA}{record.name:<20}{Fore.RESET}"
|
|
||||||
|
|
||||||
# Die Nachricht bleibt unverändert
|
|
||||||
message = record.getMessage()
|
|
||||||
|
|
||||||
# Zusammenfügen der gefärbten Teile
|
|
||||||
formatted_record = f"{date} {levelname} {name} {message}"
|
|
||||||
return formatted_record
|
|
||||||
Reference in New Issue
Block a user