
当使用多个 Discord.js 客户端(如 client 和 clientHook)时,若在事件监听中误用非目标客户端的缓存或方法(如 client.guilds.cache.get()),会导致本应由 clientHook 执行的操作被 client 错误触发。核心在于确保所有资源访问与目标客户端严格绑定。
当使用多个 discord.js 客户端(如 client 和 clienthook)时,若在事件监听中误用非目标客户端的缓存或方法(如 client.guilds.cache.get()),会导致本应由 clienthook 执行的操作被 client 错误触发。核心在于确保所有资源访问与目标客户端严格绑定。
在你的代码中,关键问题出在这一行:
adapterCreator: client.guilds.cache.get("1148582522633072741").voiceAdapterCreator,
尽管事件监听器注册在 clientHook 上(clientHook.on("messageCreate", ...)),但你却调用了 client.guilds.cache.get(...) —— 这意味着你正在从 另一个机器人实例(client)中获取语音适配器。而 voiceAdapterCreator 是与特定客户端强绑定的,它内部依赖该客户端的事件总线、WebSocket 连接和权限上下文。因此,即使逻辑上想让 clientHook 加入语音频道,实际执行时却因复用了 client 的适配器,导致行为被 client 拦截或错乱。
✅ 正确做法是:所有与 clientHook 相关的操作,必须全程使用 clientHook 实例:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
clientHook.on("messageCreate", async (message) => {
if (message.author.bot && message.content.startsWith("You casted")) {
const guild = clientHook.guilds.cache.get("1148582522633072741");
if (!guild) return;
joinVoiceChannel({
channelId: Fishgame[castStrength],
guildId: "1148582522633072741",
adapterCreator: guild.voiceAdapterCreator,
});
}
});
⚠️ 注意事项:
-
joinVoiceChannel()(来自@discordjs/voice)本身不接收客户端实例参数,它仅依赖传入的adapterCreator;而该函数生成的连接最终由adapterCreator所属的客户端驱动。因此,adapterCreator的来源决定了哪个客户端真正执行连接。 - 若你封装了自定义的
joinVoiceChannel工具函数,强烈建议重构为支持显式传入客户端,提升可维护性与安全性:
// ✅ 推荐:增强型 joinVoiceChannel(支持指定 client)
function joinVoiceChannelWithOptions(options, client) {
return joinVoiceChannel({
...options,
adapterCreator: client.guilds.cache
.get(options.guildId)
?.voiceAdapterCreator,
});
}
// 使用
joinVoiceChannelWithOptions(
{ channelId: Fishgame[castStrength], guildId: "1148582522633072741" },
clientHook
);
? 总结:多机器人项目中,“谁监听,谁提供资源” 是黄金原则。切勿跨客户端混用 guilds.cache、channels.cache、users.cache 或任何 xxxAdapterCreator。每个 Client 实例拥有独立的缓存、状态和通信通道,混合使用将直接破坏隔离性,引发不可预测的行为(如消息响应错位、语音连接归属错误、权限校验失败等)。务必逐行审查事件处理器中的所有客户端引用,确保 100% 一致性。










