From f101105d41134bc4720ccabf625a2f3b33637b6f Mon Sep 17 00:00:00 2001 From: Renovate Date: Wed, 15 May 2024 05:41:51 +0300 Subject: [PATCH 1/7] Update dependency types-ujson to v5.10.0.20240515 --- requirements/dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 2b24a25..51c26d8 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -8,4 +8,4 @@ pytest-cov==5.0.0 pytest==8.2.0 tox==4.15.0 types-aiofiles==23.2.0.20240403 -types-ujson==5.9.0.0 \ No newline at end of file +types-ujson==5.10.0.20240515 \ No newline at end of file From e8769e8aeb25631129933d5e795ec798bf6fb33a Mon Sep 17 00:00:00 2001 From: Renovate Date: Sat, 18 May 2024 20:18:16 +0300 Subject: [PATCH 2/7] Update dependency pylint to v3.2.1 --- requirements/dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 51c26d8..753f198 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -2,7 +2,7 @@ black==24.4.2 build==1.2.1 isort==5.13.2 mypy==1.10.0 -pylint==3.2.0 +pylint==3.2.1 pytest-asyncio==0.23.6 pytest-cov==5.0.0 pytest==8.2.0 From 10c7ecbfd0ca58bc96de465a600be9b89194f564 Mon Sep 17 00:00:00 2001 From: Renovate Date: Sun, 19 May 2024 15:07:08 +0300 Subject: [PATCH 3/7] Update dependency pytest-asyncio to v0.23.7 --- requirements/dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 753f198..c2ea1dc 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -3,7 +3,7 @@ build==1.2.1 isort==5.13.2 mypy==1.10.0 pylint==3.2.1 -pytest-asyncio==0.23.6 +pytest-asyncio==0.23.7 pytest-cov==5.0.0 pytest==8.2.0 tox==4.15.0 From 1f464ef624e0fd68b454560de5db00da9aed5ed0 Mon Sep 17 00:00:00 2001 From: profitroll Date: Sun, 19 May 2024 14:47:07 +0200 Subject: [PATCH 4/7] Improved metadata and readme --- README.md | 86 +++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 4 +-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5a8d35d..8b281f2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,86 @@ -# LibBotUniversal +

LibBotUniversal

+

+PyPI - License +Gitea Release +PyPI - Python Version +Code style: black +

+ +Handy library for Telegram/Discord bots development. + +## Getting started + +There are different sub-packages available: + +* pyrogram - Telegram bots with Pyrogram's fork "Pyrofork" +* pycord - Discord bots with Pycord +* speed - Performance improvements +* dev - Dependencies for package development purposes + +You can freely choose any sub-package you want, as well as add multiple (comma-separated) or none at all. + +```shell +# Only general features +pip install libbot + +# Only with Pyrogram +pip install libbot[pyrogram] + +# With Pycord and Performance improvements +pip install libbot[pycord,speed] +``` + +## Examples + +### Pyrogram + +```python +from libbot.pyrogram import PyroClient + +def main(): + client = PyroClient(scheduler=scheduler) + + try: + client.run() + except KeyboardInterrupt: + print("Shutting down...") + finally: + if client.scheduler is not None: + client.scheduler.shutdown() + exit() + + +if __name__ == "__main__": + main() +``` + +### Pycord + +```python +from discord import Intents +from libbot import sync +from libbot.pycord import PycordBot + + +async def main(): + intents = Intents.default() + bot = PycordBot(intents=intents) + + bot.load_extension("cogs") + + try: + await bot.start(sync.config_get("bot_token", "bot")) + except KeyboardInterrupt: + logger.warning("Shutting down...") + await bot.close() + + +if __name__ == "__main__": + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) +``` + +## Config examples + +For bot config examples please check the examples directory. Without a valid config file, the bot won't start at all, so you need to make sure the correct config file is used. diff --git a/pyproject.toml b/pyproject.toml index 237b193..c9f761f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,11 +9,11 @@ authors = [{ name = "Profitroll" }] description = "Universal bot library with functions needed for basic Discord/Telegram bot development." readme = "README.md" requires-python = ">=3.8" -license = { file = "LICENSE" } +license = { text = "GPLv3" } classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: OS Independent", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", From c3d3e4321643f58f452c1bbf95f61be696355ecb Mon Sep 17 00:00:00 2001 From: profitroll Date: Sun, 19 May 2024 14:48:01 +0200 Subject: [PATCH 5/7] Added errors and fixed pycord's bot --- src/libbot/__init__.py | 4 ++-- src/libbot/errors/__init__.py | 1 + src/libbot/errors/config.py | 37 ++++++++++++++++++++++++++++++++ src/libbot/pycord/classes/bot.py | 11 ++++++---- 4 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 src/libbot/errors/__init__.py create mode 100644 src/libbot/errors/config.py diff --git a/src/libbot/__init__.py b/src/libbot/__init__.py index 74b0290..ae01807 100644 --- a/src/libbot/__init__.py +++ b/src/libbot/__init__.py @@ -1,6 +1,6 @@ -__version__ = "3.0.1" +__version__ = "3.1.0" __license__ = "GPL3" __author__ = "Profitroll" -from . import i18n, pycord, pyrogram, sync +from . import errors, i18n, pycord, pyrogram, sync from .__main__ import * diff --git a/src/libbot/errors/__init__.py b/src/libbot/errors/__init__.py new file mode 100644 index 0000000..1b0549f --- /dev/null +++ b/src/libbot/errors/__init__.py @@ -0,0 +1 @@ +from .config import ConfigKeyError, ConfigValueError diff --git a/src/libbot/errors/config.py b/src/libbot/errors/config.py new file mode 100644 index 0000000..64f8a4c --- /dev/null +++ b/src/libbot/errors/config.py @@ -0,0 +1,37 @@ +from typing import Any, List, Optional, Union + + +class ConfigKeyError(Exception): + """Raised when config key is not found. + + ### Attributes: + * key (`Union[str, List[str]]`): Missing config key. + """ + + def __init__(self, key: Union[str, List[str]]) -> None: + self.key: Union[str, List[str]] = key + super().__init__( + f"Config key {'.'.join(key) if isinstance(key, list) else key} is missing. Please set in your config file." + ) + + def __str__(self): + return f"Config key {'.'.join(self.key) if isinstance(self.key, list) else self.key} is missing. Please set in your config file." + + +class ConfigValueError(Exception): + """Raised when config key's value is invalid. + + ### Attributes: + * key (`Union[str, List[str]]`): Invalid config key. + * value (`Optional[Any]`): Key's correct value. + """ + + def __init__(self, key: Union[str, List[str]], value: Optional[Any] = None) -> None: + self.key: Union[str, List[str]] = key + self.value: Optional[Any] = value + super().__init__( + f"Config key {'.'.join(key) if isinstance(key, list) else key} has invalid value. {f'Must be {value}. ' if value else ''}Please set in your config file." + ) + + def __str__(self): + return f"Config key {'.'.join(self.key) if isinstance(self.key, list) else self.key} has invalid value. {f'Must be {self.value}. ' if self.value else ''}Please set in your config file." diff --git a/src/libbot/pycord/classes/bot.py b/src/libbot/pycord/classes/bot.py index e59dad5..d521532 100644 --- a/src/libbot/pycord/classes/bot.py +++ b/src/libbot/pycord/classes/bot.py @@ -1,6 +1,6 @@ import logging from pathlib import Path -from typing import Any, Dict, Union +from typing import Any, Dict, List, Union try: from apscheduler.schedulers.asyncio import AsyncIOScheduler @@ -29,6 +29,7 @@ class PycordBot(Bot): config_path: Union[str, Path] = Path("config.json"), locales_root: Union[str, Path, None] = None, scheduler: Union[AsyncIOScheduler, BackgroundScheduler, None] = None, + *args, **kwargs, ): if config is None: @@ -38,17 +39,19 @@ class PycordBot(Bot): self.config = config super().__init__( - debug_guilds=self.config["bot"]["debug_guilds"], - owner_ids=self.config["bot"]["owners"], + *args, **kwargs, ) + self.owner_ids: List[int] = self.config["bot"]["owners"] + self.debug_guilds: List[int] = self.config["bot"]["debug_guilds"] + self.bot_locale: BotLocale = BotLocale( default_locale=self.config["locale"], locales_root=(Path("locale") if locales_root is None else locales_root), ) self.default_locale: str = self.bot_locale.default - self.locales: dict = self.bot_locale.locales + self.locales: Dict[str, Any] = self.bot_locale.locales self._ = self.bot_locale._ self.in_all_locales = self.bot_locale.in_all_locales From 2ed348933bca099d7140312e1edc4d3d2d0e8d47 Mon Sep 17 00:00:00 2001 From: profitroll Date: Sun, 19 May 2024 14:48:16 +0200 Subject: [PATCH 6/7] Separated examples for Pyrogram and Pycord --- examples/config_pycord.json | 13 +++++++++++++ examples/{config.json => config_pyrogram.json} | 0 2 files changed, 13 insertions(+) create mode 100644 examples/config_pycord.json rename examples/{config.json => config_pyrogram.json} (100%) diff --git a/examples/config_pycord.json b/examples/config_pycord.json new file mode 100644 index 0000000..128ebde --- /dev/null +++ b/examples/config_pycord.json @@ -0,0 +1,13 @@ +{ + "locale": "en", + "debug": false, + "bot": { + "owners": [ + 0 + ], + "debug_guilds": [ + 0 + ], + "bot_token": "" + } +} \ No newline at end of file diff --git a/examples/config.json b/examples/config_pyrogram.json similarity index 100% rename from examples/config.json rename to examples/config_pyrogram.json From 7068e7f194bd5a46198985083bca327100250e63 Mon Sep 17 00:00:00 2001 From: profitroll Date: Sun, 19 May 2024 15:03:01 +0200 Subject: [PATCH 7/7] PycordBot.debug_guilds is now only set when debug is on --- src/libbot/pycord/classes/bot.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libbot/pycord/classes/bot.py b/src/libbot/pycord/classes/bot.py index d521532..829961b 100644 --- a/src/libbot/pycord/classes/bot.py +++ b/src/libbot/pycord/classes/bot.py @@ -39,13 +39,14 @@ class PycordBot(Bot): self.config = config super().__init__( + debug_guilds=( + self.config["bot"]["debug_guilds"] if self.config["debug"] else None + ), + owner_ids=self.config["bot"]["owners"], *args, **kwargs, ) - self.owner_ids: List[int] = self.config["bot"]["owners"] - self.debug_guilds: List[int] = self.config["bot"]["debug_guilds"] - self.bot_locale: BotLocale = BotLocale( default_locale=self.config["locale"], locales_root=(Path("locale") if locales_root is None else locales_root),