// this entire file is Opus 4.6 sorry const fs = require('fs'); const path = require('path'); const IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp']; const DEFAULT_INTERVAL = '24h'; const DEFAULT_DIR = './avatars'; /** Parse an interval string like "24h" or "30m" into milliseconds */ function parseInterval(str) { const match = String(str).match(/^(\d+)\s*(h|m)$/i); if (!match) { console.warn(`Avatars: Invalid interval "${str}", falling back to ${DEFAULT_INTERVAL}`); return parseInterval(DEFAULT_INTERVAL); } const value = parseInt(match[1], 10); const unit = match[2].toLowerCase(); return unit === 'h' ? value * 60 * 60 * 1000 : value * 60 * 1000; } /** Scan the directory and return an array of image file paths */ function scanAvatars(dir) { try { return fs.readdirSync(dir) .filter(f => IMAGE_EXTENSIONS.includes(path.extname(f).toLowerCase())) .map(f => path.join(dir, f)); } catch (err) { console.warn(`Avatars: Could not read directory "${dir}": ${err.message}`); return []; } } /** Pick a random avatar and set it on the client */ async function setRandomAvatar(client, avatars) { if (!avatars.length) { console.warn('Avatars: No images found, skipping avatar change'); return; } const pick = avatars[Math.floor(Math.random() * avatars.length)]; try { await client.user.setAvatar(pick); console.log(`Avatars: Changed to ${path.basename(pick)}`); } catch (err) { console.error(`Avatars: Failed to set avatar: ${err.message}`); } } /** * Start the avatar rotation system. * @param {import('discord.js').Client} client - The Discord client (must be ready) * @param {object} config - Bot config object */ function start(client, config = {}) { const avatarDir = path.resolve(config.avatarDir || DEFAULT_DIR); const intervalMs = parseInterval(config.avatarInterval || DEFAULT_INTERVAL); // ensure the directory exists if (!fs.existsSync(avatarDir)) { console.warn(`Avatars: Directory "${avatarDir}" does not exist, avatar rotation disabled`); return; } let avatars = scanAvatars(avatarDir); console.log(`Avatars: Found ${avatars.length} image(s) in ${avatarDir}`); console.log(`Avatars: Rotation interval set to ${config.avatarInterval || DEFAULT_INTERVAL}`); // set one immediately on boot setRandomAvatar(client, avatars); // rotate on the configured interval setInterval(() => { avatars = scanAvatars(avatarDir); // re-scan in case watcher missed something setRandomAvatar(client, avatars); }, intervalMs); // live-watch the folder for changes let debounceTimer = null; try { fs.watch(avatarDir, (eventType, filename) => { if (debounceTimer) clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { const updated = scanAvatars(avatarDir); if (updated.length !== avatars.length) { console.log(`Avatars: Folder changed, now ${updated.length} image(s)`); } avatars = updated; }, 500); // 500ms debounce }); console.log(`Avatars: Watching "${avatarDir}" for changes`); } catch (err) { console.warn(`Avatars: Could not watch directory: ${err.message}`); } } module.exports = { start };