From afa46c4abfc73c8791742ed2ece886776823e8ab Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Sat, 23 Jul 2022 14:47:06 +0200 Subject: Add Sample Project With Boilerplate Adds a bare-bones discord.py bot using features from bot-core, to be used for quickly prototyping and testing out bot-core features. Signed-off-by: Hassan Abouelela --- dev/README.rst | 45 +++++++++++++++++++++++++++++++++++++++++++++ dev/bot/__init__.py | 24 ++++++++++++++++++++++++ dev/bot/__main__.py | 34 ++++++++++++++++++++++++++++++++++ dev/bot/cog.py | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 dev/README.rst create mode 100644 dev/bot/__init__.py create mode 100644 dev/bot/__main__.py create mode 100644 dev/bot/cog.py (limited to 'dev') diff --git a/dev/README.rst b/dev/README.rst new file mode 100644 index 00000000..b1535962 --- /dev/null +++ b/dev/README.rst @@ -0,0 +1,45 @@ +Local Development & Testing +=========================== + +To test your features locally, there are a few possible approaches: + +1. Install your local copy of botcore into a pre-existing project such as bot +2. Use the provided template from the :repo-file:`dev/bot ` folder + +See below for more info on both approaches. + +What's going to be common between them is you'll need to write code to test your feature. +This might mean adding new commands, modifying existing ones, changing utilities, etc. +The steps below should provide most of the groundwork you need, but the exact requirements will +vary by the feature you're working on. + + +Option 1 +-------- +1. Navigate to the project you want to install bot-core in, such as bot or sir-lancebot +2. Run ``pip install /path/to/botcore`` in the project's environment + + - The path provided to install should be the root directory of this project on your maching. + That is, the folder which contains the ``pyproject.toml`` file. + - Make sure to install in the correct environment. Most Python Discord projects use + poetry, so you can run ``poetry run pip install /path/to/botcore``. + +3. You can now use features from your local bot-core changes. + To load new changes, run the install command again. + + +Option 2 +-------- +1. Copy the :repo-file:`bot template folder ` to the root of your project. + This copy is going to be git-ignored, so you're free to modify it however you like. +2. Run the project + + - Locally: You can run it on your system using ``python -m bot`` + - Docker: You can run on docker using ``docker compose up -d bot``. + +3. You can now test your changes. You do not need to do anything to reinstall the + library if you modify your code. + +.. tip:: + The docker-compose included contains services from our other applications + to help you test out certain features. Use them as needed. diff --git a/dev/bot/__init__.py b/dev/bot/__init__.py new file mode 100644 index 00000000..71871209 --- /dev/null +++ b/dev/bot/__init__.py @@ -0,0 +1,24 @@ +import asyncio +import logging +import os +import sys + +import botcore + +if os.name == "nt": + # Change the event loop policy on Windows to avoid exceptions on exit + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + +# Some basic logging to get existing loggers to show +logging.getLogger().addHandler(logging.StreamHandler()) +logging.getLogger().setLevel(logging.DEBUG) +logging.getLogger("discord").setLevel(logging.ERROR) + + +class Bot(botcore.BotBase): + """Sample Bot implementation.""" + + async def setup_hook(self) -> None: + """Load extensions on startup.""" + await super().setup_hook() + asyncio.create_task(self.load_extensions(sys.modules[__name__])) diff --git a/dev/bot/__main__.py b/dev/bot/__main__.py new file mode 100644 index 00000000..00ebdefc --- /dev/null +++ b/dev/bot/__main__.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import aiohttp +import discord +import dotenv +from discord.ext import commands + +import botcore +from . import Bot + +dotenv.load_dotenv() +botcore.utils.apply_monkey_patches() + +roles = os.getenv("ALLOWED_ROLES") +roles = [int(role) for role in roles.split(",")] if roles else [] + +bot = Bot( + guild_id=int(os.getenv("GUILD_ID")), + http_session=None, # type: ignore # We need to instantiate the session in an async context + allowed_roles=roles, + command_prefix=commands.when_mentioned_or(os.getenv("PREFIX", "!")), + intents=discord.Intents.all(), + description="Bot-core test bot.", +) + + +async def main() -> None: + """Run the bot.""" + bot.http_session = aiohttp.ClientSession() + async with bot: + await bot.start(os.getenv("TOKEN")) + +asyncio.run(main()) diff --git a/dev/bot/cog.py b/dev/bot/cog.py new file mode 100644 index 00000000..7746c54e --- /dev/null +++ b/dev/bot/cog.py @@ -0,0 +1,33 @@ +from discord.ext import commands + +from . import Bot + + +class Cog(commands.Cog): + """A simple discord.py cog.""" + + def __init__(self, _bot: Bot): + self.bot = _bot + + @commands.Cog.listener() + async def on_ready(self) -> None: + """Print a message when the client (re)connects.""" + print("Client is ready.") + + @commands.command() + async def reload(self, ctx: commands.Context) -> None: + """Reload all available cogs.""" + message = await ctx.send(":hourglass_flowing_sand: Reloading") + for ext in list(self.bot.extensions): + await self.bot.reload_extension(ext) + await message.edit(content=":white_check_mark: Done") + + @commands.command() + async def ping(self, ctx: commands.Context) -> None: + """Test if the bot is online.""" + await ctx.send("We are live!") + + +async def setup(_bot: Bot) -> None: + """Install the cog.""" + await _bot.add_cog(Cog(_bot)) -- cgit v1.2.3 From 16804aab66588549da84ea503a7180fff2c54834 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Sat, 23 Jul 2022 14:49:08 +0200 Subject: Clean Up Docker Configuration Rewrites the docker configuration to better work for this project. A docker compose containing the dependencies from our other projects is also included to help aid development. Signed-off-by: Hassan Abouelela --- .dockerignore | 9 ++++++++ dev/Dockerfile | 13 ++++++----- dev/docker-compose.yaml | 27 ---------------------- docker-compose.yaml | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 33 deletions(-) create mode 100644 .dockerignore delete mode 100644 dev/docker-compose.yaml create mode 100644 docker-compose.yaml (limited to 'dev') diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..9fb3df72 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +* + +!botcore/ +!docs/ +!tests/ + +!pyproject.toml +!poetry.lock +!tox.ini diff --git a/dev/Dockerfile b/dev/Dockerfile index 738fc51a..e1d8eba3 100644 --- a/dev/Dockerfile +++ b/dev/Dockerfile @@ -4,18 +4,19 @@ FROM python:3.9-slim ENV PIP_NO_CACHE_DIR=false \ POETRY_VIRTUALENVS_CREATE=false -ENTRYPOINT ["/bin/bash"] -CMD ["./docker-entrypoint.sh"] - # Install poetry RUN pip install -U poetry -RUN mkdir bot -WORKDIR /bot +WORKDIR /app # Install project dependencies COPY pyproject.toml poetry.lock ./ -RUN poetry install --no-dev +RUN poetry install --no-root # Copy the source code in last to optimize rebuilding the image COPY . . +# Install again, this time with the root project +RUN poetry install + +ENTRYPOINT ["python"] +CMD ["-m", "bot"] diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml deleted file mode 100644 index e1dca5bb..00000000 --- a/dev/docker-compose.yaml +++ /dev/null @@ -1,27 +0,0 @@ -version: "3.9" - -x-logging: &logging - logging: - driver: "json-file" - options: - max-file: "5" - max-size: "10m" - -x-restart-policy: &restart_policy - restart: unless-stopped - -services: - botcore: - <<: *logging - <<: *restart_policy - build: - context: . - dockerfile: Dockerfile - container_name: botcore - - volumes: - - ./logs:/bot/logs - - .:/bot:ro - - env_file: - - .env diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..4b6468f1 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,61 @@ +# Modified version of python-discord/bot + +version: "3.8" + +x-restart-policy: &restart_policy + restart: unless-stopped + +services: + postgres: + << : *restart_policy + image: postgres:13-alpine + environment: + POSTGRES_DB: pysite + POSTGRES_PASSWORD: pysite + POSTGRES_USER: pysite + healthcheck: + test: ["CMD-SHELL", "pg_isready -U pysite"] + interval: 2s + timeout: 1s + retries: 5 + + redis: + << : *restart_policy + image: redis:5.0.9 + ports: + - "6379:6379" + + snekbox: + << : *restart_policy + image: ghcr.io/python-discord/snekbox:latest + init: true + ipc: none + ports: + - "8060:8060" + privileged: true + + web: + << : *restart_policy + image: ghcr.io/python-discord/site:latest + command: ["run", "--debug"] + ports: + - "8000:8000" + tty: true + environment: + DATABASE_URL: postgres://pysite:pysite@postgres:5432/pysite + METRICITY_DB_URL: postgres://pysite:pysite@postgres:5432/metricity + SECRET_KEY: suitable-for-development-only + STATIC_ROOT: /var/www/static + + bot: + << : *restart_policy + build: + context: . + dockerfile: dev/Dockerfile + volumes: + - .:/app:ro + tty: true + env_file: + - .env + environment: + BOT_API_KEY: badbot13m0n8f570f942013fc818f234916ca531 -- cgit v1.2.3 From 0e0b8933e4654bcfd80708c54a63c272bb5cbbd1 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Sat, 23 Jul 2022 17:00:16 +0200 Subject: Document Sample Project Environment Variables Co-authored-by: Chris Lovering Signed-off-by: Hassan Abouelela --- dev/README.rst | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'dev') diff --git a/dev/README.rst b/dev/README.rst index b1535962..afff6255 100644 --- a/dev/README.rst +++ b/dev/README.rst @@ -19,7 +19,7 @@ Option 1 1. Navigate to the project you want to install bot-core in, such as bot or sir-lancebot 2. Run ``pip install /path/to/botcore`` in the project's environment - - The path provided to install should be the root directory of this project on your maching. + - The path provided to install should be the root directory of this project on your machine. That is, the folder which contains the ``pyproject.toml`` file. - Make sure to install in the correct environment. Most Python Discord projects use poetry, so you can run ``poetry run pip install /path/to/botcore``. @@ -30,14 +30,22 @@ Option 1 Option 2 -------- -1. Copy the :repo-file:`bot template folder ` to the root of your project. +1. Copy the :repo-file:`bot template folder ` to the root of the bot-core project. This copy is going to be git-ignored, so you're free to modify it however you like. 2. Run the project - Locally: You can run it on your system using ``python -m bot`` - Docker: You can run on docker using ``docker compose up -d bot``. -3. You can now test your changes. You do not need to do anything to reinstall the +3. Configure the environment variables used by the program. + You can set them in an ``.env`` file in the project root directory. The variables are: + + - ``TOKEN`` (required): Discord bot token, with all intents enabled + - ``GUILD_ID`` (required): The guild the bot should monitor + - ``PREFIX``: The prefix to use for invoking bot commands. Defaults to mentions and ``!`` + - ``ALLOWED_ROLES``: A comma seperated list of role IDs which the bot is allowed to mention + +4. You can now test your changes. You do not need to do anything to reinstall the library if you modify your code. .. tip:: -- cgit v1.2.3