Skip to content

Releases: TheHolyOneZ/discord-bot-framework

discord-bot-framework (1.9.3.0)

27 Mar 18:00
525f09d

Choose a tag to compare

[Feature] — 2026-03-27 v1.9.3.0

3 new framework cogs — infrastructure-level additions (no bot-feature commands)


cogs/db_migrations.py (NEW)

Database Migration System — versioned, sequential schema migrations for the framework.

  • Migration files live in ./migrations/ as numbered Python files (001_name.py, 002_name.py, ...)
  • Each file defines async def up(db) and a description string
  • Tracking table _schema_migrations in the main database records applied migrations
  • Migrations run automatically on startup in order; execution stops on first failure (sequential guarantee)
  • Failed migrations are recorded with success = 0 so /fw_migrate can retry after a fix
  • /fw_migrations — show migration status: applied, pending, failed counts with details
  • /fw_migrate — manually re-run pending migrations (e.g. after fixing a failed one)
  • Ships with migrations/001_add_scheduled_tasks.py which creates the scheduled_tasks table for the Task Scheduler

cogs/task_scheduler.py (NEW)

Persistent Task Scheduler — cron-like scheduling that survives bot restarts.

  • Jobs stored in scheduled_tasks table (created by migration 001)
  • Standard 5-field cron expressions: minute hour day month weekday
  • CronParser class: validates, matches, calculates next run, and generates human-readable descriptions
  • Scheduler tick runs every 30 seconds, checks all enabled tasks against current time
  • Deduplication: skips tasks already run within the same minute window
  • Three task types:
    • message — send a message (with optional embed) to a target channel
    • hook — emit a framework event hook via bot.emit_hook()
    • log — write a log entry at a configurable level
  • max_runs support: auto-disables task after N executions
  • Slash command group /schedule:
    • create — create a new task (with cron validation, channel picker, type selector)
    • list — list all tasks for the current guild
    • delete — delete a task (creator or bot owner)
    • toggle — enable/disable a task
    • info — detailed view of a single task
  • Public Python API: create_task_programmatic() for other cogs/extensions to register scheduled work
  • Permission: bot owner or guild owner can create; creators can manage their own tasks

cogs/config_validator.py (NEW)

Config Schema Validator — validates config.json against a defined schema on boot.

  • Full schema definition covering all framework config keys: prefix, status, database, logging, extensions, cooldowns, command_permissions, slash_limiter, framework
  • Validates: types, required keys, numeric min/max bounds, string length, enum choices, nested objects
  • Unknown keys produce warnings (not errors) — user extension keys are allowed
  • Keys starting with _comment are silently skipped
  • Runs validation on cog_load and logs all errors/warnings at appropriate levels
  • /fw_config_validate — run validation on-demand and see errors/warnings in an embed
  • /fw_config_schema — show the full expected schema as a YAML-like reference
  • register_extension_schema(name, schema) — extensions can register their own config keys for validation
  • unregister_extension_schema(name) — remove an extension's schema on cog unload
  • _get_merged_schema() merges framework + extension schemas; /fw_config_validate and /fw_config_schema use merged schema

Reusability fixes (Same Release)

cogs/db_migrations.py

  • [FIX] _failed list was never cleared between /fw_migrate calls — old failures accumulated across re-runs. Added self._failed.clear() at top of _run_pending_migrations
  • [API] Added is_migration_applied(number) — extensions can check if a specific migration was applied before using its tables
  • [API] Added applied_migrations / failed_migrations read-only properties

cogs/task_scheduler.py

  • [FIX] _load_tasks only loaded enabled = 1 tasks from DB. After a restart, disabled tasks vanished from the cache — /schedule list wouldn't show them, and /schedule toggle couldn't re-enable them. Changed to SELECT * FROM scheduled_tasks (loads all tasks)
  • [FIX] SQLite returns enabled as int 1/0, but toggle logic used Python not on it. Added bool normalization on load: task["enabled"] = bool(task.get("enabled", 1))
  • [FIX] Removed unused import re

cogs/config_validator.py

  • [FIX] No way for extensions to register their own config keys — all extension keys flagged as "Unknown key" warnings. Added register_extension_schema() / unregister_extension_schema() API. Extensions call these from cog_load/cog_unload
  • [FIX] /fw_config_validate and /fw_config_schema used hardcoded CONFIG_SCHEMA — now use _get_merged_schema() which includes extension-registered keys

atomic_file_system.py

  • Added enable_db_migrations, enable_task_scheduler, enable_config_validator to the default config framework block

main.py

  • Added db_migrations, task_scheduler, config_validator to load_order (loaded after shard_manager)
  • Added fw_migrations, fw_migrate, fw_config_validate, fw_config_schema to BOT_OWNER_ONLY_COMMANDS

[KNOWN — UPCOMING v1.9.3.1]

  • GeminiServiceHelper collect_dashboard_data() security issue: still pending (tracked separately)

discord-bot-framework (1.9.2.0)

25 Mar 19:36
06a8979

Choose a tag to compare

[Fix] — 2026-03-07 -> 2026-03-25 v1.9.1.0 → v1.9.2.0

41 confirmed bug fixes across 13 cogs


cogs/framework_diagnostics.py

  • [FIX] generate_diagnostics() accessed self.bot.bot_owner_id, self.bot.extension_load_times, self.bot.db.conn, self.bot.db.base_path, and self.bot.config without guards. Any one missing attribute raised AttributeError caught generically, returning None with no useful detail. All replaced with getattr(...) guards.
  • [FIX] loop_lag_monitor ran every 1 second (86,400 scheduling events/day). Changed to @tasks.loop(seconds=5) and expected_interval = 5.0.
  • [FIX] _send_alert called .send() unconditionally on any channel type. If the configured channel was a voice, stage, or forum channel, send() raised HTTPException caught generically. Added isinstance(channel, discord.TextChannel) check.
  • [FIX] Write-failure alert in generate_diagnostics() fired on every failure with no debounce. Added _last_write_alert_time — alert only fires if >300 seconds since last write alert.

cogs/shard_monitor.py

  • [FIX] save_metrics and _save_alert_config used synchronous open() + json.dump() directly on the event loop, blocking all coroutines during disk writes. Both now use await asyncio.to_thread(...). _save_alert_config is now async def.
  • [FIX] ShardMetrics.is_healthy() hardcoded consecutive_failures >= 3 regardless of the configurable alert_threshold on ShardMonitor. Added threshold: int = 3 parameter. health_check and _build_health_embed now pass self.alert_threshold.

cogs/shard_manager.py

  • [FIX] _seen_nonces was a set trimmed via set(list(...)[half:]set has no ordering so the "keep newest half" logic randomly discarded nonces, potentially re-allowing replay of recently seen ones. Replaced with collections.deque(maxlen=10000) which auto-drops the oldest.
  • [FIX] sync_stats loop had no try/except. An unhandled exception silently killed the task permanently with no alert. Wrapped body in try/except Exception as e: logger.error(...).

cogs/event_hooks.py

  • [FIX] Queue-full fallback in emit_hook called await self._hook_queue.put(hook_data) with no timeout on a still-full queue, suspending the emitter indefinitely. The except asyncio.QueueFull below it was dead code since queue.put() never raises QueueFull. Replaced fallback with put_nowait() inside try/except asyncio.QueueFull.
  • [FIX] hook_id used callback.__name__ — two callbacks in different cogs with the same function name shared one hook_id, causing one to overwrite the other. Changed to callback.__module__.callback.__qualname__ for guaranteed uniqueness.
  • [FIX] disable_hook() checked if hook_id not in self.hooks where self.hooks is keyed by event_name (e.g. "bot_ready"), not hook_id (e.g. "bot_ready:module.func"). This check always evaluated True, making disable_hook always return False/eh_disable was completely broken (regression from v1.9.1.0). Now iterates hooks to find a matching hook_id.
  • [FIX] cog_unload called self._worker_task.cancel() but did not await it, leaving cleanup from CancelledError unguaranteed. Changed cog_unload to async def and added await self._worker_task in try/except asyncio.CancelledError.

cogs/plugin_registry.py

  • [FIX] PluginListView had no on_timeout — after the 120s timeout the cog reference stayed alive and buttons remained visually enabled. Added async def on_timeout that clears self._cog and disables all buttons.

cogs/slash_command_limiter.py

  • [FIX] Debug log used logging.FileHandler with no rotation or size cap, growing indefinitely. Replaced with logging.handlers.RotatingFileHandler(maxBytes=5MB, backupCount=2).
  • [FIX] /slashlimit had no access control — any guild member could enumerate all blocked/converted command names. Added @commands.is_owner().

cogs/GeminiService.py

  • [FIX] No cog_load validation for GEMINI_API_KEY — if the key was missing, the cog loaded silently and only failed at first invocation with a confusing error. Added cog_load that logs CRITICAL if the key is absent.
  • [FIX] No cog_unload — hot-reloading left _user_cooldowns and _ai_cache populated with stale state from the previous config. Added cog_unload that clears both dicts.

cogs/GeminiServiceHelper.py

  • [FIX] Sessions were only written to disk synchronously on each message send. A crash between sends lost the latest entry. Added a @tasks.loop(seconds=60) auto-save task with a dirty flag — sessions are now also persisted periodically as a safety net.

cogs/live_monitor.py + ReUseInfos/live_monitor_helper.py

  • [FIX] _load_config caught JSON parse errors with a bare except: pass and returned defaults silently. Operators had no indication config was reset. Changed to except Exception as e: logger.error(...) including the config file path and exception detail.

cogs/EventHooksCreater.py

  • [FIX] _cooldowns dict accumulated one entry per (hook_id, user_id) pair seen and grew indefinitely. Added eviction in _check_cooldown — entries older than cooldown_seconds * 2 are pruned on each cooldown check.
  • [FIX] _user_message_counts grew indefinitely (one entry per unique user ever seen). Added a cleanup step in analytics_task (runs every 5 min) that caps the dict at 5,000 users by count.
  • [FIX] _execute_webhook created a new aiohttp.ClientSession per invocation, defeating connection pooling. Added self._http_session created in cog_load and closed in cog_unload. _execute_webhook now reuses the shared session. Changed cog_unload to async def.

cogs/event_hooks.py

  • [FIX] _add_to_history per-event pruning used h not in events_to_remove where events_to_remove is a list of dicts — dict equality is O(n), making the pruning O(n²). Replaced with {id(h) for h in ...} set for O(n) membership checks.

cogs/shard_monitor.py

  • [FIX] is_bot_owner() returned False for the real bot owner when BOT_OWNER_ID was 0 (env var not set), locking the owner out of all commands. Updated predicate to try BOT_OWNER_ID first, then fall back to application_info().owner.id.

cogs/shard_manager.py

  • [FIX] Default SHARD_IPC_SECRET = "change_me_please" only logged a WARNING and continued loading, allowing IPC to run with a known-public secret. Escalated to CRITICAL log and early return — the cog will not load at all until a real secret is configured.

cogs/GeminiService.py (MEDIUM batch)

  • [FIX] Cache lookup happened after PluginRegistry.get_all_plugins(), generate_diagnostics(), etc. were already called — cache hits still paid the full I/O cost. Moved cache check to before context-gathering; a cache hit now skips all framework calls and returns immediately.
  • [FIX] _user_cooldowns and _ai_cache grew without bound. Added @tasks.loop(minutes=5) _cleanup_cache_task that evicts cooldown entries older than COOLDOWN_SECONDS * 2 and cache entries older than CACHE_TTL.
  • [FIX] _active_requests was an unprotected plain integer. Replaced with asyncio.Semaphore(_MAX_CONCURRENT). Guard uses semaphore.locked(), acquire/release in finally.

cogs/GeminiServiceHelper.py (MEDIUM batch)

  • [FIX] _save_sessions called Path.write_text() synchronously inside an async method, blocking the event loop on large session files. Wrapped with await asyncio.to_thread(lambda: ...).
  • [FIX] _gather_tool_context stopped at the first matching cog name with a break, silently ignoring further cog mentions in the same message. Removed break — all matching cog names are now collected.

cogs/EventHooksCreater.py (MEDIUM batch)

  • [FIX] _execute_webhook passed any user-supplied URL directly to aiohttp.ClientSession.post() with no validation, enabling SSRF to internal services. Added URL prefix check — only discord.com, discordapp.com, ptb.discord.com, and canary.discord.com webhook URLs are permitted.

cogs/plugin_registry.py (MEDIUM batch)

  • [FIX] check_dependencies operator extraction used ">=" if ">=" in required_version else "==", silently mapping >1.0.0 or <=2.0.0 to ==. Replaced with re.match(r'([><=!]+)', ...) for correct extraction of any operator.
  • [FIX] save_registry failures were logged but had no operator alert. Added _save_failure_count counter — after 3 consecutive failures _send_alert fires a critical message warning that disk state is stale.

cogs/backup_restore.py (MEDIUM batch)

  • [FIX] _download_image_b64 created a new aiohttp.ClientSession per image. A backup with 50 emojis + stickers + icon + banner opened 57+ sessions sequentially. capture() now creates one shared session and passes it to all _download_image_b64 calls via a new session parameter.
  • [FIX] Banner was captured as base64 during backup but _do_restore never applied it. Added banner restore after icon restore in the server_settings block: await guild.edit(banner=banner_bytes, ...).

cogs/event_hooks.py (MEDIUM batch)

  • [FIX] alert_channel_id was in-memory only — lost on every restart, leaving the alert system permanently silent after a reload. Added _load_config/_save_config backed by ./data/event_hooks_config.json; alert_channel_id is persisted on every /eh_alert_channel call.
  • [FIX] _worker_restart_count never reset — a bot that crashed twice a year could permanently exhaust its 10-restart budget. _restart_worker now resets the counter to 0 if the worker ran stably for >1 hour before the current crash.

cogs/Guild_settings.py (MEDIUM batch)

  • [FIX] get_guild_mention_prefix_enabled, get_guild_prefix, and set_guild_mention_prefix_enabled were called without try/except. A DB failure propagated to the global error handler with no user-friendly context. All DB calls now ...
Read more

discord-bot-framework (1.9.1.0)

04 Mar 17:54
e6318b5

Choose a tag to compare

[Fix] — 2026-03-04 — v1.9.0.0 → v1.9.1.0

14 confirmed bug fixes across 11 cogs


cogs/GeminiService.py

  • [FIX] Cooldown stamp _user_cooldowns[user.id] = now was written before the _active_requests >= _MAX_CONCURRENT check — a user rejected for capacity silently consumed their 15-second cooldown slot. Stamp now written only after all guards pass.

cogs/GeminiServiceHelper.py

  • [FIX] _cmd_update_config guard was if owner_id is not None and requester_id != owner_id — if application_info() raised an exception, owner_id stayed None and the guard was vacuously false, allowing any caller to update config. Guard inverted to if owner_id is None or requester_id != owner_id (deny-by-default).
  • [KNOWN — UPCOMING] Security: collect_dashboard_data() iterates all sessions and includes every user's aes_key and full history in the polled JSON. Any authenticated dashboard user can currently read other users' encryption keys. Fix requires live_monitor to pass the authenticated dashboard user's Discord ID at data-collection time (currently hardcoded None). Will be addressed in v1.9.2.0.

cogs/live_monitor.py

  • [FIX] on_command listener was defined twice in the same class. The duplicate on_command + on_command_error pair caused every prefix/hybrid command to be double-counted in _command_usage and logged twice in the dashboard event log. Duplicate block removed from both files.
  • [FIX] cog_unload was deleting plugin_registry.json on every hot-reload, destroying PluginRegistry's persisted data owned by another cog. Deletion removed from both files — Live Monitor only cleans up its own files.
  • [FIX] asyncio.get_event_loop() (deprecated Python 3.10+) replaced with asyncio.get_running_loop() in live_monitor_helper.py (_get_process, _collect_monitor_data).

cogs/EventHooksCreater.py

  • [FIX] or True on the implemented status check made the "⚠️" branch permanently unreachable — all templates always showed "✅" regardless of implementation status. Removed or True.

cogs/plugin_registry.py

  • [FIX] self.bot.extension_load_times[name] was accessed without a hasattr guard — raises AttributeError if the bot doesn't expose the attribute, silently aborting register_plugin. Replaced with getattr(self.bot, 'extension_load_times', {}).get(name, 0.0).
  • [FIX] _auto_scan_extension only called cog.get_commands(), missing all pure @app_commands.command slash commands. Added cog.get_app_commands() scan — /pr_info and /pr_list now report accurate command counts for GeminiService, EventHooksCreater, etc.

cogs/backup_restore.py

  • [FIX] BackupSnapshot version string hardcoded as "2.1.0" while the cog is v2.2.0 — new snapshots were mis-tagged. Updated to "2.2.0".

cogs/framework_diagnostics.py

  • [FIX] on_app_command_error listener added — slash command errors (the majority of commands in this framework) were never tracked in _error_history or health_metrics["last_error"]. Rolling error rate was systematically undercounted.
  • [FIX] asyncio.get_event_loop() (deprecated Python 3.10+) replaced with asyncio.get_running_loop() in _get_process and _get_system_metrics.

cogs/event_hooks.py

  • [FIX] disable_hook() unconditionally added any string to disabled_hooks and returned True — a typo in a hook ID silently "succeeded", making the "hook not found" branch in commands dead code. Now returns False for unknown hook IDs.

cogs/shard_monitor.py

  • [FIX] Health alert had no debounce — _send_health_alert fired on every 60-second tick while a shard stayed unhealthy, flooding the alert channel. Added _last_alert_time with a 5-minute cooldown per alert.

cogs/shard_manager.py

  • [FIX] _heartbeat_loop captured guild_count at connect() time and sent the stale frozen value on every heartbeat. Now reads len(self.bot.guilds) live on each tick.

cogs/Guild_settings.py

  • [FIX] action parameter typed as str — Discord showed a free-text field with no hints. Changed to Literal["enable", "disable", "status"] so Discord renders a dropdown in slash mode.

discord-bot-framework (1.9.0.0)

01 Mar 17:55
d9c5620

Choose a tag to compare

[Add] — 2026-03-01 — v1.9.0.0


cogs/GeminiServiceHelper.pyFully new cog

A dedicated AI assistant embedded directly inside the Live Monitor web dashboard. No slash commands — entirely dashboard-native, accessed from the new AI Assistant tab (tab 21).

Encryption

  • [ADD] AES-256-CBC end-to-end encryption: server-side via Python cryptography library, client-side via native Web Crypto API (crypto.subtle) — no external CDN, no CSP issues
  • [ADD] Per-user AES keys stored server-side; new users bootstrap a key in localStorage which is registered on first send
  • [ADD] Encrypted session history persisted to ./data/gemini_dashboard_sessions.json

Context tools (auto-injected based on message keywords)

  • [ADD] Framework Info — live bot stats (version, guild count, loaded cogs)
  • [ADD] Extension/Cog Info — docstring and slash commands for any loaded cog, detected by cog name appearing in the message
  • [ADD] File Structure — lists root .py files, cogs/, data/, and notable project files
  • [ADD] README Search — full hierarchical breadcrumb parse of README.md; up to 3,000 chars from the top 4 scoring sections
  • [ADD] Capabilities — triggered by "what can you do"-style queries; lists all tools and what the AI cannot do
  • [ADD] File Reading — sandboxed reader; allowed: root *.py, cogs/*.py, data/* (direct children only); always blocked: .env, gemini_dashboard_sessions.json, live monitor config JSON files

Attach File (Option C)

  • [ADD] Attach File toolbar button opens an inline row with a live-filter autocomplete dropdown above the input
  • [ADD] File list pre-fetched from Python on every data poll (available_files in collect_dashboard_data) — shows only allowed paths, no blocked files
  • [ADD] Multiple files: each confirmed file becomes a removable chip tag; up to 3 files read per message and injected as separate [Tool Context — File: …] blocks
  • [ADD] Auto-detect fallback: if no explicit attachment, the message text is scanned for filenames with known extensions and the file is read automatically

Chat UX

  • [ADD] Optimistic message bubbles — user message appears immediately; removed if a confirmed user message arrives from the server
  • [ADD] Smart scroll — only auto-scrolls if user was within 120 px of the bottom; never interrupts reading older history
  • [ADD] Typing indicator — persists until the AI response arrives in history (not just on POST ACK)
  • [ADD] Lock + Cancel — send button and textarea disabled while waiting for response; Cancel button removes the optimistic bubble and unlocks input
  • [ADD] Client-side 15-second rate limit gate with countdown feedback
  • [ADD] Markdown rendering — fenced code blocks, headers, bold, italic, inline code, lists, HR — XSS-safe via gaiEsc(), no external dependencies
  • [ADD] Capabilities popup — animated glassmorphism modal from a toolbar button listing what the AI can and cannot do

Configuration & permissions

  • [ADD] Config drawer (owner-only): live model and system prompt override without restart; respects GEMINI_MODEL env var (default gemini-2.5-flash-lite)
  • [ADD] 4 dashboard permission flags: view_gemini_chat, action_gemini_send, action_gemini_clear_history, action_gemini_config
  • [ADD] Requires pip install cryptography

cogs/live_monitor.py + ReUseInfos/live_monitor_helper.py — GeminiServiceHelper integration

  • [ADD] 'gemini' added to $validPackages in _generate_receive_php() — without this monitor_data_gemini.json returned 404
  • [ADD] GeminiServiceHelper.collect_dashboard_data(discord_id) called inside _collect_monitor_data() and merged under key "gemini" in the polled JSON
  • [ADD] AI Assistant tab (tab 21) injected into generated index.php via LiveMonitor._get_gemini_tab_html() — HTML/CSS/JS fully embedded in live_monitor_helper.py for self-contained CGI-bin deployment; GeminiServiceHelper.get_tab_html() removed (dead code)
  • [ADD] geminiInit(monitorData, userId) wired into the dashboard's existing 2-second data-poll cycle
  • [ADD] handle_command() dispatch registered for gemini_send_message, gemini_clear_history, gemini_update_config

[Update] — 2026-02-28 — v1.8.0.0 → v1.9.0.0


cogs/EventHooksCreater.py — Full overhaul

Missing template handlers implemented

  • [ADD] leveling_system — XP awarded per message with per-user cooldown, level calculation, level-up announcements to configured channel, role rewards at configured level thresholds; XP data persisted in memory and saved via the batch save task
  • [ADD] scheduled_announcement — recurring message/embed sent to a configured channel at a configurable interval (hours); implemented as a per-hook asyncio.Task started on registration and cancelled on unregister/delete/disable
  • [ADD] ticket_system — creates a private text channel per user in a configured category when they react with a configured emoji on a configured message; support role granted access automatically; channel named via template; reaction removed after ticket creation to keep the message clean
  • [ADD] voice_activity_tracker — logs join, leave, and mute/unmute events to a configured log channel with embed; each event type independently togglable
  • [ADD] dynamic_voice_channels — creates a temporary voice channel in a configured category when a user joins a designated trigger channel, moves the user into it, and deletes it automatically when it becomes empty; channel named via template; active temp channels tracked in memory

Dead code wired in

  • [FIX] _execute_actions is now called by all new template handlers — the generic action pipeline (send_message, add_role, remove_role, timeout, send_dm, webhook, create_role, delay, trigger_hook) is no longer dead code
  • [FIX] AdvancedConditionEngine.evaluate() is now called at the top of every handler before executing — hooks with conditions configured (time_range, day_of_week, role_hierarchy, message_count, user_age, custom_variable) now actually respect them

Security

  • [FIX] eval() in _format_message replaced with a safe AST-based math evaluator — only numeric constants and basic operators (+, -, *, /) are permitted; no code execution possible

Reliability

  • [FIX] Listener accumulation fixed — _registered_hook_ids: set tracks which hooks have active listeners; _register_hook skips registration if the hook is already registered, preventing duplicate listeners from piling up on restart or re-register
  • [FIX] I/O on every execution removed — _save_created_hooks() is no longer called after every hook fires; execution_count and error_count are updated in memory and flushed by a new _auto_save background task (60-second interval, dirty flag); the analytics task already saves analytics every 5 minutes
  • [FIX] Channel and role ID validation at registration time — invalid IDs (non-integer, channel/role not found in guild) now return a clear error from create_hook() instead of failing silently at runtime

New Discord commands (Bot Owner / Administrator)

  • [ADD] /hooks list [page] — paginated list of all hooks in the current guild with template name, status (enabled/disabled), execution count, error count
  • [ADD] /hooks info <hook_id> — detailed embed showing all params, conditions, execution stats, and last execution time for a specific hook
  • [ADD] /hooks delete <hook_id> — delete a hook with confirmation; owner-only
  • [ADD] /hooks toggle <hook_id> — enable or disable a hook
  • [ADD] /hooks create <template_id> — shows required and optional parameters for the template and creates the hook with provided params via command options

cogs/plugin_registry.py — Upgrade

Auto-scan completeness

  • [ADD] provides_hooks and listens_to_hooks are now populated during auto-scan by reading __provides_hooks__ and __listens_to_hooks__ module-level attributes from extension modules

Persistence

  • [FIX] Alert channel now persisted to ./data/plugin_registry_config.json — survives restarts
  • [FIX] enforce_dependencies and enforce_conflicts states now persisted to the same config file — no longer reset to True on restart after being disabled via /pr_enforce

Real enforcement

  • [FIX] Enforcement is no longer advisory only — when enforce_dependencies=True and a plugin has missing or incompatible dependencies, register_plugin() now refuses to register it and returns an error; same for conflict enforcement

UX

  • [FIX] /pr_list now uses paginated embeds (10 plugins per page with Prev/Next buttons) — no longer hits Discord's 25-field embed limit with large plugin sets

Resilience

  • [FIX] extension_loaded / extension_unloaded hook registration no longer depends on EventHooks being loaded — fallback uses direct bot.add_listener() on on_ready if EventHooks is absent

discord-bot-framework (1.8.0.0)

28 Feb 17:58
0c6c6e2

Choose a tag to compare

[Update] — 2026-02-28 — v1.7.2.2 → v1.8.0.0

cogs/framework_diagnostics.py

Persistence

  • [FIX] Alert channel now persisted to ./data/framework_diagnostics_config.json — survives bot restarts, no longer needs to be re-set every time

Reliability

  • [FIX] bot.metrics is no longer a hard dependency — all accesses wrapped with getattr fallbacks; cog loads and runs without crashing even if the main bot doesn't implement bot.metrics
  • [FIX] Loop lag threshold is now configurable via FW_LOOP_LAG_THRESHOLD_MS env var (default: 500ms) — no longer hardcoded and no longer stored confusingly as seconds while being compared as ms

Accuracy

  • [FIX] Loop lag now uses a rolling average of the last 10 readings instead of the raw instantaneous value — eliminates false alerts from single-tick jitter
  • [FIX] Error rate now computed over a rolling 1-hour window (delta of 12 × 5-minute snapshots) instead of lifetime totals — an early error burst no longer permanently inflates the rate; /fw_diagnostics shows (rolling 1h) or (lifetime) to indicate which mode is active

History & Observability

  • [ADD] Health check history: last 48 entries (4 hours) kept in memory and persisted to ./data/framework_health_history.json after each health_monitor run
  • [ADD] Error history: last 20 command errors kept in a deque; on_command_error now appends each error with timestamp and command name instead of overwriting a single field
  • [ADD] /fw_history [entries] command — shows last N (1–20) health check snapshots with timestamp, status, error rate, and loop lag per entry
  • [ADD] /fw_errors command — shows the last 20 command errors with timestamp, command name, and error message

Embed improvements

  • [CHG] /fw_diagnostics health field now shows rolling window note, recent error count, and (avg 10s) annotation on loop lag

cogs/GeminiService.py

Security

  • [FIX] file action is now restricted to bot owner only — previously any Discord user could read .env, config.json, database files, and any other file in the bot's working directory
  • [FIX] permission action now accurately describes the real access model (file and permission = bot owner only; all other actions = everyone) instead of incorrectly stating all actions are public

Fixes

  • [FIX] Per-user cooldown (15 s) and global max concurrency (3) are now enforced via a manual _user_cooldowns dict and _active_requests counter — @commands.cooldown / @commands.max_concurrency are silently ignored by discord.py for pure @app_commands.command handlers and have been removed; both limits now fire before interaction.response.defer() so the response is immediate and ephemeral
  • [FIX] AI responses that exceed Discord's 4096-character embed limit now show a visible truncation notice (Response truncated — ask a more specific question) instead of cutting off silently
  • [FIX] Context strings sent to Gemini are now capped at 8,000 characters — large plugin lists or database schemas no longer risk exceeding model token limits
  • [FIX] Import coupling removed — PluginRegistry and FrameworkDiagnostics are no longer imported at module level; GeminiService loads gracefully even if those cogs are disabled

Additions

  • [ADD] 60-second in-memory TTL cache for repeated identical queries on diagnose, plugins, slash, hooks, and automations actions — cache hits are noted in the embed footer
  • [ADD] Gemini model is now configurable via GEMINI_MODEL environment variable (default: gemini-2.5-flash-lite)

cogs/backup_restore.py — Restore expanded to cover all captured data

Previously the backup captured forum channels, stage channels, emojis, stickers, and server settings but silently skipped all of them during restore. This update makes restore match what backup captures.

Backup (capture) changes

  • [FIX] Emoji images are now downloaded and stored as base64 inside the backup JSON at capture time — CDN URLs alone are useless after an emoji is deleted
  • [FIX] Sticker images are now downloaded and stored as base64 inside the backup JSON at capture time (also adds the missing url field to sticker entries)
  • [FIX] Server icon and banner are now downloaded and stored as base64 (icon_b64, banner_b64) inside the guild info block — restoring an icon no longer depends on the CDN URL remaining valid
  • [ADD] Added _download_image_b64() async helper used by capture for all image downloads

Restore changes

  • [ADD] Forum channels: restored via guild.create_forum(), skips duplicates by name
  • [ADD] Stage channels: restored via guild.create_stage_channel(), skips duplicates by name
  • [ADD] Emojis: restored from embedded base64 image data via guild.create_custom_emoji() — managed emojis are skipped
  • [ADD] Stickers: restored from embedded base64 image data via guild.create_sticker() — requires re-backup for entries captured before this update
  • [ADD] Server settings: restores name, verification level, default notifications, explicit content filter, AFK channel/timeout, premium progress bar via guild.edit()
  • [ADD] Server icon: restored from embedded base64 data via guild.edit(icon=bytes)

Discord UI (RestoreSelectView)

  • [ADD] Three new toggle buttons: Emojis, Stickers, Server Settings
  • [CHG] Bot Settings moved to row 1 alongside the new buttons
  • [CHG] Select All now includes emojis, stickers, and server_settings in its selection set
  • [CHG] Confirm Restore moved to its own row (row 3) for visual clarity

cogs/live_monitor.py — Dashboard restore parity

  • [ADD] _execute_dashboard_restore() updated with the same new restore blocks: forum channels, stage channels, emojis (base64), stickers (base64), server settings + icon (base64)
  • [ADD] PHP backup/restore UI: added Forum Channels and Stage Channels restore component checkboxes (Emojis, Stickers, Server Settings were already present in the UI but non-functional on the backend)
  • [CHG] Default restore components in _process_backup_actions() extended to include emojis, stickers, server_settings

discord-bot-framework (1.7.2.2)

25 Feb 19:49
d2a375b

Choose a tag to compare

What's New in Version 1.7.2.2

[Patch] - 2026-02-25

Fixed

cogs/EventHooksCreater.py — Async I/O fix

  • _save_analytics() was a synchronous function called from an async background task (analytics_task, runs every 5 minutes). Using open() + json.dump() in a sync function inside an async context blocks the entire event loop until the write finishes — meaning the bot cannot process any messages, commands, or Discord heartbeats during that time.
  • _save_created_hooks() had the same problem and is called in over a dozen places across async event handlers and command callbacks.
  • Fix: Both functions converted to async def using aiofiles. All 13 call sites updated to await self._save_created_hooks(). analytics_task updated to await self._save_analytics().
  • Behaviour is identical — hooks and analytics are still saved to the same JSON files at the same times. Only the I/O is now non-blocking.

cogs/GeminiService.py — Path traversal fix

  • The /ask_zdbf command's file and extension actions sanitized user-supplied file paths using file.lstrip("./\\").replace("..", ""). This was incorrect: lstrip strips individual characters from the left edge, not a literal prefix. A path like cogs/../config.json would survive the sanitization and resolve to cogs/config.json, potentially exposing files outside the intended scope.
  • Fix: Replaced the string manipulation with Path.resolve() + Path.relative_to(). The resolved absolute path is checked to be inside the allowed directory (bot root for file action, extensions/ for extension action) before the file is opened. If the path escapes the boundary, the command returns a clear access denied message.
  • Behaviour for valid paths is identical. Paths that previously slipped through are now blocked.

discord-bot-framework (1.7.2.1)

25 Feb 17:38
e20f54a

Choose a tag to compare

  • Added Action Permissions + Permission checks for the new Feature: Bot Status Configurator

discord-bot-framework (1.7.2.0)

24 Feb 15:58
7e8359a

Choose a tag to compare

Pre-release

What's New in Version 1.7.2.0

This update introduces a comprehensive Bot Status Configuration system, fully integrated into the Live Monitor web dashboard. This feature allows for dynamic, multi-status rotation with customizable variables, providing a more engaging and informative presence for your bot on Discord.


Bot Status Configuration — Now in the Dashboard

The new Bot Status Configuration card, located in the System tab of the Live Monitor dashboard, provides complete control over your bot's presence.

Key Features

  • Multi-Status Rotator: Create a list of different statuses for your bot to cycle through. Each status can have its own text, type (playing, watching, listening), and presence (online, idle, dnd).
  • Customizable Interval: Set the rotation interval in seconds to control how frequently the bot's status updates.
  • Dynamic Variables: Use variables like {guilds}, {users}, and {commands} in your status text, which will be automatically replaced with real-time data.
  • Live Editing: Add, edit, and delete statuses directly from the dashboard. Changes are saved and applied instantly without needing to restart the bot.
  • Log Toggling: A new toggle allows you to enable or disable logging for status updates, helping you monitor the rotator's activity in your bot's console.
  • Intuitive UI: The interface provides clear input fields for status type, text, and presence, making it easy to configure complex rotations.

This new system replaces the previous static status configuration, offering a much more flexible and powerful way to manage your bot's presence.

discord-bot-framework (1.7.1.0)

21 Feb 18:36
da73590

Choose a tag to compare

What's New in Version 1.7.1.0

Two major systems that were previously only accessible through Discord commands are now fully integrated into the Live Monitor web dashboard: Backup & Restore and Shard Management. Everything you could do in Discord, you can now do from your browser — plus a few extras.


Backup & Restore — Now in the Dashboard

The Backup & Restore tab gives you a complete overview of every server snapshot across all your guilds, with full management capabilities built right in.

At a Glance

When you open the tab, you'll see global stats at the top — total backups, how many guilds have backups, total storage used, pinned count, cooldown timer, auto-backup interval, and retention policy. A storage utilization bar shows how much of your capacity is in use.

Guild Sidebar

On the left, every guild with backups is listed with its backup count, total size, and schedule status. Click any guild to open its backup viewer.

Backup Viewer

Once you select a guild, you'll see all its backups listed chronologically. Each entry shows the label, timestamp, role and channel counts, file size, and whether it was created manually or automatically. From here you can:

  • Create a new backup directly from the dashboard with an optional custom label. The bot captures the full server snapshot — roles, channels, categories, emojis, stickers, member role assignments, and server settings — just like it would from a Discord command.
  • Delete a backup you no longer need. Pinned backups are protected and must be unpinned first.
  • Restore a backup using the restore modal, where you pick exactly which components to restore (roles, channels, categories, bot settings, member roles) and optionally enable full role sync mode.
  • Pin or unpin backups with one click to protect important snapshots from automatic cleanup and deletion.
  • View full details for any backup by expanding its detail panel, which shows everything — role count, category count, text/voice/forum/stage channel counts, emoji and sticker counts, member role assignments, total members at time of capture, file size, data integrity checksum, who created it, and any attached notes.

Per-Guild Scheduling

Each guild has its own configuration panel where you can enable or disable automatic scheduled backups, set the interval in hours, and configure retention (how many days to keep old backups before they're automatically cleaned up). Changes are saved instantly and take effect on the next bot cycle.

Restore Workflow

The restore process walks you through component selection, warns you about what will be affected, and shows a real-time log as the bot processes the operation. When it's done, you'll see a full results summary — how many items were created, skipped, or failed, how many members were processed, roles added or removed, duration, and any issues that came up. The button then changes to let you close the modal cleanly.


Shard Manager — Now in the Dashboard

If your bot runs across multiple shards or IPC clusters, the new Shard Manager tab gives you real-time visibility into every shard's health and performance without needing to run commands in Discord.

Overview

The top of the tab shows your total shard count, how many are healthy, how many have warnings, and your average latency across all shards. Below that, three info panels cover:

  • IPC Status — your clustering mode, cluster name, and how many clients are connected to the IPC mesh.
  • Health Summary — a breakdown of healthy, warning, and critical shards at a glance.
  • Global Totals — total guilds, total users, and overall uptime across all shards.

Health Bar

A visual health bar shows every shard as a colored block — green for healthy, yellow for warning, red for critical. Hover over any block to see that shard's ID, current latency, and the reason for its health status.

Shard Detail Cards

Below the health bar, each shard gets its own detail card showing its current latency, guild count, health status and reason, connection/disconnection/reconnection history, error count, and event throughput. You can view detailed metrics and reset shard statistics from the dashboard.

Cluster Map

If you're running multiple IPC clusters, the cluster map visualizes which shards belong to which cluster, their connection status, and how they're distributed across your infrastructure.

Role-Based Access

Both tabs respect the dashboard's permission system. Server owners have full access by default, while custom roles can be granted granular permissions — separately controlling who can view backups, create them, delete them, restore them, edit scheduling configs, view shard details, or reset shard metrics.


Summary of What's New

Feature Before 1.7.1.0 Now
Create backups Discord command only Dashboard + Discord
Delete backups Discord command only Dashboard + Discord
Restore backups Discord command only Dashboard + Discord
Pin/unpin backups Discord command only Dashboard + Discord
View backup details Discord command only Dashboard + Discord
Configure backup schedules Discord command only Dashboard + Discord
Monitor shard health Discord command only Dashboard + Discord
View shard latency & metrics Discord command only Dashboard + Discord
Reset shard statistics Discord command only Dashboard + Discord
IPC cluster visualization Not available Dashboard

All existing Discord commands continue to work exactly as before. The dashboard simply gives you an additional way to manage everything from your browser.

discord-bot-framework (1.7.0.0)

19 Feb 18:06
d670947

Choose a tag to compare

📋 Changelog

All notable changes to the Zoryx Discord Bot Framework are documented in this file.


🚀 v1.7.0.0 — Advanced Shard System & Backup/Restore

Release Date: 2026-02-18
Previous Version: 1.6.1.0


✨ New Features

📊 Shard Monitor Cog (cogs/shard_monitor.py) — v2.0.0 (V1 = Private)

A complete real-time shard health monitoring system with an interactive dashboard.

  • Interactive Dashboard (/shardmonitor) with 4 button-navigated tabs:
    • 📊 Overview — Cluster-wide stats, per-shard summary, alert configuration
    • 🏥 Health — Full health report with critical/warning/healthy breakdown
    • 📡 Latency — Visual latency bars per shard with min/avg/max statistics
    • 📈 Events — Per-shard counters (messages, commands, connects, disconnects, errors)
    • 🔄 Refresh — Refresh active tab with latest data
  • 5 Hybrid Commands (all Bot Owner Only):
    • /shardmonitor — Interactive dashboard
    • /sharddetails <id> — Deep-dive metrics for a specific shard
    • /shardhealth — Quick health report across all shards
    • /shardalerts [#channel] [threshold] — Configure automatic health alerts
    • /shardreset [shard_id] — Reset metrics for one or all shards
  • Enhanced ShardMetrics Class:
    • Latency history tracking (120 samples with rolling window)
    • Per-shard event counters (messages, commands, guild joins/leaves)
    • Uptime percentage calculation
    • Connection/disconnection/reconnection tracking with timestamps
    • Consecutive failure tracking with error details
  • Three-Tier Health Check System:
    • 🟢 Healthy — All metrics within normal range
    • 🟡 Warning — Latency >1s, no activity for 5+ min, or 3+ consecutive failures
    • 🔴 Critical — Latency >2s, 5+ consecutive failures, or currently disconnected
  • Alert System:
    • Configurable alert channel with persistent storage (./data/shard_monitor/alert_config.json)
    • Configurable failure threshold (1–20, default: 3)
    • Automatic alert embeds sent on unhealthy shard detection
  • Background Tasks:
    • collect_metrics — Records shard latency every 30 seconds
    • health_check — Evaluates shard health every 60 seconds
    • save_metrics — Persists metrics to disk every 5 minutes
  • Event Listeners:
    • on_message — Per-shard message counter
    • on_command — Per-shard command counter
    • on_shard_connect / on_shard_disconnect / on_shard_resumed / on_shard_ready
    • on_guild_join / on_guild_remove
  • .env Toggle: ENABLE_SHARD_MONITOR=true/false (default: true)

🌐 Shard Manager Cog (cogs/shard_manager.py) — v1.0.0

A new IPC (Inter-Process Communication) system for running shards across multiple processes or servers.

  • TCP-Based IPC Protocol:
    • Length-prefixed messages (4-byte header + JSON payload)
    • 1MB max message size
    • Nonce-based deduplication to prevent duplicate processing
  • IPC Server Mode (primary cluster):
    • Hosts TCP server, handles client authentication
    • Tracks connected clients with heartbeat monitoring
    • Routes messages between clusters
    • Broadcasts cluster join/leave notifications
  • IPC Client Mode (secondary clusters):
    • Connects to primary cluster's IPC server
    • Automatic reconnection with exponential backoff (5s → 120s max)
    • Sends heartbeats every 30 seconds
  • Message Types:
    • auth / auth_response — Shared secret authentication
    • heartbeat / heartbeat_ack — Keep-alive with guild count
    • stats_broadcast — Cluster statistics exchange (every 60s)
    • cluster_join / cluster_leave — Connection notifications
    • broadcast_message — Owner-initiated text broadcast
  • Security:
    • Shared secret authentication (SHARD_IPC_SECRET)
    • 10-second auth timeout for unauthenticated connections
    • No arbitrary code execution — safe preset queries only
    • Warning logged when using default secret
  • 3 Hybrid Commands (all Bot Owner Only):
    • /clusters — Show all connected clusters with stats, health, and global totals
    • /ipcstatus — IPC system diagnostics (mode, host, port, clients, heartbeats)
    • /broadcastmsg <message> — Broadcast text to all connected clusters
  • Background Task:
    • sync_stats — Broadcasts cluster statistics every 60 seconds
  • .env Toggle: ENABLE_SHARD_MANAGER=true/false (default: false)

💾 Backup & Restore System (cogs/backup_restore.py) — v2.1.0

A full guild configuration snapshot system for disaster recovery, server migrations, and auditing. Now with member role snapshots, selective restore, auto-backup scheduling, and a full audit trail.

  • Full Guild Snapshots capturing:
    • Roles (name, color, hoist, mentionable, permissions value, position)
    • Categories (name, position, NSFW, permission overwrites with target/allow/deny)
    • Text channels (name, topic, slowmode, NSFW, category, full permission overwrites)
    • Voice channels (name, bitrate, user limit, RTC region, category, full permission overwrites)
    • Forum channels and Stage channels (safe fallback if discord.py version lacks support)
    • Emojis (name, animated, URL, managed status)
    • Stickers (name, description, emoji)
    • Server settings (verification level, notification level, content filter, AFK, system channel, locale, boost bar)
    • Member role assignments — saves which non-bot members have which roles (requires Members Intent)
    • Bot settings (custom prefix, mention prefix configuration)
  • Interactive Dashboard (/backup) with 5 button-navigated tabs:
    • 📊 Overview — Storage usage bar, latest backup, current guild stats, cooldown timer
    • 📦 Backups — Paginated list with metadata (roles, channels, member snapshots, author, size)
    • 🔍 Compare — Drift analysis: current state vs latest backup with change counts
    • 📜 Audit Log — Every backup operation tracked (create, delete, restore, pin, verify, export)
    • 📈 Analytics — Trends, top creators, backup frequency, member snapshot counts
    • 🔄 Refresh + ◀ ▶ Pagination on all paginated tabs
    • 🗑️ Delete — Quick-delete from dashboard via dropdown selector with pin protection
  • 13 Hybrid Commands:
    • /backup — Interactive dashboard with 5 tabs
    • /backupcreate [label] — Create a full guild snapshot
    • /backuprestore <id> — Selective restore with component toggles (roles, categories, channels, member roles, bot settings)
    • /backupview <id> — Detailed backup inspection
    • /backupdelete <id> — Delete with two-step confirmation (respects pin protection)
    • /backuplist — Paginated backup list
    • /backuppin <id> — Pin/unpin to protect from deletion and cleanup
    • /backupnote <id> <text> — Annotate backups with notes
    • /backupverify <id> — SHA-256 checksum integrity verification
    • /backupschedule <action> [hours] — Per-guild auto-backup schedule (enable/disable/status)
    • /backupdiff <id_a> <id_b> — Compare any two backups (added/removed roles, channels, members)
    • /backupexport <id> — Export as JSON (Bot Owner only)
    • /backupstats — Global backup statistics (Bot Owner only)
  • Selective Restore Engine:
    • Toggle individual components: roles, categories, channels, member roles, bot settings
    • Creates only missing roles, categories, and channels (skips existing by name)
    • Recreates permission overwrites with old→new role ID mapping
    • Reapplies member role assignments — gives members back the roles they had at backup time
    • Role Sync mode (off by default) — when enabled, does a full rewind: adds missing roles AND removes roles that weren't in the backup, restoring each member's roles to the exact state at backup time
    • Guild chunking ensures all members are loaded before processing
    • Restores bot settings with cache invalidation
    • Real-time progress updates and detailed results report
    • Per-guild restore lock prevents concurrent operations
  • Audit Log System:
    • Tracks all operations with user ID, backup ID, and details
    • Per-guild storage, keeps last 200 entries
  • Auto-Backup Scheduler:
    • Per-guild configurable interval (1–168 hours)
    • Background loop checks hourly, auto-backups flagged with 🔁
    • Requires BACKUP_AUTO_INTERVAL > 0 in .env
  • Retention Cleanup:
    • Auto-deletion of old unpinned backups past threshold
    • Pinned backups always protected
    • Configurable via BACKUP_RETENTION_DAYS
  • Timezone-Aware Timestamps:
    • All timestamps stored as UTC-aware ISO 8601 (+00:00)
    • Discord <t:epoch:R> formatting shows correct relative time in every user's local timezone
    • Backward-compatible with legacy naive timestamps
  • Safety & Abuse Protection:
    • 5-minute cooldown per guild (configurable, bot owner gets bypass notification instead of silent skip)
    • Max 25 backups per guild (configurable)
    • Two-step confirmation for restore and delete
    • Interaction author verification on all buttons — only the invoker can interact
    • SHA-256 checksums, pin protection, restore lock
  • Permission System:
    • Bot Owner: Full access + export + global stats
    • Administrator: Guild-scoped access to all commands
    • Delete protection: non-admin users can only delete their own backups
  • .env Toggle: ENABLE_BACKUP_RESTORE=true/false (default: true)`

🔧 Modified Files

main.py

4 patches applied to integrate the new cogs:

  1. Owner-Only Commands List (line ~103):

    • Added 8 commands to BOT_OWNER_ONLY_COMMANDS:
      shardmonitor, sharddetails, shardhealth, shardalerts, shardreset, clusters, ipcstatus, broadcastmsg
    • Added backupexport and backupstats to owner-only list (backup export and global stats restricted to bot owner)
    • Ensures all shard and backup-export commands are restricted to BOT_OWNER_ID
  2. Cog Load Order (line ~22...

Read more