Project: Lumi Bot (Discord + Twitch + YouTube) — WebUI-first management Purpose of this file - Single source of truth for cross‑conversation context, conventions, and packaging. - Update when project behavior changes (routes, APIs, packaging, DB schema). - Refer back here before making changes. Repository layout - Core: - src/main.js (entry) - src/web/server.js (WebUI + routes + wizards) - src/services (auth, platforms, users, plugins, update-manager, etc.) - src/web/views (EJS pages, partials/layout) - src/web/public (styles.css, app.js) - Plugins: plugins// (plugin.json + index.js + optional views/) - Data: data/app.db (SQLite), snapshots, uploads (should be excluded from updates) - Updates output: updates/ (all update zips go here) Platform integration (current) - Discord, Twitch, YouTube supported; modular via src/services/platforms.js - Wizards in /setup/*: - /setup/discord, /setup/twitch, /setup/youtube (cancelable) - OAuth routes in /auth/*: - /auth/discord, /auth/twitch, /auth/youtube - Role mapping: - Discord roles from settings discord_admin_role_id / discord_mod_role_id (supports comma-separated) - Twitch: broadcaster/admin/mod via tags/badges - YouTube: chat owner/moderator flags WebUI key routes (core) - / (home) - /commands, /leaderboards, /stats, /profile - /moderator (Mods List) - /admin - /admin/settings - /admin/navigation - /admin/theming - /admin/privileges - /admin/logs - /admin/updates - /admin/commands - /admin/pages - /admin/users - /admin/plugins WebUI profile hook (core) - web.addProfileSection({ id, label, view?, content?, role?, order?, locals? }) - view: EJS include path; content: raw HTML string - role defaults to "public" if omitted - In profile template, sections render under "Personalized" - Profile view receives: user, profile, accounts + section.locals Update system (core) - applyBotUpdate(zipPath, { mode: "full"|"patch" }) - Full update requires: package.json, safe-mode.js, src/main.js, src/web/server.js - Patch mode accepts any files and overlays them (no deletes) - applyPluginUpdate(zipPath) expects plugin.json in root + entry file - Snapshots: data/snapshots (keeps last 20 successful) - Safe Mode: safe-mode.js supports rollback Update packaging standards - Always place update zips in updates/ - Core full update (default): - Zip from repo root EXCLUDING: .git, node_modules, data, plugins, updates - Filename: updates/lumi-update-.zip - Core patch update: - Zip only changed files/folders - Use Patch Mode in UI - Filename: updates/lumi-update--patch.zip (or similar) - Plugin update: - Zip contents of plugins// (root = plugin folder) - Filename: updates/lumi-plugin--vX.Y.Z.zip - Preferred zip tool on Windows: - tar -a -c -f -C . Command framework (core) - commandRouter.registerCommands(pluginId, [{ id, triggers, platforms, handler }]) - Platforms enumerated by services/platforms.js - Plugins can expose cmds.json for admin command list ingestion - Core dynamic command: !top (categories pulled from leaderboards/providers via src/services/top.js) Database schema (core) - data/app.db (SQLite) - user_profiles table includes: - internal_username (unique, NOCASE) - username_updated_at (added for 90‑day cooldown) - user_identities: provider/user mapping - plugin_settings: plugin key/value store - plugins: plugin registry Profile username cooldown (core) - User can update once every 90 days - Stored in user_profiles.username_updated_at - /profile/username checks cooldown server‑side - UI: modal with disabled button + hint when on cooldown Sidebar UX standards (core) - User chip is clickable to /profile - Collapsed sidebar: - Icons centered, tooltips on items/sections - Subitem icons remain visible (default or admin-uploaded) - Consistent padding/width - Enable/disable inputs should use green/red switch toggles (not plain checkboxes) - /admin/navigation uses drag-and-drop layout with an Advanced JSON editor Plugins (important) - Plugin system loads from plugins/ directory - Each plugin: - plugin.json with id, name, version, main (index.js) - index.js exports { id, init(...) } - web.mount("/plugins/", router, navItem) to add nav entry - Plugins should avoid core edits unless explicitly requested Current notable plugins - echonomy-framework: - Currency framework only (no items/betting) - Banking UI: /profile/banking (plugin) - Response templates with random/weighted replies - Community funds (renamable) - Commands under root (default "coins") - Activity rewards (discord/twitch messages, discord voice) are queued per user per hour and flushed as one hourly transaction note "Activity Reward" with metadata breakdown - echonomy-games: - Uses echonomy-framework currency - Hot Potato / Coinflip / Mystery Box - Per-platform enable + configurable triggers/aliases - Admin UI at /plugins/echonomy-games - Stats stored in echonomy_game_stats (plays, coins won/lost, last played) - moderation: - Global moderation actions, notes, sanctions - Ban/timeout UI at /plugins/moderation - TOs & Bans view at /plugins/moderation/tos-bans - Login gating shows moderation status screen - Evidence uploads stored in data/moderation/evidence (download via /plugins/moderation/evidence/:id) - quotes: - Quote storage/search with WebUI at /plugins/quotes - quotes table fields include quoter_user_id (internal user id) + game_name - Stats provider adds total quotes, top quoters, and top quoted games Database schema (core) - mod_role_periods table tracks mod/admin time for Mods List - auto-vc: - Auto VC creation based on lobby channels - Game name detection uses Discord presence PLAYING/STREAMING/COMPETING only - expression-interaction: - Action commands with stats tracking Important settings keys (core) - discord: discord_client_id, discord_client_secret, discord_bot_token, discord_guild_id, discord_admin_role_id, discord_mod_role_id, discord_redirect_uri - twitch: twitch_client_id, twitch_client_secret, twitch_bot_username, twitch_bot_oauth, twitch_channels, twitch_redirect_uri - youtube: youtube_client_id, youtube_client_secret, youtube_bot_refresh_token, youtube_bot_channel_id, youtube_redirect_uri - site: site_title, bot_avatar_url, command_prefix - nav: nav_item_icons (map of nav item id -> filename in data/nav-icons), nav_structure (custom sidebar layout) Known file locations - Layout partials: src/web/views/partials/layout-top.ejs, layout-bottom.ejs - Global CSS: src/web/public/styles.css - Global JS: src/web/public/app.js - Asset versioning: res.locals.assetVersion (cache-bust for styles/app) - Nav icons: src/web/public/icons/nav (defaults), data/nav-icons (admin uploads) Packaging sanity checks (before shipping) - Plugin zips contain plugin.json at root - Core zip contains package.json and src/main.js - No data/ or node_modules included - Update zip placed in updates/ TODOs / Open questions - Align plugin profile sections with new core hook (replace direct injection if used) - Standardize plugin response templates UI to avoid duplication - Consider centralized search API for profile user lookup - Add docs for web.addProfileSection usage (when stable)