Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ repos:

# 6. Security Check
- repo: https://github.com/gitleaks/gitleaks
rev: v8.26.0 # Use the latest tag from the repo
rev: v8.27.0 # Use the latest tag from the repo
hooks:
- id: gitleaks

Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ RUN apt-get update && \
libpango1.0-0 \
libpangocairo-1.0-0 \
shared-mime-info \
tealdeer \
ffmpeg && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
Expand Down Expand Up @@ -113,11 +112,12 @@ ENV VIRTUAL_ENV=/app/.venv \
# Ensure ownership is set to nonroot
COPY --from=build --chown=nonroot:nonroot /app /app

# Create TLDR cache directory with proper permissions for the nonroot user
RUN mkdir -p /app/.cache/tldr && \
chown -R nonroot:nonroot /app/.cache

# Switch to the non-root user
USER nonroot

# tldr stuff
RUN tldr --update

ENTRYPOINT ["tux"]
CMD ["--prod", "start"]
186 changes: 93 additions & 93 deletions poetry.lock

Large diffs are not rendered by default.

38 changes: 28 additions & 10 deletions tux/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
self.setup_complete: bool = False
self.start_time: float | None = None
self.setup_task: asyncio.Task[None] | None = None
self.cog_watcher: Any = None
self.active_sentry_transactions: dict[int, Any] = {}

self._emoji_manager_initialized = False
Expand All @@ -77,6 +76,10 @@ async def setup(self) -> None:
span.set_tag("setup_phase", "database_connected")
await self._load_extensions()
span.set_tag("setup_phase", "extensions_loaded")
await self._load_cogs()
span.set_tag("setup_phase", "cogs_loaded")
await self._setup_hot_reload()
span.set_tag("setup_phase", "hot_reload_ready")
self._start_monitoring()
span.set_tag("setup_phase", "monitoring_started")

Expand Down Expand Up @@ -123,8 +126,6 @@ async def _load_extensions(self) -> None:
span.set_tag("jishaku.loaded", False)
span.set_data("error", str(e))

await self.load_cogs()

def _start_monitoring(self) -> None:
"""Start the background task monitoring loop."""
self._monitor_tasks_loop.start()
Expand Down Expand Up @@ -157,10 +158,6 @@ def _setup_callback(self, task: asyncio.Task[None]) -> None:

async def setup_hook(self) -> None:
"""discord.py setup_hook: one-time async setup before connecting to Discord."""
if not self._hot_reload_loaded and "tux.utils.hot_reload" not in self.extensions:
await self.load_extension("tux.utils.hot_reload")
self._hot_reload_loaded = True

if not self._emoji_manager_initialized:
await self.emoji_manager.init()
self._emoji_manager_initialized = True
Expand Down Expand Up @@ -190,6 +187,14 @@ async def _post_ready_startup(self):
},
)

async def on_ready(self) -> None:
"""Handle bot ready event."""
await self._wait_for_setup()

# Set bot status
activity = discord.Activity(type=discord.ActivityType.watching, name="for /help")
await self.change_presence(activity=activity, status=discord.Status.online)

async def on_disconnect(self) -> None:
"""Log and report when the bot disconnects from Discord."""
logger.warning("Bot has disconnected from Discord.")
Expand Down Expand Up @@ -335,7 +340,7 @@ async def shutdown(self) -> None:
await self._close_connections()
transaction.set_tag("connections_closed", True)

logger.info("Shutdown complete.")
logger.info("Bot shutdown complete.")

async def _handle_setup_task(self) -> None:
"""Handle setup task during shutdown."""
Expand Down Expand Up @@ -452,8 +457,8 @@ async def _close_connections(self) -> None:
if sentry_sdk.is_initialized():
sentry_sdk.capture_exception(e)

async def load_cogs(self) -> None:
"""Load cogs using CogLoader."""
async def _load_cogs(self) -> None:
"""Load bot cogs using CogLoader."""
with start_span("bot.load_cogs", "Loading all cogs") as span:
logger.info("Loading cogs...")

Expand Down Expand Up @@ -484,3 +489,16 @@ async def _log_startup_banner(self) -> None:
)

console.print(banner)

async def _setup_hot_reload(self) -> None:
"""Set up hot reload system after all cogs are loaded."""
if not self._hot_reload_loaded and "tux.utils.hot_reload" not in self.extensions:
with start_span("bot.setup_hot_reload", "Setting up hot reload system"):
try:
await self.load_extension("tux.utils.hot_reload")
self._hot_reload_loaded = True
logger.info("🔥 Hot reload system initialized")
except Exception as e:
logger.error(f"Failed to load hot reload extension: {e}")
if sentry_sdk.is_initialized():
sentry_sdk.capture_exception(e)
2 changes: 1 addition & 1 deletion tux/cogs/admin/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


class Dev(commands.Cog):
Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/admin/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from tux.bot import Tux
from tux.ui.embeds import EmbedCreator
from tux.utils import checks
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


def insert_returns(body: list[ast.stmt]) -> None:
Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/admin/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from tux.ui.embeds import EmbedCreator
from tux.utils import checks
from tux.utils.config import CONFIG
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage
from tux.wrappers.github import GithubService


Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/fun/rand.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from tux.bot import Tux
from tux.ui.embeds import EmbedCreator
from tux.utils.constants import CONST
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


class Random(commands.Cog):
Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/fun/xkcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from tux.bot import Tux
from tux.ui.buttons import XkcdButtons
from tux.ui.embeds import EmbedCreator
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage
from tux.wrappers import xkcd


Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/info/avatar.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from discord.ext import commands

from tux.bot import Tux
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage

client = httpx.AsyncClient()

Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/info/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from tux.bot import Tux
from tux.ui.embeds import EmbedCreator, EmbedType
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


class Info(commands.Cog):
Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/levels/level.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from tux.database.controllers import DatabaseController
from tux.ui.embeds import EmbedCreator, EmbedType
from tux.utils.config import CONFIG
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


class Level(commands.Cog):
Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/levels/levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from tux.database.controllers import DatabaseController
from tux.ui.embeds import EmbedCreator, EmbedType
from tux.utils import checks
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


class Levels(commands.Cog):
Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/ban.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import BanFlags, generate_usage
from tux.utils.flags import BanFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
from tux.ui.embeds import EmbedCreator, EmbedType
from tux.utils import checks
from tux.utils.constants import CONST
from tux.utils.flags import CaseModifyFlags, CasesViewFlags, generate_usage
from tux.utils.flags import CaseModifyFlags, CasesViewFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/jail.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import JailFlags, generate_usage
from tux.utils.flags import JailFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/kick.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import KickFlags, generate_usage
from tux.utils.flags import KickFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/pollban.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import PollBanFlags, generate_usage
from tux.utils.flags import PollBanFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/pollunban.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import PollUnbanFlags, generate_usage
from tux.utils.flags import PollUnbanFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/moderation/purge.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


class Purge(commands.Cog):
Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/snippetban.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import SnippetBanFlags, generate_usage
from tux.utils.flags import SnippetBanFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/snippetunban.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import SnippetUnbanFlags, generate_usage
from tux.utils.flags import SnippetUnbanFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/tempban.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from prisma.models import Case
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import TempBanFlags, generate_usage
from tux.utils.flags import TempBanFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
4 changes: 2 additions & 2 deletions tux/cogs/moderation/timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import TimeoutFlags, generate_usage
from tux.utils.functions import parse_time_string
from tux.utils.flags import TimeoutFlags
from tux.utils.functions import generate_usage, parse_time_string

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/unban.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from tux.bot import Tux
from tux.utils import checks
from tux.utils.constants import CONST
from tux.utils.flags import UnbanFlags, generate_usage
from tux.utils.flags import UnbanFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/unjail.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from prisma.models import Case
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import UnjailFlags, generate_usage
from tux.utils.flags import UnjailFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/untimeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import UntimeoutFlags, generate_usage
from tux.utils.flags import UntimeoutFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
3 changes: 2 additions & 1 deletion tux/cogs/moderation/warn.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from prisma.enums import CaseType
from tux.bot import Tux
from tux.utils import checks
from tux.utils.flags import WarnFlags, generate_usage
from tux.utils.flags import WarnFlags
from tux.utils.functions import generate_usage

from . import ModerationCogBase

Expand Down
4 changes: 4 additions & 0 deletions tux/cogs/services/gif_limiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ async def old_gif_remover(self) -> None:
else:
del self.recent_gifs_by_user[user_id]

async def cog_unload(self) -> None:
"""Cancel the background task when the cog is unloaded."""
self.old_gif_remover.cancel()


async def setup(bot: Tux) -> None:
await bot.add_cog(GifLimiter(bot))
2 changes: 1 addition & 1 deletion tux/cogs/services/starboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from tux.database.controllers import DatabaseController
from tux.ui.embeds import EmbedCreator, EmbedType
from tux.utils import checks
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage


class Starboard(commands.Cog):
Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/snippets/create_snippet.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from tux.bot import Tux
from tux.utils.constants import CONST
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage

from . import SnippetsBaseCog

Expand Down
2 changes: 1 addition & 1 deletion tux/cogs/snippets/delete_snippet.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from tux.bot import Tux
from tux.utils.constants import CONST
from tux.utils.flags import generate_usage
from tux.utils.functions import generate_usage

from . import SnippetsBaseCog

Expand Down
Loading