diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..c1a30eb8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +Dockerfile +config.py +.env +.vscode/ +.github/ +logs/ diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 00000000..eabf493d --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,21 @@ +name: Docker Image CI + +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Publish Image + uses: matootie/github-docker@v3.1.0 + with: + accessToken: ${{ secrets.GHCR_PAT }} + containerRegistry: true + tag: | + latest + ${{ github.sha }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..1c47d486 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.8 + +WORKDIR /app +COPY pyproject.toml poetry.lock ./ + +RUN pip install poetry +RUN poetry config virtualenvs.create false +RUN poetry install --no-dev + +COPY . . +RUN mkdir logs +CMD ["python", "docker-launcher.py"] diff --git a/bot.py b/bot.py index 5a2f12cb..701e4a3f 100644 --- a/bot.py +++ b/bot.py @@ -7,9 +7,11 @@ from discord.ext import commands import cogs -import config import helpers + +uvloop.install() + DEFAULT_DISABLED_MESSAGE = ( "The bot's currently disabled. It may be refreshing for some quick updates, or down for another reason. " "Try again later and check the #status channel in the official server for more details." @@ -36,10 +38,9 @@ def __init__(self, **kwargs): super().__init__(**kwargs, color=color) def __init__(self, **kwargs): - self.pipe = kwargs.pop("pipe") self.cluster_name = kwargs.pop("cluster_name") self.cluster_idx = kwargs.pop("cluster_idx") - self.config = config + self.config = kwargs.pop("config") self.ready = False self.menus = {} @@ -120,11 +121,6 @@ async def do_startup_tasks(self): async def on_ready(self): self.log.info(f"[Cluster#{self.cluster_name}] Ready called.") - try: - self.pipe.send(1) - self.pipe.close() - except OSError: - pass async def on_shard_ready(self, shard_id): self.log.info(f"[Cluster#{self.cluster_name}] Shard {shard_id} ready") @@ -164,6 +160,3 @@ async def reload_modules(self): self.reload_extension(f"cogs.{i}") await self.do_startup_tasks() - - -uvloop.install() diff --git a/cogs/__init__.py b/cogs/__init__.py index 9b058dc1..62e9b4c4 100644 --- a/cogs/__init__.py +++ b/cogs/__init__.py @@ -13,7 +13,6 @@ "noevent", "pokemon", "redis", - "sentry", "shop", "spawning", "sprites", diff --git a/cogs/bot.py b/cogs/bot.py index a52ba603..0780e3d3 100644 --- a/cogs/bot.py +++ b/cogs/bot.py @@ -30,7 +30,7 @@ def __init__(self, bot): self.post_count.start() self.update_status.start() - if self.bot.cluster_idx == 0: + if self.bot.cluster_idx == 0 and self.bot.config.DBL_TOKEN is not None: self.post_dbl.start() self.remind_votes.start() @@ -452,7 +452,7 @@ def cog_unload(self): self.post_count.cancel() self.update_status.cancel() - if self.bot.cluster_idx == 0: + if self.bot.cluster_idx == 0 and self.bot.config.DBL_TOKEN is not None: self.post_dbl.cancel() self.remind_votes.cancel() diff --git a/cogs/sentry.py b/cogs/sentry.py deleted file mode 100644 index 592f38b1..00000000 --- a/cogs/sentry.py +++ /dev/null @@ -1,39 +0,0 @@ -import sentry_sdk -from discord.ext import commands, flags - -from helpers import converters -from .bot import Blacklisted - - -class Sentry(commands.Cog): - """For sentry.""" - - def __init__(self, bot): - self.bot = bot - sentry_sdk.init(bot.config.SENTRY_URL, traces_sample_rate=1.0) - - @commands.Cog.listener() - async def on_command_error(self, ctx, error): - if not isinstance( - error, - ( - Blacklisted, - commands.CommandOnCooldown, - commands.MaxConcurrencyReached, - commands.DisabledCommand, - commands.ConversionError, - commands.CheckFailure, - commands.UserInputError, - commands.CommandNotFound, - flags.ArgumentParsingError, - ), - ): - sentry_sdk.capture_exception(error) - - @commands.Cog.listener() - async def on_error(self, error): - sentry_sdk.capture_exception(error) - - -def setup(bot): - bot.add_cog(Sentry(bot)) diff --git a/config.example.py b/config.example.py index ef509d42..03347dee 100644 --- a/config.example.py +++ b/config.example.py @@ -6,7 +6,6 @@ BOT_TOKEN = None SECRET_KEY = None REDIS_CONF = {} -SENTRY_URL = None # DBL DBL_TOKEN = None diff --git a/docker-launcher.py b/docker-launcher.py new file mode 100644 index 00000000..5784a5df --- /dev/null +++ b/docker-launcher.py @@ -0,0 +1,50 @@ +import os +from collections import namedtuple + +import discord + +from bot import ClusterBot + +Config = namedtuple( + "Config", + [ + "DATABASE_URI", + "DATABASE_NAME", + "BOT_TOKEN", + "SECRET_KEY", + "REDIS_CONF", + "DBL_TOKEN", + ], +) + +if __name__ == "__main__": + config = Config( + DATABASE_URI=os.environ["DATABASE_URI"], + DATABASE_NAME=os.environ["DATABASE_NAME"], + BOT_TOKEN=os.environ["BOT_TOKEN"], + SECRET_KEY=os.environ["SECRET_KEY"], + REDIS_CONF={ + "address": os.environ["REDIS_URI"], + "password": os.getenv("REDIS_PASSWORD"), + }, + DBL_TOKEN=os.getenv("DBL_TOKEN"), + ) + + num_shards = os.getenv("NUM_SHARDS", 1) + num_clusters = os.getenv("NUM_CLUSTERS", 1) + cluster_idx = os.getenv("CLUSTER_IDX", 0) + + shard_ids = list(range(cluster_idx, num_shards, num_clusters)) + + ClusterBot( + token=config.BOT_TOKEN, + shard_ids=shard_ids, + shard_count=num_shards, + cluster_name=str(cluster_idx), + cluster_idx=cluster_idx, + case_insensitive=True, + fetch_offline_members=False, + allowed_mentions=discord.AllowedMentions(everyone=False, roles=False), + intents=discord.Intents.default(), + config=config, + ) diff --git a/launcher.py b/launcher.py index 9ebbaa5e..3947a5a0 100644 --- a/launcher.py +++ b/launcher.py @@ -163,6 +163,7 @@ def __init__(self, launcher, name, shard_ids, max_shards): fetch_offline_members=False, allowed_mentions=discord.AllowedMentions(everyone=False, roles=False), intents=intents, + config=config, ) self.name = name self.log = logging.getLogger(f"Cluster#{name}") @@ -194,19 +195,12 @@ async def start(self, *, force=False): self.process.terminate() self.process.close() - stdout, stdin = multiprocessing.Pipe() - kw = self.kwargs - kw["pipe"] = stdin self.process = multiprocessing.Process( - target=ClusterBot, kwargs=kw, daemon=True + target=ClusterBot, kwargs=self.kwargs, daemon=True ) self.process.start() self.log.info(f"Process started with PID {self.process.pid}") - if await self.launcher.loop.run_in_executor(None, stdout.recv) == 1: - stdout.close() - self.log.info("Process started successfully") - return True def stop(self, sign=signal.SIGINT): diff --git a/poetry.lock b/poetry.lock index 98b5148d..2e90ff33 100644 --- a/poetry.lock +++ b/poetry.lock @@ -189,7 +189,7 @@ resolved_reference = "458ae5a1ce8436821667dfeb471061f78c5adfa0" [[package]] name = "discord-ext-menus" -version = "1.0.0a27+g6f2b873" +version = "1.0.0a29+g4429b56" description = "An extension module to make reaction based menus with discord.py" category = "main" optional = false @@ -203,7 +203,7 @@ develop = false type = "git" url = "https://github.com/Rapptz/discord-ext-menus.git" reference = "master" -resolved_reference = "6f2b873bf0d28903eb752aa1166b3aac26dc9007" +resolved_reference = "4429b564fd8f031deaccd60caa5be7320e248816" [[package]] name = "discord-flags" @@ -607,34 +607,6 @@ urllib3 = ">=1.21.1,<1.27" security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] -[[package]] -name = "sentry-sdk" -version = "0.19.5" -description = "Python client for Sentry (https://sentry.io)" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.10.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -beam = ["apache-beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -chalice = ["chalice (>=1.16.0)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -flask = ["flask (>=0.11)", "blinker (>=1.1)"] -pure_eval = ["pure-eval", "executing", "asttokens"] -pyspark = ["pyspark (>=2.4.4)"] -rq = ["rq (>=0.6)"] -sanic = ["sanic (>=0.8)"] -sqlalchemy = ["sqlalchemy (>=1.2)"] -tornado = ["tornado (>=5)"] - [[package]] name = "six" version = "1.15.0" @@ -773,7 +745,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "54df022377850497ea1d149f169e0fa657e0febe0561f5b5402d879f57b3629f" +content-hash = "a74ca313f510ba1c7c23f94e2a1226222100602fb1864b9dbc18144a35fcb809" [metadata.files] aiofiles = [ @@ -1212,10 +1184,6 @@ requests = [ {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, ] -sentry-sdk = [ - {file = "sentry-sdk-0.19.5.tar.gz", hash = "sha256:737a094e49a529dd0fdcaafa9e97cf7c3d5eb964bd229821d640bc77f3502b3f"}, - {file = "sentry_sdk-0.19.5-py2.py3-none-any.whl", hash = "sha256:0a711ec952441c2ec89b8f5d226c33bc697914f46e876b44a4edd3e7864cf4d0"}, -] six = [ {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, diff --git a/pyproject.toml b/pyproject.toml index 0c680a5f..b494f51e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,6 @@ stripe = "^2.51.0" durations_nlp = "^1.0.1" aioredis = "^1.3.1" uvloop = "^0.14.0" -sentry-sdk = "^0.19.2" Quart-CORS = "^0.3.0" discord-ext-menus = {git = "https://github.com/Rapptz/discord-ext-menus.git"} aioredis-lock = "^0.1.0"