const { Client, GatewayIntentBits, ActivityType } = require("discord.js"); const http = require("http"); const TOKEN = process.env.DISCORD_BOT_TOKEN; const TARGET_USER_ID = process.env.DISCORD_USER_ID || "172037532370862080"; const PORT = parseInt(process.env.BOT_PORT || "3001", 10); if (!TOKEN) { console.error("DISCORD_BOT_TOKEN is required"); process.exit(1); } const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildPresences, ], }); let cachedData = { discord_status: "offline", listening_to_spotify: false, spotify: null, activities: [], }; function updatePresence(guild) { const member = guild.members.cache.get(TARGET_USER_ID); if (!member || !member.presence) return; const presence = member.presence; cachedData.discord_status = presence.status || "offline"; cachedData.activities = presence.activities ? presence.activities .filter((a) => a.type !== ActivityType.Custom) .map((a) => ({ name: a.name, type: a.type, details: a.details || null, state: a.state || null, assets: a.assets ? { large_image: a.assets.largeImage || null, large_text: a.assets.largeText || null, small_image: a.assets.smallImage || null, small_text: a.assets.smallText || null, } : null, timestamps: a.timestamps ? { start: a.timestamps.start?.toISOString() || null, end: a.timestamps.end?.toISOString() || null, } : null, })) : []; const spotifyActivity = presence.activities ? presence.activities.find((a) => a.type === ActivityType.Listening && a.name === "Spotify") : null; if (spotifyActivity && spotifyActivity.syncId) { cachedData.listening_to_spotify = true; cachedData.spotify = { song: spotifyActivity.details || "", artist: spotifyActivity.state ? spotifyActivity.state.replace(/; /g, "; ") : "", album: spotifyActivity.assets?.largeText || "", album_art_url: spotifyActivity.assets?.largeImage ? `https://i.scdn.co/image/${spotifyActivity.assets.largeImage.replace("spotify:", "")}` : null, track_id: spotifyActivity.syncId || null, }; } else { cachedData.listening_to_spotify = false; cachedData.spotify = null; } } function updateAll() { for (const guild of client.guilds.cache.values()) { updatePresence(guild); } } client.on("ready", () => { console.log(`Bot online as ${client.user.tag}`); client.user.setActivity("Watching Presence", { type: ActivityType.Watching }); updateAll(); }); client.on("presenceUpdate", () => { updateAll(); }); const server = http.createServer((req, res) => { if (req.method === "GET" && req.url === "/presence") { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ data: cachedData })); } else { res.writeHead(404); res.end("Not found"); } }); server.listen(PORT, () => { console.log(`HTTP endpoint listening on port ${PORT}`); }); client.login(TOKEN);