From b482d87d0ebf77d8296426be3c0d7ad17fea1a82 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Mon, 17 Mar 2025 12:46:29 -0400 Subject: [PATCH] Initial commit --- .gitea/workflows/build_develop.yml | 26 ++++++ .gitea/workflows/build_latest.yml | 26 ++++++ .gitea/workflows/build_release.yml | 28 +++++++ .gitignore | 130 +++++++++++++++++++++++++++++ .vscode/extensions.json | 8 ++ .vscode/launch.json | 15 ++++ .vscode/settings.json | 7 ++ Dockerfile | 16 ++++ README.md | 0 cogs/commands/__init__.py | 12 +++ cogs/commands/hi.py | 22 +++++ config.py | 22 +++++ main.py | 52 ++++++++++++ pyproject.toml | 116 +++++++++++++++++++++++++ renovate.json | 29 +++++++ settings.py | 28 +++++++ 16 files changed, 537 insertions(+) create mode 100644 .gitea/workflows/build_develop.yml create mode 100644 .gitea/workflows/build_latest.yml create mode 100644 .gitea/workflows/build_release.yml create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 cogs/commands/__init__.py create mode 100644 cogs/commands/hi.py create mode 100644 config.py create mode 100644 main.py create mode 100644 pyproject.toml create mode 100644 renovate.json create mode 100644 settings.py diff --git a/.gitea/workflows/build_develop.yml b/.gitea/workflows/build_develop.yml new file mode 100644 index 0000000..519ed51 --- /dev/null +++ b/.gitea/workflows/build_develop.yml @@ -0,0 +1,26 @@ +name: build_develop + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Install Docker + uses: https://github.com/papodaca/install-docker-action@v1 + - name: Log into container registry + uses: docker/login-action@v2 + with: + registry: gitea.cheezers.org + username: imcompiling + password: ${{ secrets.PASSWORD }} + - name: set env + run: echo "GIT_BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV + - name: Build Docker Image + run: docker build -t gitea.cheezers.org/imcompiling/off-cooldown-bot:${{env.GIT_BRANCH}} . + - name: Push Docker Image + run: docker push gitea.cheezers.org/imcompiling/off-cooldown-bot:${{env.GIT_BRANCH}} diff --git a/.gitea/workflows/build_latest.yml b/.gitea/workflows/build_latest.yml new file mode 100644 index 0000000..c97b983 --- /dev/null +++ b/.gitea/workflows/build_latest.yml @@ -0,0 +1,26 @@ +name: build_latest + +on: + push: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Install Docker + uses: https://github.com/papodaca/install-docker-action@v1 + - name: Log into container registry + uses: docker/login-action@v2 + with: + registry: gitea.cheezers.org + username: imcompiling + password: ${{ secrets.PASSWORD }} + - name: Build Docker Image + run: docker build -t gitea.cheezers.org/imcompiling/off-cooldown-bot:latest . + - name: Push Docker Image + run: docker push gitea.cheezers.org/imcompiling/off-cooldown-bot:latest diff --git a/.gitea/workflows/build_release.yml b/.gitea/workflows/build_release.yml new file mode 100644 index 0000000..9fa2d86 --- /dev/null +++ b/.gitea/workflows/build_release.yml @@ -0,0 +1,28 @@ +name: build_release + +on: + push: + tags: ["v[0-9].[0-9].[0-9]"] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Install Docker + uses: https://github.com/papodaca/install-docker-action@v1 + - name: Log into container registry + uses: docker/login-action@v2 + with: + registry: gitea.cheezers.org + username: imcompiling + password: ${{ secrets.PASSWORD }} + - name: Set env + run: echo "GIT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - name: Build Docker Image + run: docker build -t gitea.cheezers.org/imcompiling/off-cooldown-bot:${{env.GIT_TAG}} . + - name: Push Tagged Image + run: docker push gitea.cheezers.org/imcompiling/off-cooldown-bot:${{env.GIT_TAG}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8eb0026 --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +conf/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# logging +nextcord.log +outputs/ \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..b8dd61b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "ms-python.vscode-pylance", + "ms-python.python", + "ms-python.debugpy", + "charliermarsh.ruff" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9ecc6e2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Module", + "type": "debugpy", + "request": "launch", + "module": "main", + "justMyCode": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0e73f13 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "python.analysis.diagnosticSeverityOverrides": { + "reportOptionalMemberAccess": "warning", + "reportArgumentType": "information", + "reportAttributeAccessIssue": "warning" + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0b03a2b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.12.3-slim + +# install uv +COPY --from=ghcr.io/astral-sh/uv:0.6.5 /uv /uvx /bin/ + +WORKDIR /home + +COPY config.py config.py +COPY main.py main.py +COPY pyproject.toml pyproject.toml + +COPY cogs cogs/ + +RUN uv sync --frozen --no-dev + +CMD ["uv", "run", "./main.py"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/cogs/commands/__init__.py b/cogs/commands/__init__.py new file mode 100644 index 0000000..b6739b9 --- /dev/null +++ b/cogs/commands/__init__.py @@ -0,0 +1,12 @@ +"""Cog loader. Adds all command cogs to the bot.""" + +from nextcord.ext import commands + +from cogs.commands.hi import HiCog + + +# This function will be called when this extension is loaded. +# It is necessary to add these functions to the bot. +def setup(bot: commands.Bot) -> None: + """Add all command classes to bot.""" + bot.add_cog(HiCog(bot)) diff --git a/cogs/commands/hi.py b/cogs/commands/hi.py new file mode 100644 index 0000000..0a7a512 --- /dev/null +++ b/cogs/commands/hi.py @@ -0,0 +1,22 @@ +"""Example command file.""" + +import nextcord +from nextcord.ext import commands + + +class HiCog(commands.Cog, name="Test commands."): + """Class holds commands for testing.""" + + def __init__(self, bot: nextcord.Bot) -> None: + self.bot = bot + + @nextcord.slash_command() + async def hi(self, interaction: nextcord.Interaction) -> None: + """ + Says hi. + + Args: + interaction (nextcord.Interaction): Interaction to reply to. + + """ + await interaction.response.send_message("Hi!", ephemeral=True) diff --git a/config.py b/config.py new file mode 100644 index 0000000..99a61a5 --- /dev/null +++ b/config.py @@ -0,0 +1,22 @@ +""" +File contains classes defining the Hydra configuraton structure. +""" +from dataclasses import dataclass + + +@dataclass +class Params: + """ + Class defines the various configuration parameters. + """ + + discord_token: str + + +@dataclass +class BotConfig: + """ + Class defines all configs required for Dakiny Bot. + """ + + params: Params diff --git a/main.py b/main.py new file mode 100644 index 0000000..ee38aad --- /dev/null +++ b/main.py @@ -0,0 +1,52 @@ +"""Main file for bot.""" + +import logging +import os + +import nextcord +from nextcord.ext import commands + +from settings import settings + +nextcord_logger = logging.getLogger("nextcord") +nextcord_logger.setLevel(logging.DEBUG) +nextcord_handler = logging.FileHandler(filename="nextcord.log", encoding="utf-8", mode="w") +nextcord_handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")) +nextcord_logger.addHandler(nextcord_handler) + + +def main() -> None: + """Set config, intents, then connects the bot to discord.""" + # Allows privileged intents for monitoring members joining, roles editing, and role assignments + # These need to be enabled in the developer portal as well + intents = nextcord.Intents.default() + + # Required in order to read messages (eg. prefix commands) + intents.message_content = True + + # To enable the guilds privileged intent: + # intents.guilds = True + + # To enable the members privileged intent: + # intents.members = True + + bot = commands.Bot(intents=intents) + + # Get the modules of all cogs whose directory structure is ./cogs/ + for folder in os.listdir("cogs"): + bot.load_extension(f"cogs.{folder}") + + @bot.listen() + async def on_ready() -> None: + """When Discord is connected.""" + if bot.user is None: + print("Discord connection failed.") + return + print(f"{bot.user.name} has connected to Discord!") + + # Run Discord bot + bot.run(settings.params.discord_token) + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b228de4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,116 @@ +[project] +name = "off-cooldown-bot" +version = "0.1.0" +description = "" +authors = [{name="imcompiling", email=""}] +readme = "README.md" +dependencies = [ + "nextcord>=2.6.0", + "python-dotenv>=1.0.1", + "sqlmodel>=0.0.22", + "dataclass-wizard[yaml]>=0.22.3,<1.0.0", +] +requires-python = ">=3.12" + +[tool.uv] +dev-dependencies = ["ruff>=0.7.2"] + + +[tool.ruff] +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".ipynb_checkpoints", + ".mypy_cache", + ".nox", + ".pants.d", + ".pyenv", + ".pytest_cache", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "site-packages", + "venv", +] + +# Same as Black. +line-length = 120 +indent-width = 4 + +# Assume Python 3.8 +target-version = "py38" + +[tool.ruff.lint] +# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. +# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or +# McCabe complexity (`C901`) by default. +select = ["ALL"] +ignore = [ + "B008", # I build SlashOptions as arguments. + "COM812", + "COM819", + "D107", # don't want docstrings on init functions + "D203", + "D206", + "D212", + "D300", + "E111", + "E114", + "E117", + "ISC001", + "ISC002", + "PD011", # doesn't like me using '.values' on embeds.... + "Q000", + "Q001", + "Q002", + "Q003", + "W191", +] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.format] +# Like Black, use double quotes for strings. +quote-style = "double" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" + +# Enable auto-formatting of code examples in docstrings. Markdown, +# reStructuredText code/literal blocks and doctests are all supported. +# +# This is currently disabled by default, but it is planned for this +# to be opt-out in the future. +docstring-code-format = true + +# Set the line length limit used when formatting code snippets in +# docstrings. +# +# This only has an effect when the `docstring-code-format` setting is +# enabled. +docstring-code-line-length = "dynamic" diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..18c1a75 --- /dev/null +++ b/renovate.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "lockFileMaintenance": { + "automerge": true + }, + "major": { + "automerge": false, + "automergeType": "pr" + }, + "minor": { + "automerge": true, + "automergeType": "branch" + }, + "patch": { + "automerge": true, + "automergeType": "branch" + }, + "pin": { + "automerge": true, + "automergeType": "branch" + }, + "ignoreTests": true, + "dockerfile": { + "minor": { + "automerge": false, + "automergeType": "pr" + } + } +} \ No newline at end of file diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..5acc9c3 --- /dev/null +++ b/settings.py @@ -0,0 +1,28 @@ +"""File contains classes defining off-cooldown-bot settings structure.""" + +from dataclasses import dataclass + +from dataclass_wizard import YAMLWizard + +CONFIG_LOCATION = "conf/config.yaml" + + +@dataclass +class Params: + """Class defines start parameters that shouldn't be changed.""" + + discord_token: str + + +@dataclass +class Settings(YAMLWizard): + """Class defines all configs required for off-cooldown-bot.""" + + params: Params + + def save(self) -> None: + """Save settings to the yaml file.""" + self.to_yaml_file(CONFIG_LOCATION) + + +settings = Settings.from_yaml_file(CONFIG_LOCATION)