有没有办法在删除 CategoryChannel 之前访问其子级?[Discord.js]

Mig*_*gon 5 discord discord.js

我在discord 机器人中处理channelDelete 事件。我的初衷是做以下事情:

  1. 侦听频道何时被删除
  2. 检查其类型是否等于“GUILD_CATEGORY”
  3. 删除该类别下的所有频道

我通常可以通过除此事件期间之外的其他任何地方CategoryChannel调用的属性访问 a 下的通道...children

module.exports = {
    name: 'channelDelete',
    once: false,
    async execute(channel) {
        if(channel.type == 'GUILD_CATEGORY')
            for(let [child_id, child] of channel.children)
                if (child.deletable) child.delete();
    },
}
Run Code Online (Sandbox Code Playgroud)

我可以确认代码正在执行,但问题是传入的通道对象处于已删除的状态,并且我无法获取子对象:

  • 在调试过程中,我注意到通道对象具有以下属性deleted: true
  • children属性为空,即使我知道在删除之前该频道类别中存在频道

CategoryChannel有没有办法让我的机器人在删除之前收集和处理 a 的子项?

Pal*_*alm 1

为什么?

不幸的是,这就是CategoryChannels 在discord.js 中的工作方式...
当类别被删除时,discord.js 会向API 发送请求以删除频道。只有这样,Discord 才会在删除类别后向您发送事件。
接下来发生的事情是孩子们不再属于该类别了!因此您将无法获取 CategoryChannel 对象内的子级。


children这是该房产的代码

get children() {
    return this.guild.channels.cache.filter(c => c.parentId === this.id);
}
Run Code Online (Sandbox Code Playgroud)

它过滤了公会中的频道,但这些子频道不再位于该类别中。这就是该房产空置的原因。

(唯一?)解决方案

这将需要缓存通道本身。因为实际上没有任何其他解决方案。
您可以通过不同的方式缓存频道。
请记住... Javascript 中有实例和引用,如果不承认可能会导致奇怪的行为。下面的代码仅适用于没有分片的小型机器人,只是为了让您知道。

const cachedChannels = new Map()

client.on('ready', () => {
  // Looping thru guilds...
  client.guilds.forEach((guild) => {
    // Filtering the channels to category channels only and looping thru them...
    guild.channels.filter((channel) => channel.type === "GUILD_CATEGORY").forEach((category) => {
      // Note on references and instances: Numbers, Strings and Booleans do not have instances like Object, Arrays, etc. do
      // We are using an array here to abuse the references
      cachedChannels.set(category.id, [])

      // Looping thru the children channels...
      category.children.forEach((children) => {
        // This is the array we've created earlier
        const storedChannels = cachedChannels.get(category.id)

        // Pushing the ID so we can fetch them later
        storedChannels.push(children.id)
      })
    })
  })
})

client.on('channelDelete', (channel) => {
  if (channel.type === "GUILD_CATEGORY") {
    // Looping thru our cached channel IDs defined earlier
    cachedChannels.get(channel.id).forEach((id) => {
      const child = channel.guild.channels.get(id)
      child.delete()
    })

    // Delete the cached IDs to save memory
    cachedChannels.delete(channel.id)
  }
})

Run Code Online (Sandbox Code Playgroud)