/** * Secondary-token channel rename helper. * * Routes channel/thread renames through a second bot token (RENAMER_BOT) * so renames don't consume the primary bot's per-channel 2/10min budget. * * The secondary bot must be invited to the guild with Manage Channels * and Manage Threads. * * Not called directly from feature code — invoked by services/channelQueue.js * so all channel ops continue to flow through the queue. */ const { logWarn } = require('../services/debugLog'); const DISCORD_API = 'https://discord.com/api/v10'; async function renameChannel(channelId, newName) { const token = (process.env.RENAMER_BOT || '').trim(); if (!token) { throw new Error('RENAMER_BOT is not set; cannot rename via secondary token'); } const res = await fetch(`${DISCORD_API}/channels/${channelId}`, { method: 'PATCH', headers: { 'Authorization': `Bot ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: newName }) }); const text = await res.text(); let body; try { body = text ? JSON.parse(text) : null; } catch (_) { body = text; } if (res.status === 429) { const retryAfter = (body && typeof body === 'object' && body.retry_after) || null; logWarn('renamer', `429 rename channel=${channelId} retry_after=${retryAfter}`).catch(() => {}); const err = new Error(`rename 429: retry_after=${retryAfter}`); err.status = 429; err.retryAfter = retryAfter; err.body = body; throw err; } if (!res.ok) { const bodyStr = typeof body === 'string' ? body : JSON.stringify(body); const err = new Error(`rename failed: status=${res.status} body=${bodyStr}`); err.status = res.status; err.body = body; throw err; } return body; } module.exports = { renameChannel };