From 94553b602e53ea41b805d5eadab16a65b0efe178 Mon Sep 17 00:00:00 2001
From: kku <kku@inconsult-online.de>
Date: Sun, 29 Dec 2024 16:27:58 +0100
Subject: [PATCH 1/8] 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())
 ```
 
-- 
2.39.5


From bbbec75f91c5b4cb717092e260ea2d57433725f6 Mon Sep 17 00:00:00 2001
From: kku <kku@inconsult-online.de>
Date: Sun, 29 Dec 2024 19:27:42 +0100
Subject: [PATCH 2/8] 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
-- 
2.39.5


From b47bcbe513b31378b6e6664373d296ea85ec4672 Mon Sep 17 00:00:00 2001
From: Renovate <renovate@git.end-play.xyz>
Date: Mon, 30 Dec 2024 19:17:40 +0200
Subject: [PATCH 3/8] 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
-- 
2.39.5


From 5dd873d683b71f40f47b80ec8f75f6468228c2d3 Mon Sep 17 00:00:00 2001
From: kku <kku@inconsult-online.de>
Date: Tue, 31 Dec 2024 11:07:24 +0100
Subject: [PATCH 4/8] 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)
-- 
2.39.5


From 9ce251d7332778e56c56e425c6c0b6132a4e3b68 Mon Sep 17 00:00:00 2001
From: kku <kku@inconsult-online.de>
Date: Tue, 31 Dec 2024 11:10:06 +0100
Subject: [PATCH 5/8] 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
-- 
2.39.5


From ae54bd5cce22bbb4e1c840f6048142569f64d63e Mon Sep 17 00:00:00 2001
From: kku <kku@inconsult-online.de>
Date: Tue, 31 Dec 2024 11:16:16 +0100
Subject: [PATCH 6/8] 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"
 
-- 
2.39.5


From 9bc4d0348d0ffaa0458467f1723cb7bde19883ab Mon Sep 17 00:00:00 2001
From: kku <kku@inconsult-online.de>
Date: Wed, 1 Jan 2025 22:35:17 +0100
Subject: [PATCH 7/8] WIP: Matrix support (with SMBL)

---
 pyproject.toml                        |  1 +
 requirements/matrix.txt               |  1 +
 src/libbot/matrix/__init__.py         |  2 +
 src/libbot/matrix/classes/__init__.py |  1 +
 src/libbot/matrix/classes/bot.py      | 63 +++++++++++++++++++++++++++
 5 files changed, 68 insertions(+)
 create mode 100644 requirements/matrix.txt
 create mode 100644 src/libbot/matrix/__init__.py
 create mode 100644 src/libbot/matrix/classes/__init__.py
 create mode 100644 src/libbot/matrix/classes/bot.py

diff --git a/pyproject.toml b/pyproject.toml
index 5748f8d..b9f673f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -28,6 +28,7 @@ dependencies = { file = "requirements/_.txt" }
 
 [tool.setuptools.dynamic.optional-dependencies]
 dev = { file = "requirements/dev.txt" }
+matrix = { file = "requirements/matrix.txt" }
 pycord = { file = "requirements/pycord.txt" }
 pyrogram = { file = "requirements/pyrogram.txt" }
 speed = { file = "requirements/speed.txt" }
diff --git a/requirements/matrix.txt b/requirements/matrix.txt
new file mode 100644
index 0000000..244adad
--- /dev/null
+++ b/requirements/matrix.txt
@@ -0,0 +1 @@
+simplematrixbotlib~=2.12.1
\ No newline at end of file
diff --git a/src/libbot/matrix/__init__.py b/src/libbot/matrix/__init__.py
new file mode 100644
index 0000000..a64b6f3
--- /dev/null
+++ b/src/libbot/matrix/__init__.py
@@ -0,0 +1,2 @@
+# This file is left empty on purpose
+# Adding imports here will cause import errors when libbot[matrix] is not installed
diff --git a/src/libbot/matrix/classes/__init__.py b/src/libbot/matrix/classes/__init__.py
new file mode 100644
index 0000000..39a0ed6
--- /dev/null
+++ b/src/libbot/matrix/classes/__init__.py
@@ -0,0 +1 @@
+from .bot import MatrixBot
diff --git a/src/libbot/matrix/classes/bot.py b/src/libbot/matrix/classes/bot.py
new file mode 100644
index 0000000..4004e40
--- /dev/null
+++ b/src/libbot/matrix/classes/bot.py
@@ -0,0 +1,63 @@
+import logging
+from logging import Logger
+from pathlib import Path
+from typing import Dict, Any
+
+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
+    from simplematrixbotlib import Bot, Creds, Config
+except ImportError as exc:
+    raise ImportError("You need to install libbot[matrix] in order to use this class.") from exc
+
+logger: Logger = logging.getLogger(__name__)
+
+
+class MatrixBot(Bot):
+    @override
+    def __init__(
+            self,
+            config: Dict[str, Any] | None = None,
+            config_path: str | Path = Path("config.json"),
+            locales_root: str | Path | None = None,
+            scheduler: AsyncIOScheduler | BackgroundScheduler | None = None,
+            smbl_creds: Creds = None,
+            smbl_config: Config = None,
+    ):
+        self.config: Dict[str, Any] = config if config is not None else json_read(config_path)
+
+        super().__init__(
+            creds=smbl_creds if smbl_creds is not None else Creds(homeserver=self.config["homeserver"],
+                                                                  username=self.config["username"],
+                                                                  password=self.config["password"],
+                                                                  device_name=self.config["device_name"]),
+            config=smbl_config,
+        )
+
+        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[str, Any] = self.bot_locale.locales
+
+        self._ = self.bot_locale._
+        self.in_all_locales = self.bot_locale.in_all_locales
+        self.in_every_locale = self.bot_locale.in_every_locale
+
+        self.scheduler: AsyncIOScheduler | BackgroundScheduler | None = scheduler
+
+    @override
+    def run(self, scheduler_start: bool = True, scheduler_shutdown: bool = True, scheduler_wait: bool = True) -> None:
+        if self.scheduler is not None and scheduler_start:
+            self.scheduler.start()
+
+        super().run()
+
+        if self.scheduler is not None and scheduler_shutdown:
+            self.scheduler.shutdown(scheduler_wait)
-- 
2.39.5


From 5a244f603d18ae2a672dfdff581692dd62a4893d Mon Sep 17 00:00:00 2001
From: kku <kku@inconsult-online.de>
Date: Thu, 2 Jan 2025 13:51:36 +0100
Subject: [PATCH 8/8] 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
-- 
2.39.5