// src/discordService.js // Discord bot client initialization and role management functions const { Client, GatewayIntentBits } = require('discord.js'); const rolesConfig = require('../config/roles.json'); const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] }); // Initialize the Discord bot login client.login(process.env.DISCORD_BOT_TOKEN); client.on('ready', () => { console.log(`[Discord] Bot logged in as ${client.user.tag}`); }); /** * Assign a Discord role to a user based on their subscription tier * @param {string} userId - Discord user ID (snowflake) * @param {string} tier - Subscription tier name (e.g., 'awakened', 'fire_elemental') * @returns {Promise} - Success status */ async function assignDiscordRole(userId, tier) { try { const guild = client.guilds.cache.get(process.env.GUILD_ID); if (!guild) throw new Error('Guild not found.'); // Fetch the member. If they aren't in the server, this throws an error. const member = await guild.members.fetch(userId); const roleId = rolesConfig[tier]; if (!roleId) throw new Error(`No role mapping found for tier: ${tier}`); const role = guild.roles.cache.get(roleId); if (!role) throw new Error(`Role ID ${roleId} not found in server.`); await member.roles.add(role); console.log(`[Discord] Assigned role ${tier} to user ${userId}`); return true; } catch (error) { console.error(`[Discord] Failed to assign role to ${userId}:`, error.message); return false; } } /** * Remove all subscription roles from a user (used for cancellations or before upgrades) * @param {string} userId - Discord user ID (snowflake) * @returns {Promise} - Success status */ async function removeAllSubscriptionRoles(userId) { try { const guild = client.guilds.cache.get(process.env.GUILD_ID); if (!guild) throw new Error('Guild not found.'); const member = await guild.members.fetch(userId); // Extract all role IDs from the config const allRoleIds = Object.values(rolesConfig); // discord.js allows removing an array of role IDs at once await member.roles.remove(allRoleIds); console.log(`[Discord] Removed all subscription roles from ${userId}`); return true; } catch (error) { console.error(`[Discord] Failed to remove roles for ${userId}:`, error.message); throw error; } } /** * Update subscription roles (remove old, add new) - used for tier changes * @param {string} userId - Discord user ID * @param {string|null} newTier - New tier name, or null for cancellation */ async function updateSubscriptionRoles(userId, newTier = null) { try { const guild = client.guilds.cache.get(process.env.GUILD_ID); const member = await guild.members.fetch(userId); // 1. Remove ALL possible subscription roles const allRoleIds = Object.values(rolesConfig); await member.roles.remove(allRoleIds); // 2. Add the new role (if not cancelled) if (newTier && rolesConfig[newTier]) { const newRole = guild.roles.cache.get(rolesConfig[newTier]); if (newRole) await member.roles.add(newRole); } console.log(`[Discord] Updated roles for ${userId} to ${newTier || 'none'}`); } catch (error) { console.error(`[Discord] Role update failed for ${userId}:`, error); } } module.exports = { client, rolesConfig, assignDiscordRole, removeAllSubscriptionRoles, updateSubscriptionRoles };