discord.py.logging 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ from .handlers.channel_log_handler import (
2
+ ChannelLogHandler,
3
+ get_channel_log_handler,
4
+ )
5
+ from .handlers.user_log_handler import UserLogHandler, get_user_log_handler
6
+
7
+ __all__ = [
8
+ "ChannelLogHandler",
9
+ "UserLogHandler",
10
+ "get_channel_log_handler",
11
+ "get_user_log_handler",
12
+ ]
@@ -0,0 +1,9 @@
1
+ import logging
2
+ from logging import WARNING
3
+
4
+
5
+ class RateLimitFilter(logging.Filter):
6
+ def filter(self, record: logging.LogRecord):
7
+ return not (
8
+ "responded with 429" in record.message and record.levelno == WARNING
9
+ )
@@ -0,0 +1,10 @@
1
+ import logging
2
+ from logging import INFO
3
+
4
+
5
+ class SessionResumedFilter(logging.Filter):
6
+ def filter(self, record: logging.LogRecord):
7
+ return not (
8
+ "has successfully RESUMED session" in record.message
9
+ and record.levelno == INFO
10
+ )
@@ -0,0 +1,79 @@
1
+ import asyncio
2
+ from abc import ABC, abstractmethod
3
+ from logging import Handler, LogRecord, getLogger
4
+ from typing import override
5
+
6
+ from ratelimit import limits, sleep_and_retry
7
+
8
+ from discord.ext import logging
9
+ from discord.ext.logging import Embed
10
+
11
+
12
+ class BaseDiscordHandler(Handler, ABC):
13
+ def __init__(self, client: logging.Client, level: int = 0):
14
+ super().__init__(level=0)
15
+ self._ready = asyncio.Event()
16
+ self._successful = False
17
+ self._client: logging.Client = client
18
+ self._logger = getLogger(self.__class__.__name__)
19
+ asyncio.create_task(self.__setup())
20
+
21
+ async def __setup(self):
22
+ await self._client.wait_until_ready()
23
+ self._successful = await self._setup()
24
+ self._ready.set()
25
+
26
+ @abstractmethod
27
+ async def _setup(self) -> bool:
28
+ pass
29
+
30
+ @abstractmethod
31
+ async def _send_message(self, embed: logging.Embed):
32
+ pass
33
+
34
+ @override
35
+ def emit(self, record: LogRecord) -> None:
36
+ asyncio.create_task(self._send_record(record))
37
+
38
+ async def info(self, title: str, message: str):
39
+ await self._send_message(
40
+ Embed(title=title, description=message, color=logging.Color.blue())
41
+ )
42
+
43
+ async def warning(self, title: str, message: str):
44
+ await self._send_message(
45
+ Embed(title=title, description=message, color=logging.Color.yellow())
46
+ )
47
+
48
+ async def error(self, title: str, message: str):
49
+ await self._send_message(
50
+ Embed(title=title, description=message, color=logging.Color.red())
51
+ )
52
+
53
+ async def critical(self, title: str, message: str):
54
+ await self._send_message(
55
+ Embed(title=title, description=message, color=logging.Color.dark_red())
56
+ )
57
+
58
+ @sleep_and_retry
59
+ @limits(calls=1, period=0.5)
60
+ async def _send_record(self, record: LogRecord) -> None:
61
+ await self._ready.wait()
62
+ if self._successful is None or self._client.is_closed():
63
+ return
64
+
65
+ title = f"{record.name}:{record.levelname}"
66
+ description = record.message
67
+
68
+ if record.exc_text is not None:
69
+ description += f" -> {record.exc_text}"
70
+
71
+ match record.levelname.upper():
72
+ case "INFO":
73
+ await self.info(title, description)
74
+ case "WARNING":
75
+ await self.warning(title, description)
76
+ case "ERROR":
77
+ await self.error(title, description)
78
+ case "CRITICAL":
79
+ await self.critical(title, description)
@@ -0,0 +1,38 @@
1
+ from discord.ext import logging
2
+
3
+ from ..filters.rate_limit_filter import RateLimitFilter
4
+ from ..filters.session_resumed_filter import SessionResumedFilter
5
+ from .base_discord_handler import BaseDiscordHandler
6
+
7
+
8
+ class ChannelLogHandler(BaseDiscordHandler):
9
+ def __init__(self, discord_client: logging.Client, target_channel_id: int):
10
+ self._target_channel_id: int = target_channel_id
11
+ self._target_channel: logging.User | None = None
12
+
13
+ super().__init__(discord_client)
14
+
15
+ async def _setup(self) -> bool:
16
+ try:
17
+ self._target_channel = self._client.fetch_channel(self.target_channel_id)
18
+ return True
19
+ except logging.NotFound:
20
+ self._logger.error(
21
+ f"Channel : {self.target_channel_id} could not be found for logging!"
22
+ )
23
+ return False
24
+ except logging.HTTPException:
25
+ self._logger.error("Failed to fetch channel for logger!")
26
+ return False
27
+
28
+ async def _send_message(self, embed: logging.Embed):
29
+ await self._target_channel.send(embed=embed)
30
+
31
+
32
+ def get_channel_log_handler(
33
+ discord_client: logging.Client, target_channel_id: int
34
+ ) -> ChannelLogHandler:
35
+ handler = ChannelLogHandler(discord_client, target_channel_id)
36
+ handler.addFilter(RateLimitFilter())
37
+ handler.addFilter(SessionResumedFilter())
38
+ return handler
@@ -0,0 +1,40 @@
1
+ from typing import override
2
+
3
+ from discord.ext import logging
4
+
5
+ from ..filters.rate_limit_filter import RateLimitFilter
6
+ from ..filters.session_resumed_filter import SessionResumedFilter
7
+ from .base_discord_handler import BaseDiscordHandler
8
+
9
+
10
+ class UserLogHandler(BaseDiscordHandler):
11
+ def __init__(self, discord_client: logging.Client, target_user_id: int):
12
+ self._target_user_id: int = target_user_id
13
+ self._target_user: logging.User | None = None
14
+
15
+ super().__init__(discord_client)
16
+
17
+ @override
18
+ async def _setup(self) -> bool:
19
+ try:
20
+ self._target_user = await self._client.fetch_user(self.target_user_id)
21
+ return True
22
+ except logging.NotFound:
23
+ self._logger.error(
24
+ f"User : {self.target_user_id} could not be found for logging!"
25
+ )
26
+ return False
27
+ except logging.HTTPException:
28
+ self._logger.error("Failed to fetch user for logger!")
29
+ return False
30
+
31
+ @override
32
+ async def _send_message(self, embed: logging.Embed):
33
+ await self._target_user.send(embed=embed)
34
+
35
+
36
+ def get_user_log_handler(discord_client: logging.Client, target_user_id: int):
37
+ handler = UserLogHandler(discord_client, target_user_id)
38
+ handler.addFilter(RateLimitFilter())
39
+ handler.addFilter(SessionResumedFilter())
40
+ return handler
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.5
2
+ Name: discord.py.logging
3
+ Version: 0.1.0
4
+ Summary: A logger handle that uses discord
5
+ Author-email: Wildbush <75509166+Wildbush76@users.noreply.github.com>
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: discord-py>=2.7.1
8
+ Requires-Dist: ratelimit>=2.2.1
@@ -0,0 +1,9 @@
1
+ discord/ext/logging/__init__.py,sha256=CietN_zM_m79JnOadGAwnNAs5mr3vgITU-JjCrsPRSM,295
2
+ discord/ext/logging/filters/rate_limit_filter.py,sha256=xDhdcAcP5YjxkTIPX8JUaKS4XYFEABJzkovuSpZtUL8,254
3
+ discord/ext/logging/filters/session_resumed_filter.py,sha256=5lx4wCxmQqiuchncQGwoCqvW6BxvN7aa4fNnBHpQpng,280
4
+ discord/ext/logging/handlers/base_discord_handler.py,sha256=r84u1RTDAT2iuxp0pGKJln0ZYmaWLgkq9KBj8oUpC1E,2614
5
+ discord/ext/logging/handlers/channel_log_handler.py,sha256=NzYWj3kcPzNxVRjMve1i5GqrVOuv32Kug4xWLEbQlqE,1410
6
+ discord/ext/logging/handlers/user_log_handler.py,sha256=CltaSnXQ2dgiJUZs-VxYi6RjiRC4-dVkv0yq8_KwpKc,1400
7
+ discord_py_logging-0.1.0.dist-info/METADATA,sha256=GG0deG9ugqHe9gBLIr47FvxDE889lzzxe9JYfCYpc2s,264
8
+ discord_py_logging-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
9
+ discord_py_logging-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any