Two paired logWarn calls used to post to DEBUGGING_CHANNEL_ID every time the RENAMER_BOT secondary token hit Discord's per-channel rename quota: Warning: renamer — "429 rename channel=… retry_after=…" Warning: renameQueue — "secondary-bot 429; falling back to primary…" Both fire on the recoverable path: the channelQueue immediately falls back to the primary discord.js client, and that client's REST handler transparently waits out the retry_after and retries — the rename lands without operator action. Posting these to the debug channel was pure noise; staff were reading them as failures when nothing had failed. Demoted both to console.warn so they still appear in `docker logs broccolini` for diagnostic purposes but no longer post to Discord. Kept untouched: - utils/renamer.js:64 — 401/403 logWarn on secondary-bot auth/permission errors (real config problems; the operator does need to know). - services/channelQueue.js next.catch logError for status 401/403/429 — only fires when the fallback itself also failed (rare and worth a debug-channel post).
84 lines
2.7 KiB
JavaScript
84 lines
2.7 KiB
JavaScript
/**
|
|
* 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 retryAfterSec = (body && typeof body === 'object' && body.retry_after) || null;
|
|
const retryAfterMs = retryAfterSec != null ? Math.ceil(Number(retryAfterSec) * 1000) : null;
|
|
// Local log only; the channelQueue fallback path handles recovery
|
|
// transparently via discord.js's built-in 429 retry. Posting these to
|
|
// the debug channel was non-actionable noise.
|
|
console.warn(`[renamer] 429 rename channel=${channelId} retry_after=${retryAfterSec}`);
|
|
|
|
// Respect retry_after up to 2000ms; otherwise fail over immediately.
|
|
if (retryAfterMs != null && retryAfterMs > 0 && retryAfterMs <= 2000) {
|
|
await new Promise((resolve) => setTimeout(resolve, retryAfterMs));
|
|
}
|
|
|
|
const err = new Error(`rename 429: retry_after=${retryAfterSec}`);
|
|
err.status = 429;
|
|
err.retryAfter = retryAfterSec;
|
|
err.body = body;
|
|
err.fallback = true;
|
|
throw err;
|
|
}
|
|
|
|
if (res.status === 401 || res.status === 403) {
|
|
const bodyStr = typeof body === 'string' ? body : JSON.stringify(body);
|
|
logWarn('renamer', `${res.status} rename channel=${channelId} body=${bodyStr}`).catch(() => {});
|
|
const err = new Error(`rename ${res.status}: ${bodyStr}`);
|
|
err.status = res.status;
|
|
err.body = body;
|
|
err.fallback = true;
|
|
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 };
|