【问题标题】:Discord.js v13 Invite trackerDiscord.js v13 邀请跟踪器
【发布时间】:2021-11-29 22:03:35
【问题描述】:

终于开始将我的机器人从 v12 更新到 v13,并且遇到了一个我似乎无法解决的问题。我有一个在 v12 上完美运行但在 v13 上无法运行的邀请跟踪器。我已经包含了下面的代码,注释行是我知道需要为 v13 更改的 v12 代码。

// const Discord = require('discord.js')
const {
    Client,
    Intents
} = require('discord.js')

// const client = new Discord.Client({
//     partials: ['MESSAGE', 'CHANNEL', 'REACTION']
// })
const client = new Client({
    intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.GUILD_BANS, Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS, Intents.FLAGS.GUILD_INTEGRATIONS, Intents.FLAGS.GUILD_WEBHOOKS, Intents.FLAGS.GUILD_INVITES, Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.GUILD_PRESENCES, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS, Intents.FLAGS.GUILD_MESSAGE_TYPING, Intents.FLAGS.DIRECT_MESSAGES, Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, Intents.FLAGS.DIRECT_MESSAGE_TYPING],
    partials: ['MESSAGE', 'CHANNEL', 'REACTION']
})
const guildInvites = new Map()

// client.on('inviteCreate', async invite => guildInvites.set(invite.guild.id, await invite.guild.fetchInvites()))
client.on('inviteCreate', async invite => guildInvites.set(invite.guild.id, await invite.guild.invites.fetch()))

client.once('ready', () => {
    client.guilds.cache.forEach(guild => {
        //guild.fetchInvites()
        guild.invites.fetch()
            .then(invites => guildInvites.set(guild.id, invites))
            .catch(err => {
                console.log(err)
                console.log(guildInvites)
                client.channels.cache.get('channelId').send({
                    content: `${err}`
                })
            })
    })
})

client.on('guildMemberAdd', async member => {
    const cachedInvites = guildInvites.get(member.guild.id)
    // const newInvites = await member.guild.fetchInvites()
    const newInvites = await member.guild.invites.fetch()
    guildInvites.set(member.guild.id, newInvites)
    try {
        const usedInvite = newInvites.find(inv => cachedInvites.get(inv.code).uses < inv.uses)
        console.log(cachedInvites)
        console.log(newInvites)
        console.log(usedInvite)
        console.log(`The code ${usedInvite.code} was just used by ${member.user.username}.`)
    } catch (err) {
        console.log(err)
        client.channels.cache.get('channelId').send({
            content: `${err}`
        })
    }
})

这是控制台日志结果:

console.log(cachedInvites) => 在下面返回

Collection(2) [Map] {
    '11111111' => Invite {
      guild: Guild {
        id: 'xxxx',
        name: "Testing Server",
        icon: null,
        features: [Array],
        commands: [GuildApplicationCommandManager],
        members: [GuildMemberManager],
        channels: [GuildChannelManager],
        bans: [GuildBanManager],
        roles: [RoleManager],
        presences: PresenceManager {},
        voiceStates: [VoiceStateManager],
        stageInstances: [StageInstanceManager],
        invites: [GuildInviteManager],
        deleted: false,
        available: true,
        shardId: 0,
        splash: null,
        banner: null,
        description: null,
        verificationLevel: 'LOW',
        vanityURLCode: null,
        nsfwLevel: 'DEFAULT',
        discoverySplash: null,
        memberCount: 3,
        large: false,
        applicationId: null,
        afkTimeout: 900,
        afkChannelId: 'xxxx',
        systemChannelId: 'xxxx',
        premiumTier: 'NONE',
        premiumSubscriptionCount: 0,
        explicitContentFilter: 'ALL_MEMBERS',
        mfaLevel: 'NONE',
        joinedTimestamp: 1633812225872,
        defaultMessageNotifications: 'ONLY_MENTIONS',
        systemChannelFlags: [SystemChannelFlags],
        maximumMembers: 250000,
        maximumPresences: null,
        approximateMemberCount: null,
        approximatePresenceCount: null,
        vanityURLUses: null,
        rulesChannelId: 'xxxx',
        publicUpdatesChannelId: 'xxxx',
        preferredLocale: 'en-US',
        ownerId: 'xxxx',
        emojis: [GuildEmojiManager],
        stickers: [GuildStickerManager]
      },
      code: '11111111',
      presenceCount: null,
      memberCount: null,
      temporary: false,
      maxAge: 604800,
      uses: 40,
      maxUses: 0,
      inviter: User {
        id: 'xxxx',
        bot: false,
        system: false,
        flags: [UserFlags],
        username: 'xxxx',
        discriminator: 'xxxx',
        avatar: 'xxxx',
        banner: undefined,
        accentColor: undefined
      },
      targetUser: null,
      targetApplication: null,
      targetType: null,
      channel: TextChannel {
        type: 'GUILD_TEXT',
        deleted: false,
        guild: [Guild],
        guildId: 'xxxx',
        parentId: 'xxxx',
        permissionOverwrites: [PermissionOverwriteManager],
        messages: [MessageManager],
        threads: [ThreadManager],
        nsfw: false,
        id: 'xxxx',
        name: 'welcome',
        rawPosition: 3,
        topic: null,
        lastMessageId: 'xxxx',
        rateLimitPerUser: 0
      },
      createdTimestamp: 1633922331801,
      _expiresTimestamp: null,
      stageInstance: null
    },
    '22222222' => Invite {
      guild: Guild {
        id: 'xxxx',
        name: "Testing Server",
        icon: null,
        features: [Array],
        commands: [GuildApplicationCommandManager],
        members: [GuildMemberManager],
        channels: [GuildChannelManager],
        bans: [GuildBanManager],
        roles: [RoleManager],
        presences: PresenceManager {},
        voiceStates: [VoiceStateManager],
        stageInstances: [StageInstanceManager],
        invites: [GuildInviteManager],
        deleted: false,
        available: true,
        shardId: 0,
        splash: null,
        banner: null,
        description: null,
        verificationLevel: 'LOW',
        vanityURLCode: null,
        nsfwLevel: 'DEFAULT',
        discoverySplash: null,
        memberCount: 3,
        large: false,
        applicationId: null,
        afkTimeout: 900,
        afkChannelId: 'xxxx',
        systemChannelId: 'xxxx',
        premiumTier: 'NONE',
        premiumSubscriptionCount: 0,
        explicitContentFilter: 'ALL_MEMBERS',
        mfaLevel: 'NONE',
        joinedTimestamp: 1633812225872,
        defaultMessageNotifications: 'ONLY_MENTIONS',
        systemChannelFlags: [SystemChannelFlags],
        maximumMembers: 250000,
        maximumPresences: null,
        approximateMemberCount: null,
        approximatePresenceCount: null,
        vanityURLUses: null,
        rulesChannelId: 'xxxx',
        publicUpdatesChannelId: 'xxxx',
        preferredLocale: 'en-US',
        ownerId: 'xxxx',
        emojis: [GuildEmojiManager],
        stickers: [GuildStickerManager]
      },
      code: '22222222',
      presenceCount: null,
      memberCount: null,
      temporary: false,
      maxAge: 604800,
      uses: 21,
      maxUses: 0,
      inviter: User {
        id: 'xxxx',
        bot: false,
        system: false,
        flags: [UserFlags],
        username: 'xxxx',
        discriminator: 'xxxx',
        avatar: 'xxx',
        banner: undefined,
        accentColor: undefined
      },
      targetUser: null,
      targetApplication: null,
      targetType: null,
      channel: TextChannel {
        type: 'GUILD_TEXT',
        deleted: false,
        guild: [Guild],
        guildId: 'xxxxx',
        parentId: 'xxxx',
        permissionOverwrites: [PermissionOverwriteManager],
        messages: [MessageManager],
        threads: [ThreadManager],
        nsfw: false,
        id: 'xxxx',
        name: 'guest-chat',
        rawPosition: 48,
        topic: 'Guest Invitation Link',
        lastMessageId: null,
        rateLimitPerUser: 0
      },
      createdTimestamp: 1633969178889,
      _expiresTimestamp: null,
      stageInstance: null
    }
  }

console.log(newInvites) => 下面返回

Collection(2) [Map] {
    '11111111' => Invite {
      guild: Guild {
        id: 'xxxx',
        name: "Testing Server",
        icon: null,
        features: [Array],
        commands: [GuildApplicationCommandManager],
        members: [GuildMemberManager],
        channels: [GuildChannelManager],
        bans: [GuildBanManager],
        roles: [RoleManager],
        presences: PresenceManager {},
        voiceStates: [VoiceStateManager],
        stageInstances: [StageInstanceManager],
        invites: [GuildInviteManager],
        deleted: false,
        available: true,
        shardId: 0,
        splash: null,
        banner: null,
        description: null,
        verificationLevel: 'LOW',
        vanityURLCode: null,
        nsfwLevel: 'DEFAULT',
        discoverySplash: null,
        memberCount: 3,
        large: false,
        applicationId: null,
        afkTimeout: 900,
        afkChannelId: 'xxxx',
        systemChannelId: 'xxxx',
        premiumTier: 'NONE',
        premiumSubscriptionCount: 0,
        explicitContentFilter: 'ALL_MEMBERS',
        mfaLevel: 'NONE',
        joinedTimestamp: 1633812225872,
        defaultMessageNotifications: 'ONLY_MENTIONS',
        systemChannelFlags: [SystemChannelFlags],
        maximumMembers: 250000,
        maximumPresences: null,
        approximateMemberCount: null,
        approximatePresenceCount: null,
        vanityURLUses: null,
        rulesChannelId: 'xxxx',
        publicUpdatesChannelId: 'xxxx',
        preferredLocale: 'en-US',
        ownerId: 'xxxx',
        emojis: [GuildEmojiManager],
        stickers: [GuildStickerManager]
      },
      code: '11111111',
      presenceCount: null,
      memberCount: null,
      temporary: false,
      maxAge: 604800,
      uses: 40,
      maxUses: 0,
      inviter: User {
        id: 'xxxx',
        bot: false,
        system: false,
        flags: [UserFlags],
        username: 'xxxx',
        discriminator: 'xxxx',
        avatar: 'xxxx',
        banner: undefined,
        accentColor: undefined
      },
      targetUser: null,
      targetApplication: null,
      targetType: null,
      channel: TextChannel {
        type: 'GUILD_TEXT',
        deleted: false,
        guild: [Guild],
        guildId: 'xxxx',
        parentId: 'xxxx',
        permissionOverwrites: [PermissionOverwriteManager],
        messages: [MessageManager],
        threads: [ThreadManager],
        nsfw: false,
        id: 'xxxx',
        name: 'welcome',
        rawPosition: 3,
        topic: null,
        lastMessageId: 'xxxx',
        rateLimitPerUser: 0
      },
      createdTimestamp: 1633922331801,
      _expiresTimestamp: null,
      stageInstance: null
    },
    '22222222' => Invite {
      guild: Guild {
        id: '878285237082271744',
        name: "Testing Server",
        icon: null,
        features: [Array],
        commands: [GuildApplicationCommandManager],
        members: [GuildMemberManager],
        channels: [GuildChannelManager],
        bans: [GuildBanManager],
        roles: [RoleManager],
        presences: PresenceManager {},
        voiceStates: [VoiceStateManager],
        stageInstances: [StageInstanceManager],
        invites: [GuildInviteManager],
        deleted: false,
        available: true,
        shardId: 0,
        splash: null,
        banner: null,
        description: null,
        verificationLevel: 'LOW',
        vanityURLCode: null,
        nsfwLevel: 'DEFAULT',
        discoverySplash: null,
        memberCount: 3,
        large: false,
        applicationId: null,
        afkTimeout: 900,
        afkChannelId: 'xxxx',
        systemChannelId: 'xxxx',
        premiumTier: 'NONE',
        premiumSubscriptionCount: 0,
        explicitContentFilter: 'ALL_MEMBERS',
        mfaLevel: 'NONE',
        joinedTimestamp: 1633812225872,
        defaultMessageNotifications: 'ONLY_MENTIONS',
        systemChannelFlags: [SystemChannelFlags],
        maximumMembers: 250000,
        maximumPresences: null,
        approximateMemberCount: null,
        approximatePresenceCount: null,
        vanityURLUses: null,
        rulesChannelId: 'xxxx',
        publicUpdatesChannelId: 'xxxx',
        preferredLocale: 'en-US',
        ownerId: 'xxxx',
        emojis: [GuildEmojiManager],
        stickers: [GuildStickerManager]
      },
      code: '22222222',
      presenceCount: null,
      memberCount: null,
      temporary: false,
      maxAge: 604800,
      uses: 22,
      maxUses: 0,
      inviter: User {
        id: 'xxxx',
        bot: false,
        system: false,
        flags: [UserFlags],
        username: 'xxxx',
        discriminator: 'xxxx',
        avatar: 'xxxx',
        banner: undefined,
        accentColor: undefined
      },
      targetUser: null,
      targetApplication: null,
      targetType: null,
      channel: TextChannel {
        type: 'GUILD_TEXT',
        deleted: false,
        guild: [Guild],
        guildId: 'xxxx',
        parentId: 'xxxx',
        permissionOverwrites: [PermissionOverwriteManager],
        messages: [MessageManager],
        threads: [ThreadManager],
        nsfw: false,
        id: 'xxxx',
        name: 'guest-chat',
        rawPosition: 48,
        topic: 'Guest Invitation Link',
        lastMessageId: null,
        rateLimitPerUser: 0
      },
      createdTimestamp: 1633969178889,
      _expiresTimestamp: null,
      stageInstance: null
    }
  }

console.log(usedInvite) => 返回未定义

我得到的错误信息显然是:

TypeError: Cannot read property 'code' of undefined

【问题讨论】:

  • 在实际代码中,'channelId' 是一个数字,所以我没有得到指出。
  • 您能否更新您的问题以包含相关数据(例如,邀请的用途和代码——不包括实际代码,仅显示两个集合之间匹配的代码) cachedInvitesnewInvites 集合?
  • @Cannicide 已添加。

标签: discord.js


【解决方案1】:

您遇到的问题很可能源于您将整个Invites Collection 对象保存在guildInvites 映射中。请记住,在 Javascript 中,当您将单个对象保存在多个不同位置时,每个位置仍然指向同一个对象。基本上,当您将invites 对象或invite.guild.invites.fetch() 保存到您的guildInvites 映射时,它指的是与newInvites 完全相同的对象。换句话说,cachedInvitesnewInvites 都指向同一个对象;因此,它们将包含完全相同的值。每当newInvites 中的邀请更新时,它也会自动更新cachedInvites 中的邀请。由于 discord.js 在 v13 中用于邀请管理的代码发生了一些变化,这可能只是现在才发生。

但是,我还没有查看新 InviteManager 的 discord.js 源代码,因此这里可能存在其他一些类似的问题。但是,无论如何,此答案中的解决方案都有效。

因为缓存和新的邀请列表都是相同的,所以缓存的邀请和使用的邀请之间的使用最终是相等的(导致不满足cachedInvites.get(inv.code).uses &lt; inv.uses 条件)。因此,newInvites.find() 找不到您正在寻找的邀请,usedInvite 最终成为undefined

您可以通过多种方式解决此问题。我的偏好是不要将整个 invites 集合保存到您的邀请缓存中。由于您只需要知道缓存的邀请代码和旧的使用次数,您只需保存该信息。当您只需要来自每个缓存邀请的两条小信息时,无需将整个 Invite 对象保存到您的缓存中。

这是我提议的cachedInvites 的新结构。如您所见,它比以前更简单、更高效。它还通过不直接将invites 对象保存在缓存中来解决上述可能的JS 问题,即单个对象被保存到多个位置。

Collection(2) [Map] {
    '11111111' => 40,
    '22222222' => 21
}

这是我的完整解决方案,使用这种新的、更简单的缓存邀请结构。我已经测试过了,它可以工作:

client.on('inviteCreate', async invite => {
    const invites = await invite.guild.invites.fetch();

    const codeUses = new Map();
    invites.each(inv => codeUses.set(inv.code, inv.uses));

    guildInvites.set(invite.guild.id, codeUses);
})

client.once('ready', () => {
    client.guilds.cache.forEach(guild => {
        guild.invites.fetch()
            .then(invites => {
                console.log("INVITES CACHED");
                const codeUses = new Map();
                invites.each(inv => codeUses.set(inv.code, inv.uses));

                guildInvites.set(guild.id, codeUses);
            })
            .catch(err => {
                console.log("OnReady Error:", err)
            })
    })
})

client.on('guildMemberAdd', async member => {
    const cachedInvites = guildInvites.get(member.guild.id)
    const newInvites = await member.guild.invites.fetch();
    try {
        const usedInvite = newInvites.find(inv => cachedInvites.get(inv.code) < inv.uses);
        console.log("Cached", [...cachedInvites.keys()])
        console.log("New", [...newInvites.values()].map(inv => inv.code))
        console.log("Used", usedInvite)
        console.log(`The code ${usedInvite.code} was just used by ${member.user.username}.`)
    } catch (err) {
        console.log("OnGuildMemberAdd Error:", err)
    }

    newInvites.each(inv => cachedInvites.set(inv.code, inv.uses));
    guildInvites.set(member.guild.id, cachedInvites);
});

【讨论】:

    猜你喜欢
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 2021-11-09
    相关资源
    最近更新 更多