(function () { const statusEl = document.getElementById('status'); const logEl = document.getElementById('log'); const tokenEl = document.getElementById('token'); const guildEl = document.getElementById('guild'); const loginBtn = document.getElementById('login'); const logoutBtn = document.getElementById('logout'); const msgContentEl = document.getElementById('msgContent'); let client = null; function banner(kind, text) { statusEl.className = 'bs-banner bs-banner--' + kind; statusEl.textContent = text; } function log(line) { const p = document.createElement('div'); p.textContent = line; logEl.appendChild(p); logEl.scrollTop = logEl.scrollHeight; } function setBusy(on) { loginBtn.disabled = on; logoutBtn.disabled = on && !client; } function waitForDiscordJS(timeoutMs) { timeoutMs = timeoutMs || 8000; const started = Date.now(); return new Promise(function (resolve, reject) { function tick() { const dj = window.BridgeSwarm && window.BridgeSwarm.DiscordJS; if (dj && typeof dj.status === 'function') { resolve(dj); return; } if (Date.now() - started >= timeoutMs) { reject( new Error( 'BridgeSwarm.DiscordJS is missing. In chrome://extensions reload BridgeSwarm, then refresh this page.' ) ); return; } setTimeout(tick, 50); } tick(); }); } async function boot() { await BridgeSwarmExamples.waitForBridgeSwarm(); let dj; try { dj = await waitForDiscordJS(); } catch (err) { banner('err', err.message || String(err)); return; } let st = {}; try { st = await dj.status(); } catch (err) { banner('err', err.message || String(err)); return; } if (!st.loaded) { banner('warn', 'discord.js did not load on the host' + (st.loadError ? ': ' + st.loadError : '.')); return; } if (!st.enabled) { banner('warn', 'Discord is off. BridgeSwarm Settings β†’ Enable Discord, then refresh.'); return; } banner('ok', 'Discord pack ready. Paste a bot token and login.'); try { await dj.ready(); } catch (_) {} } async function onLogin() { const token = (tokenEl.value || '').trim(); if (!token) { banner('warn', 'Paste a bot token first.'); return; } setBusy(true); try { const dj = await waitForDiscordJS(); await dj.ready(); const { Client, GatewayIntentBits, Events, SlashCommandBuilder, REST, Routes } = dj; const intents = [GatewayIntentBits.Guilds]; if (GatewayIntentBits.DirectMessages) intents.push(GatewayIntentBits.DirectMessages); if (GatewayIntentBits.GuildMessages) intents.push(GatewayIntentBits.GuildMessages); if (msgContentEl.checked && GatewayIntentBits.MessageContent) { intents.push(GatewayIntentBits.MessageContent); } if (client) { try { await client.destroy(); } catch (_) {} client = null; } client = new Client({ intents: intents }); client.once(Events.ClientReady || Events.Ready || 'clientReady', async function (readyClient) { const tag = (readyClient && readyClient.user && readyClient.user.tag) || (client.user && client.user.tag) || 'bot'; log('Logged in as ' + tag); banner('ok', 'Logged in as ' + tag); const ping = new SlashCommandBuilder().setName('ping').setDescription('Replies with pong.').toJSON(); try { const rest = new REST().setToken(token); const appId = readyClient.user && readyClient.user.id; const guildId = (guildEl.value || '').trim(); if (guildId) { await rest.put(Routes.applicationGuildCommands(appId, guildId), { body: [ping] }); log('Registered /ping for guild ' + guildId); } else { await rest.put(Routes.applicationCommands(appId), { body: [ping] }); log('Registered global /ping (may take up to an hour). Set a guild id for instant updates.'); } } catch (err) { log('slash register failed: ' + (err && err.message ? err.message : err)); } }); client.on(Events.InteractionCreate || 'interactionCreate', async function (ix) { if (!ix || typeof ix.isChatInputCommand !== 'function' || !ix.isChatInputCommand()) return; if (ix.commandName !== 'ping') return; try { await ix.reply({ content: 'pong' }); log('/ping β†’ pong'); } catch (err) { log('reply failed: ' + (err && err.message ? err.message : err)); } }); if (Events.MessageCreate) { client.on(Events.MessageCreate, async function (message) { if (!message || (message.author && message.author.bot)) return; if (String(message.content || '').trim().toLowerCase() !== 'ping') return; try { await message.reply('pong'); log('message ping β†’ pong'); } catch (err) { log('message reply failed: ' + (err && err.message ? err.message : err)); } }); } client.on('error', function (err) { log('client error: ' + (err && err.message ? err.message : err)); }); log('Logging in…'); await client.login(token); } catch (err) { banner('err', err.message || String(err)); log(err.message || String(err)); } finally { setBusy(false); } } async function onLogout() { if (!client) return; setBusy(true); try { await client.destroy(); client = null; banner('ok', 'Client destroyed.'); log('Destroyed client.'); } catch (err) { log(err.message || String(err)); } finally { setBusy(false); } } loginBtn.addEventListener('click', onLogin); logoutBtn.addEventListener('click', onLogout); BridgeSwarmExamples.waitForBridgeSwarm().then(boot).catch(function (err) { banner('err', err.message || String(err)); }); })();