From a9cba48eb094d273cb30624a9a47efe5ffba92d6 Mon Sep 17 00:00:00 2001 From: Yu-yu0202 <135312165+Yu-yu0202@users.noreply.github.com> Date: Sat, 21 Jun 2025 14:44:27 +0900 Subject: [PATCH 1/4] feat: add guildtag property to User class - Add guildtag property that reads from primary_guild.tag in API response - Update equals and _equals methods to include guildtag comparison - Add TypeScript type definition for guildtag property - Support for accessing user's primary guild tag via user.guildtag --- packages/discord.js/src/structures/User.js | 20 ++++++++++++++++++-- packages/discord.js/typings/index.d.ts | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/discord.js/src/structures/User.js b/packages/discord.js/src/structures/User.js index e2fa4cab4fde..53c5e6c75502 100644 --- a/packages/discord.js/src/structures/User.js +++ b/packages/discord.js/src/structures/User.js @@ -28,6 +28,8 @@ class User extends Base { this.flags = null; + this.guildtag = null; + this._patch(data); } @@ -151,6 +153,17 @@ class User extends Base { } else { this.avatarDecorationData = null; } + + if (data.primary_guild?.tag) { + /** + * The guild tag name of this user + * + * @type {?string} + */ + this.guildtag = data.primary_guild?.tag; + } else { + this.guildtag ??= null; + } } /** @@ -338,7 +351,8 @@ class User extends Base { this.banner === user.banner && this.accentColor === user.accentColor && this.avatarDecorationData?.asset === user.avatarDecorationData?.asset && - this.avatarDecorationData?.skuId === user.avatarDecorationData?.skuId + this.avatarDecorationData?.skuId === user.avatarDecorationData?.skuId && + this.guildtag === user.primary_guild?.tag ); } @@ -363,7 +377,8 @@ class User extends Base { ('avatar_decoration_data' in user ? this.avatarDecorationData?.asset === user.avatar_decoration_data?.asset && this.avatarDecorationData?.skuId === user.avatar_decoration_data?.sku_id - : true) + : true) && + this.guildtag === user.primary_guild?.tag ); } @@ -396,6 +411,7 @@ class User extends Base { defaultAvatarURL: true, hexAccentColor: true, tag: true, + guildtag: true, }, ...props, ); diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index ed2da0646c0f..7043997a717d 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -3519,6 +3519,7 @@ export class User extends Base { public avatarDecorationData: AvatarDecorationData | null; public banner: string | null | undefined; public bot: boolean; + public guildtag: string | null; public get createdAt(): Date; public get createdTimestamp(): number; public discriminator: string; From 94683bd67fd4616cc2aa10182a4b81abe26451b6 Mon Sep 17 00:00:00 2001 From: Yu-yu0202 <135312165+Yu-yu0202@users.noreply.github.com> Date: Sat, 21 Jun 2025 14:54:27 +0900 Subject: [PATCH 2/4] test: add unit tests for User guildtag property --- .../discord.js/test/user-guildtag.test.js | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 packages/discord.js/test/user-guildtag.test.js diff --git a/packages/discord.js/test/user-guildtag.test.js b/packages/discord.js/test/user-guildtag.test.js new file mode 100644 index 000000000000..df259140f5e2 --- /dev/null +++ b/packages/discord.js/test/user-guildtag.test.js @@ -0,0 +1,137 @@ +'use strict'; + +const { Client, GatewayIntentBits } = require('../src/index.js'); + +// Mock data based on actual API response (personal information anonymized) +const mockUserDataWithGuildtag = { + id: '1234567890123456789', + username: 'testuser', + avatar: null, + discriminator: '0', + public_flags: 128, + flags: 128, + banner: null, + accent_color: null, + global_name: 'Test User', + avatar_decoration_data: null, + collectibles: null, + banner_color: null, + clan: { + identity_guild_id: '9876543210987654321', + identity_enabled: true, + tag: 'TEST', + badge: 'abcdef1234567890abcdef1234567890', + }, + primary_guild: { + identity_guild_id: '9876543210987654321', + identity_enabled: true, + tag: 'TEST', + badge: 'abcdef1234567890abcdef1234567890', + }, +}; + +const mockUserDataWithoutGuildtag = { + id: '123456789012345678', + username: 'testuser', + discriminator: '1234', + avatar: 'test_avatar_hash', + bot: false, + system: false, + public_flags: 0, + // primary_guild is not present +}; + +describe('User guildtag property tests', () => { + let client; + let user; + + beforeEach(() => { + client = new Client({ + intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.DirectMessages], + }); + + const { User } = require('../src/structures/User.js'); + user = new User(client, mockUserDataWithGuildtag); + }); + + afterEach(() => { + if (client) { + client.destroy(); + } + }); + + test('should have guildtag property when provided in data', () => { + expect(user.guildtag).toBe('TEST'); + }); + + test('should set guildtag to null when not provided in data', () => { + const userWithoutGuildtag = new (require('../src/structures/User.js').User)(client, mockUserDataWithoutGuildtag); + expect(userWithoutGuildtag.guildtag).toBeNull(); + }); + + test('should update guildtag when _patch is called with new data', () => { + const newData = { + ...mockUserDataWithGuildtag, + primary_guild: { ...mockUserDataWithGuildtag.primary_guild, tag: 'NewGuildTag' }, + }; + user._patch(newData); + expect(user.guildtag).toBe('NewGuildTag'); + }); + + test('should handle guildtag in equals method', () => { + const { User } = require('../src/structures/User.js'); + const user1 = new User(client, mockUserDataWithGuildtag); + const user2 = new User(client, { + ...mockUserDataWithGuildtag, + primary_guild: { ...mockUserDataWithGuildtag.primary_guild, tag: 'DifferentGuildTag' }, + }); + + expect(user1.equals(user2)).toBe(false); + + const user3 = new User(client, mockUserDataWithGuildtag); + expect(user1.equals(user3)).toBe(true); + }); + + test('should handle guildtag in _equals method', () => { + const apiUserData = { + id: '1234567890123456789', + username: 'testuser', + discriminator: '0', + avatar: 'test_avatar_hash', + public_flags: 128, + primary_guild: { + identity_guild_id: '9876543210987654321', + identity_enabled: true, + tag: 'TEST', + badge: 'abcdef1234567890abcdef1234567890', + }, + }; + + expect(user._equals(apiUserData)).toBe(true); + + const differentApiData = { + ...apiUserData, + primary_guild: { ...apiUserData.primary_guild, tag: 'DifferentGuildTag' }, + }; + expect(user._equals(differentApiData)).toBe(false); + }); + + test('should include guildtag in toJSON output', () => { + const json = user.toJSON(); + expect(json.guildtag).toBe('TEST'); + }); + + test('should handle guildtag in cache operations', () => { + client.users.cache.set(user.id, user); + const cachedUser = client.users.cache.get(user.id); + expect(cachedUser.guildtag).toBe('TEST'); + }); + + test('should handle partial user data', () => { + const partialData = { id: '123456789012345678' }; + const partialUser = new (require('../src/structures/User.js').User)(client, partialData); + + expect(partialUser.partial).toBe(true); + expect(partialUser.guildtag).toBeNull(); + }); +}); From f6ddcb7035b8eb3a69dfec9487209f1c7baf2b05 Mon Sep 17 00:00:00 2001 From: Yu-yu0202 <135312165+Yu-yu0202@users.noreply.github.com> Date: Sat, 21 Jun 2025 14:56:53 +0900 Subject: [PATCH 3/4] test: update User guildtag tests with additional properties --- packages/discord.js/test/user-guildtag.test.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/discord.js/test/user-guildtag.test.js b/packages/discord.js/test/user-guildtag.test.js index df259140f5e2..c322e1258505 100644 --- a/packages/discord.js/test/user-guildtag.test.js +++ b/packages/discord.js/test/user-guildtag.test.js @@ -96,9 +96,22 @@ describe('User guildtag property tests', () => { const apiUserData = { id: '1234567890123456789', username: 'testuser', + avatar: null, discriminator: '0', - avatar: 'test_avatar_hash', public_flags: 128, + flags: 128, + banner: null, + accent_color: null, + global_name: 'Test User', + avatar_decoration_data: null, + collectibles: null, + banner_color: null, + clan: { + identity_guild_id: '9876543210987654321', + identity_enabled: true, + tag: 'TEST', + badge: 'abcdef1234567890abcdef1234567890', + }, primary_guild: { identity_guild_id: '9876543210987654321', identity_enabled: true, From 56bdc1cb59690f012ff6453afd37f84b7ccaf01a Mon Sep 17 00:00:00 2001 From: Yu-yu0202 <135312165+Yu-yu0202@users.noreply.github.com> Date: Sat, 21 Jun 2025 14:57:15 +0900 Subject: [PATCH 4/4] fix: correct guildtag comparison in User class equality check --- packages/discord.js/src/structures/User.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discord.js/src/structures/User.js b/packages/discord.js/src/structures/User.js index 53c5e6c75502..58dfa6d6e982 100644 --- a/packages/discord.js/src/structures/User.js +++ b/packages/discord.js/src/structures/User.js @@ -352,7 +352,7 @@ class User extends Base { this.accentColor === user.accentColor && this.avatarDecorationData?.asset === user.avatarDecorationData?.asset && this.avatarDecorationData?.skuId === user.avatarDecorationData?.skuId && - this.guildtag === user.primary_guild?.tag + this.guildtag === user.guildtag ); }