From 94553b602e53ea41b805d5eadab16a65b0efe178 Mon Sep 17 00:00:00 2001 From: kku Date: Sun, 29 Dec 2024 16:27:58 +0100 Subject: [PATCH 1/9] Fixed imports in examples --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c4b21b4..b77c3c9 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ pip install libbot[pycord,speed] ### Pyrogram ```python +import sys + from libbot.pyrogram.classes import PyroClient @@ -47,7 +49,7 @@ def main(): except KeyboardInterrupt: print("Shutting down...") finally: - exit() + sys.exit() if __name__ == "__main__": @@ -57,6 +59,9 @@ if __name__ == "__main__": ### Pycord ```python +import asyncio +from asyncio import AbstractEventLoop + from discord import Intents from libbot.utils import config_get from libbot.pycord.classes import PycordBot @@ -76,7 +81,7 @@ async def main(): if __name__ == "__main__": - loop = asyncio.get_event_loop() + loop: AbstractEventLoop = asyncio.get_event_loop() loop.run_until_complete(main()) ``` From bbbec75f91c5b4cb717092e260ea2d57433725f6 Mon Sep 17 00:00:00 2001 From: kku Date: Sun, 29 Dec 2024 19:27:42 +0100 Subject: [PATCH 2/9] Fixed naming conventions --- requirements/_.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/_.txt b/requirements/_.txt index 0533664..3a5d6be 100644 --- a/requirements/_.txt +++ b/requirements/_.txt @@ -1,2 +1,2 @@ aiofiles>=23.0.0 -typing_extensions~=4.12.2 \ No newline at end of file +typing-extensions~=4.12.2 \ No newline at end of file From b47bcbe513b31378b6e6664373d296ea85ec4672 Mon Sep 17 00:00:00 2001 From: Renovate Date: Mon, 30 Dec 2024 19:17:40 +0200 Subject: [PATCH 3/9] Update dependency mypy to v1.14.1 --- requirements/dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 15173ba..7236d43 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,7 +1,7 @@ black==24.10.0 build==1.2.2.post1 isort==5.13.2 -mypy==1.14.0 +mypy==1.14.1 pylint==3.3.3 pytest-asyncio==0.25.0 pytest-cov==6.0.0 From 5dd873d683b71f40f47b80ec8f75f6468228c2d3 Mon Sep 17 00:00:00 2001 From: kku Date: Tue, 31 Dec 2024 11:07:24 +0100 Subject: [PATCH 4/9] Closes #61 --- src/libbot/pycord/utils/__init__.py | 1 + src/libbot/pycord/utils/color.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/libbot/pycord/utils/__init__.py create mode 100644 src/libbot/pycord/utils/color.py diff --git a/src/libbot/pycord/utils/__init__.py b/src/libbot/pycord/utils/__init__.py new file mode 100644 index 0000000..a2b41be --- /dev/null +++ b/src/libbot/pycord/utils/__init__.py @@ -0,0 +1 @@ +from .color import color_from_hex, hex_from_color diff --git a/src/libbot/pycord/utils/color.py b/src/libbot/pycord/utils/color.py new file mode 100644 index 0000000..9b61282 --- /dev/null +++ b/src/libbot/pycord/utils/color.py @@ -0,0 +1,35 @@ +from discord import Colour + + +def _int_from_hex(hex_string: str) -> int: + try: + return int(hex_string, base=16) + except Exception as exc: + raise ValueError("Input string must be a valid HEX code.") from exc + + +def _hex_from_int(color_int: int) -> str: + if not 0 <= color_int <= 0xFFFFFF: + raise ValueError("Color's value must be in the range 0 to 0xFFFFFF.") + + return f"#{color_int:06x}" + + +def color_from_hex(hex_string: str) -> Colour: + """Convert valid hexadecimal string to discord.Colour. + + :param hex_string: Hexadecimal string to convert into Colour object + :type hex_string: str + :return: Colour object + """ + return Colour(_int_from_hex(hex_string)) + + +def hex_from_color(color: Colour) -> str: + """Convert discord.Colour to hexadecimal string. + + :param color: Colour object to convert into the string + :type color: Colour + :return: Hexadecimal string in #XXXXXX format + """ + return _hex_from_int(color.value) From 9ce251d7332778e56c56e425c6c0b6132a4e3b68 Mon Sep 17 00:00:00 2001 From: kku Date: Tue, 31 Dec 2024 11:10:06 +0100 Subject: [PATCH 5/9] Added a quick README for examples (belongs to #60) --- examples/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 examples/README.md diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..8113d37 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,4 @@ +# Examples + +If you're looking for Pyrogram usage examples, please take a look at +the [PyrogramBotBase](https://git.end-play.xyz/profitroll/PyrogramBotBase) repository. \ No newline at end of file From ae54bd5cce22bbb4e1c840f6048142569f64d63e Mon Sep 17 00:00:00 2001 From: kku Date: Tue, 31 Dec 2024 11:16:16 +0100 Subject: [PATCH 6/9] Bump version to 4.0.2 --- src/libbot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libbot/__init__.py b/src/libbot/__init__.py index ff03163..a0b80de 100644 --- a/src/libbot/__init__.py +++ b/src/libbot/__init__.py @@ -1,4 +1,4 @@ -__version__ = "4.0.1" +__version__ = "4.0.2" __license__ = "GPL3" __author__ = "Profitroll" From d5e390fe6620bbd3ab3a2dbdef05d761cbd14ab2 Mon Sep 17 00:00:00 2001 From: kku Date: Wed, 1 Jan 2025 22:34:38 +0100 Subject: [PATCH 7/9] Optimized json_load usage, imports and typing --- src/libbot/pycord/classes/bot.py | 33 ++++++-------- src/libbot/pyrogram/classes/client.py | 66 +++++++++++++-------------- 2 files changed, 45 insertions(+), 54 deletions(-) diff --git a/src/libbot/pycord/classes/bot.py b/src/libbot/pycord/classes/bot.py index d5986a1..6390813 100644 --- a/src/libbot/pycord/classes/bot.py +++ b/src/libbot/pycord/classes/bot.py @@ -1,9 +1,13 @@ import logging +from logging import Logger from pathlib import Path from typing import Any, Dict from typing_extensions import override +from ...i18n.classes import BotLocale +from ...utils import json_read + try: from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.schedulers.background import BackgroundScheduler @@ -11,32 +15,21 @@ try: except ImportError as exc: raise ImportError("You need to install libbot[pycord] in order to use this class.") from exc -try: - from ujson import loads -except ImportError: - from json import loads - -from ...i18n.classes import BotLocale - -logger = logging.getLogger(__name__) +logger: Logger = logging.getLogger(__name__) class PycordBot(Bot): @override def __init__( - self, - *args, - config: Dict[str, Any] | None = None, - config_path: str | Path = Path("config.json"), - locales_root: str | Path | None = None, - scheduler: AsyncIOScheduler | BackgroundScheduler | None = None, - **kwargs, + self, + *args, + config: Dict[str, Any] | None = None, + config_path: str | Path = Path("config.json"), + locales_root: str | Path | None = None, + scheduler: AsyncIOScheduler | BackgroundScheduler | None = None, + **kwargs, ): - if config is None: - with open(config_path, "r", encoding="utf-8") as f: - self.config: dict = loads(f.read()) - else: - self.config = config + self.config: Dict[str, Any] = config if config is not None else json_read(config_path) super().__init__( debug_guilds=(self.config["bot"]["debug_guilds"] if self.config["debug"] else None), diff --git a/src/libbot/pyrogram/classes/client.py b/src/libbot/pyrogram/classes/client.py index 0e8a204..2b01db7 100644 --- a/src/libbot/pyrogram/classes/client.py +++ b/src/libbot/pyrogram/classes/client.py @@ -2,6 +2,7 @@ import asyncio import logging import sys from datetime import datetime, timedelta +from logging import Logger from os import cpu_count, getpid from pathlib import Path from time import time @@ -9,6 +10,12 @@ from typing import Any, Dict, List from typing_extensions import override +from .command import PyroCommand +from .commandset import CommandSet +from ...i18n import _ +from ...i18n.classes import BotLocale +from ...utils import json_read + try: import pyrogram from apscheduler.schedulers.asyncio import AsyncIOScheduler @@ -35,42 +42,33 @@ try: except ImportError: from json import dumps, loads -from ...i18n.classes import BotLocale -from ...i18n import _ -from .command import PyroCommand -from .commandset import CommandSet - -logger = logging.getLogger(__name__) +logger: Logger = logging.getLogger(__name__) class PyroClient(Client): @override def __init__( - self, - name: str = "bot_client", - owner: int | None = None, - config: Dict[str, Any] | None = None, - config_path: str | Path = Path("config.json"), - api_id: int | None = None, - api_hash: str | None = None, - bot_token: str | None = None, - workers: int = min(32, cpu_count() + 4), - locales_root: str | Path | None = None, - plugins_root: str = "plugins", - plugins_exclude: List[str] | None = None, - sleep_threshold: int = 120, - max_concurrent_transmissions: int = 1, - commands_source: Dict[str, dict] | None = None, - scoped_commands: bool | None = None, - i18n_bot_info: bool = False, - scheduler: AsyncIOScheduler | BackgroundScheduler | None = None, - **kwargs, + self, + name: str = "bot_client", + owner: int | None = None, + config: Dict[str, Any] | None = None, + config_path: str | Path = Path("config.json"), + api_id: int | None = None, + api_hash: str | None = None, + bot_token: str | None = None, + workers: int = min(32, cpu_count() + 4), + locales_root: str | Path | None = None, + plugins_root: str = "plugins", + plugins_exclude: List[str] | None = None, + sleep_threshold: int = 120, + max_concurrent_transmissions: int = 1, + commands_source: Dict[str, dict] | None = None, + scoped_commands: bool | None = None, + i18n_bot_info: bool = False, + scheduler: AsyncIOScheduler | BackgroundScheduler | None = None, + **kwargs, ): - if config is None: - with open(config_path, "r", encoding="utf-8") as f: - self.config: dict = loads(f.read()) - else: - self.config = config + self.config: Dict[str, Any] = config if config is not None else json_read(config_path) super().__init__( name=name, @@ -211,7 +209,7 @@ class PyroClient(Client): @override async def stop( - self, exit_completely: bool = True, scheduler_shutdown: bool = True, scheduler_wait: bool = True + self, exit_completely: bool = True, scheduler_shutdown: bool = True, scheduler_wait: bool = True ) -> None: try: await self.send_message( @@ -310,7 +308,7 @@ class PyroClient(Client): # in it, if there are any. Then adds them to self.commands for handler in self.dispatcher.groups[0]: if isinstance(handler, MessageHandler) and ( - hasattr(handler.filters, "base") or hasattr(handler.filters, "other") + hasattr(handler.filters, "base") or hasattr(handler.filters, "other") ): for entry in [handler.filters.base, handler.filters.other]: if hasattr(entry, "commands"): @@ -321,8 +319,8 @@ class PyroClient(Client): return command_sets def add_command( - self, - command: str, + self, + command: str, ) -> None: """Add command to the bot's internal commands list From 1da367ccb1112b72b5c4d6cd8ec520c039b575b6 Mon Sep 17 00:00:00 2001 From: Renovate Date: Thu, 2 Jan 2025 08:03:07 +0200 Subject: [PATCH 8/9] Update dependency pytest-asyncio to v0.25.1 --- requirements/dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 7236d43..1411061 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -3,7 +3,7 @@ build==1.2.2.post1 isort==5.13.2 mypy==1.14.1 pylint==3.3.3 -pytest-asyncio==0.25.0 +pytest-asyncio==0.25.1 pytest-cov==6.0.0 pytest==8.3.4 tox==4.23.2 From e9b9fc6ca14e15c8f1299c87391f19b9130ba94b Mon Sep 17 00:00:00 2001 From: kku Date: Thu, 2 Jan 2025 13:58:23 +0100 Subject: [PATCH 9/9] TEST: Publishing Action --- .gitea/workflows/publish.yml | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 .gitea/workflows/publish.yml diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml new file mode 100644 index 0000000..5809a53 --- /dev/null +++ b/.gitea/workflows/publish.yml @@ -0,0 +1,90 @@ +name: Upload Python Package + +on: + release: + types: [ published ] + +permissions: + contents: read + +jobs: + release-build: + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - name: Build release distributions + run: | + python -m pip install build + python -m build + + - name: Upload distributions + uses: christopherhx/gitea-upload-artifact@v4 + with: + name: release-dists + path: dist/ + + gitea-publish: + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + + needs: + - release-build + + permissions: + id-token: write + + environment: + name: gitea + url: https://git.end-play.xyz/profitroll/-/packages/pypi/libbot + + env: + GITHUB_WORKFLOW_REF: ${{ gitea.workflow_ref }} + INPUT_REPOSITORY_URL: https://git.end-play.xyz/api/packages/profitroll/pypi + + steps: + - name: Retrieve release distributions + uses: christopherhx/gitea-download-artifact@v4 + with: + name: release-dists + path: dist/ + + - name: Publish package distributions to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_GITEA_API_TOKEN }} + repository-url: https://git.end-play.xyz/api/packages/profitroll/pypi + + pypi-publish: + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + + needs: + - release-build + + permissions: + id-token: write + + environment: + name: pypi + + env: + GITHUB_WORKFLOW_REF: ${{ gitea.workflow_ref }} + + steps: + - name: Retrieve release distributions + uses: christopherhx/gitea-download-artifact@v4 + with: + name: release-dists + path: dist/ + + - name: Publish package distributions to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_PYPI_API_TOKEN }} \ No newline at end of file