From 0e4e90163bd5490552115d7f644b5f24a86aec0b Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 13:50:58 -0500 Subject: [PATCH 01/10] basic teams support --- src/structures/ClientApplication.js | 5 +- src/structures/Team.js | 109 ++++++++++++++++++++++++++++ src/structures/TeamMember.js | 66 +++++++++++++++++ src/util/Constants.js | 11 +++ 4 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 src/structures/Team.js create mode 100644 src/structures/TeamMember.js diff --git a/src/structures/ClientApplication.js b/src/structures/ClientApplication.js index d2bcd17a70cb..ac712bb6a53a 100644 --- a/src/structures/ClientApplication.js +++ b/src/structures/ClientApplication.js @@ -3,6 +3,7 @@ const Snowflake = require('../util/Snowflake'); const { ClientApplicationAssetTypes, Endpoints } = require('../util/Constants'); const Base = require('./Base'); +const Team = require('./Team'); const AssetTypes = Object.keys(ClientApplicationAssetTypes); @@ -67,9 +68,9 @@ class ClientApplication extends Base { /** * The owner of this OAuth application - * @type {?User} + * @type {User|Team} */ - this.owner = data.owner ? this.client.users.add(data.owner) : null; + this.owner = data.team ? new Team(this.client, data.team) : this.client.users.add(data.owner); } /** diff --git a/src/structures/Team.js b/src/structures/Team.js new file mode 100644 index 000000000000..001c98e86c46 --- /dev/null +++ b/src/structures/Team.js @@ -0,0 +1,109 @@ +'use strict'; + +const Snowflake = require('../util/Snowflake'); +const Collection = require('../util/Collection'); +const Base = require('./Base'); +const TeamMember = require('./TeamMember'); + +/** + * Represents a Client OAuth2 Application Team. + * @extends {Base} + */ +class Team extends Base { + constructor(client, data) { + super(client); + this._patch(data); + } + + _patch(data) { + /** + * The ID of the Team + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The name of the Team + * @type {string} + */ + this.name = data.name; + + /** + * The Team's icon hash + * @type {string} + */ + this.icon = data.icon; + + /** + * The Team's owner id + * @type {?string} + */ + this.ownerID = data.owner_user_id || null; + + /** + * The Team's members + * @type {Collection} + */ + this.members = new Collection(); + + for (const memberData of data.members) { + const member = new TeamMember(this.client, this, memberData); + this.members.set(member.id, member); + } + } + + /** + * The owner of this team + * @type {?TeamMember} + * @readonly + */ + get owner() { + return this.members.get(this.ownerID) || null; + } + + /** + * The timestamp the app was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the app was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * A link to the application's icon. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} URL to the icon + */ + iconURL({ format, size } = {}) { + if (!this.icon) return null; + return this.client.rest.cdn.AppIcon(this.id, this.icon, { format, size }); + } + + /** + * When concatenated with a string, this automatically returns the Team's name instead of the + * Team object. + * @returns {string} + * @example + * // Logs: Team name: My Team + * console.log(`Team name: ${application}`); + */ + toString() { + return this.name; + } + + toJSON() { + return super.toJSON({ createdTimestamp: true }); + } +} + +module.exports = Team; diff --git a/src/structures/TeamMember.js b/src/structures/TeamMember.js new file mode 100644 index 000000000000..60fdbf35d064 --- /dev/null +++ b/src/structures/TeamMember.js @@ -0,0 +1,66 @@ +'use strict'; + +const Base = require('./Base'); +const { MembershipStates } = require('../util/Constants'); + +/** + * Represents a Client OAuth2 Application Team Member. + * @extends {Base} + */ +class TeamMember extends Base { + constructor(client, team, data) { + super(client); + + /** + * The Team + * @type {Team} + */ + this.team = team; + + this._patch(data); + } + + _patch(data) { + /** + * The ID of the Team Member + * @type {Snowflake} + */ + this.id = data.user.id; + + /** + * The permissions this Team Member has with reguard to the team + * @type {string[]} + */ + this.permissions = data.permissions; + + /** + * The permissions this Team Member has with reguard to the team + * @type {string} + */ + this.membershipState = MembershipStates[data.membership_state]; + + /** + * The user for this Team Member + * @type {User} + */ + this.user = this.client.users.add(data.user); + } + + /** + * When concatenated with a string, this automatically returns the team members's name instead of the + * TeamMember object. + * @returns {string} + * @example + * // Logs: Team Member's username: Hydrabolt + * console.log(`Team Member's name: ${teamMember}`); + */ + toString() { + return this.user.username; + } + + toJSON() { + return super.toJSON(); + } +} + +module.exports = TeamMember; diff --git a/src/util/Constants.js b/src/util/Constants.js index 993563c073f6..22475089d172 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -569,6 +569,17 @@ exports.DefaultMessageNotifications = [ 'MENTIONS', ]; +/** + * The value set for a team members's membership state: + * * INVITED + * * ACCEPTED + * @typedef {string} MembershipStates + */ +exports.MembershipStates = [ + 'INVITED', + 'ACCEPTED', +]; + function keyMirror(arr) { let tmp = Object.create(null); for (const value of arr) tmp[value] = value; From 0478d277826fd8389343499a29f9ac962d4cc919 Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 13:56:22 -0500 Subject: [PATCH 02/10] export Team & TeamMember --- src/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.js b/src/index.js index b3a92f60caba..916056fe0b52 100644 --- a/src/index.js +++ b/src/index.js @@ -85,6 +85,8 @@ module.exports = { ReactionEmoji: require('./structures/ReactionEmoji'), RichPresenceAssets: require('./structures/Presence').RichPresenceAssets, Role: require('./structures/Role'), + Team: require('./structures/Team'), + TeamMember: require('./structures/TeamMember'), TextChannel: require('./structures/TextChannel'), User: require('./structures/User'), VoiceChannel: require('./structures/VoiceChannel'), From 23373c845ed05a8991a9fd701aa55d96171f9cb2 Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 13:57:38 -0500 Subject: [PATCH 03/10] use typedef --- src/structures/TeamMember.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/TeamMember.js b/src/structures/TeamMember.js index 60fdbf35d064..d640ec21a63a 100644 --- a/src/structures/TeamMember.js +++ b/src/structures/TeamMember.js @@ -35,7 +35,7 @@ class TeamMember extends Base { /** * The permissions this Team Member has with reguard to the team - * @type {string} + * @type {MembershipStates} */ this.membershipState = MembershipStates[data.membership_state]; From 4310e7c1e4f235b30db6f08d4b2036ce5afc9553 Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 14:16:54 -0500 Subject: [PATCH 04/10] typings and some fixes --- src/structures/Team.js | 2 +- src/structures/TeamMember.js | 24 ++++++++++-------------- typings/index.d.ts | 31 +++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/structures/Team.js b/src/structures/Team.js index 001c98e86c46..3614b4865b8b 100644 --- a/src/structures/Team.js +++ b/src/structures/Team.js @@ -95,7 +95,7 @@ class Team extends Base { * @returns {string} * @example * // Logs: Team name: My Team - * console.log(`Team name: ${application}`); + * console.log(`Team name: ${team}`); */ toString() { return this.name; diff --git a/src/structures/TeamMember.js b/src/structures/TeamMember.js index d640ec21a63a..b777d4cb507f 100644 --- a/src/structures/TeamMember.js +++ b/src/structures/TeamMember.js @@ -21,12 +21,6 @@ class TeamMember extends Base { } _patch(data) { - /** - * The ID of the Team Member - * @type {Snowflake} - */ - this.id = data.user.id; - /** * The permissions this Team Member has with reguard to the team * @type {string[]} @@ -44,22 +38,24 @@ class TeamMember extends Base { * @type {User} */ this.user = this.client.users.add(data.user); + + /** + * The ID of the Team Member + * @type {Snowflake} + */ + this.id = this.user.id; } /** - * When concatenated with a string, this automatically returns the team members's name instead of the + * When concatenated with a string, this automatically returns the team members's tag instead of the * TeamMember object. * @returns {string} * @example - * // Logs: Team Member's username: Hydrabolt - * console.log(`Team Member's name: ${teamMember}`); + * // Logs: Team Member's tag: @Hydrabolt + * console.log(`Team Member's tag: ${teamMember}`); */ toString() { - return this.user.username; - } - - toJSON() { - return super.toJSON(); + return this.user.toString(); } } diff --git a/typings/index.d.ts b/typings/index.d.ts index 7dfe5eed3331..b61839d85a32 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -264,6 +264,34 @@ declare module 'discord.js' { public toString(): string; } + export class Team extends Base { + constructor(client: Client, data: object); + public id: Snowflake; + public name: string; + public icon: string; + public ownerID: Snowflake | null; + public members: Collection + + public readonly owner: TeamMember; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + + public iconURL(options?: AvatarOptions): string; + public toJSON(): object; + public toString(): string; + } + + export class TeamMember extends Base { + constructor(client: Client, team: Team, data: object); + public team: Team; + public id: Snowflake; + public permissions: string[]; + public membershipState: MembershipStates; + public user: User; + + public toString(): string; + } + export interface ActivityOptions { name?: string; url?: string; @@ -1992,6 +2020,9 @@ declare module 'discord.js' { type InviteResolvable = string; + type MembershipStates = 'INVITED' + | 'ACCEPTED'; + interface MessageCollectorOptions extends CollectorOptions { max?: number; maxProcessed?: number; From 42ccff6d46a054f0973f175a427a2ddb6aebef54 Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 14:17:29 -0500 Subject: [PATCH 05/10] Update src/structures/TeamMember.js Co-Authored-By: Vlad Frangu --- src/structures/TeamMember.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/TeamMember.js b/src/structures/TeamMember.js index b777d4cb507f..f37fcbe04c7e 100644 --- a/src/structures/TeamMember.js +++ b/src/structures/TeamMember.js @@ -12,7 +12,7 @@ class TeamMember extends Base { super(client); /** - * The Team + * The Team this member is part of * @type {Team} */ this.team = team; From 9aeb74f675f23f40457a683cd76af2873ef10ddb Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 14:23:28 -0500 Subject: [PATCH 06/10] fix Team#iconURL() --- src/structures/Team.js | 2 +- src/util/Constants.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/structures/Team.js b/src/structures/Team.js index 3614b4865b8b..bb4cb44febaa 100644 --- a/src/structures/Team.js +++ b/src/structures/Team.js @@ -86,7 +86,7 @@ class Team extends Base { */ iconURL({ format, size } = {}) { if (!this.icon) return null; - return this.client.rest.cdn.AppIcon(this.id, this.icon, { format, size }); + return this.client.rest.cdn.TeamIcon(this.id, this.icon, { format, size }); } /** diff --git a/src/util/Constants.js b/src/util/Constants.js index 22475089d172..17bae132289b 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -145,6 +145,8 @@ exports.Endpoints = { makeImageUrl(`${root}/channel-icons/${channelID}/${hash}`, { size, format }), Splash: (guildID, hash, format = 'webp', size) => makeImageUrl(`${root}/splashes/${guildID}/${hash}`, { size, format }), + TeamIcon: (teamID, hash, format = 'webp', size) => + makeImageUrl(`${root}/team-icons/${teamID}/${hash}`, { size, format }), }; }, invite: (root, code) => `${root}/${code}`, From d021c81eb5245de56de1996be0c15914f10655b4 Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 14:26:37 -0500 Subject: [PATCH 07/10] fix typings and a bug --- src/util/Constants.js | 2 +- typings/index.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/Constants.js b/src/util/Constants.js index 17bae132289b..3b050e00f4ba 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -145,7 +145,7 @@ exports.Endpoints = { makeImageUrl(`${root}/channel-icons/${channelID}/${hash}`, { size, format }), Splash: (guildID, hash, format = 'webp', size) => makeImageUrl(`${root}/splashes/${guildID}/${hash}`, { size, format }), - TeamIcon: (teamID, hash, format = 'webp', size) => + TeamIcon: (teamID, hash, { format = 'webp', size } = {}) => makeImageUrl(`${root}/team-icons/${teamID}/${hash}`, { size, format }), }; }, diff --git a/typings/index.d.ts b/typings/index.d.ts index b61839d85a32..399130471d9b 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -270,7 +270,7 @@ declare module 'discord.js' { public name: string; public icon: string; public ownerID: Snowflake | null; - public members: Collection + public members: Collection; public readonly owner: TeamMember; public readonly createdAt: Date; From 0c6b0a8977d26dc43950b7e7cdf3b81e00fb7556 Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 14:30:42 -0500 Subject: [PATCH 08/10] fix states start at 1 --- src/util/Constants.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/Constants.js b/src/util/Constants.js index 3b050e00f4ba..0587163cdbc5 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -578,6 +578,8 @@ exports.DefaultMessageNotifications = [ * @typedef {string} MembershipStates */ exports.MembershipStates = [ + // They start at 1 + null, 'INVITED', 'ACCEPTED', ]; From 73b5b7c896676f88f44a900ff7c2e27469490597 Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 16:21:43 -0500 Subject: [PATCH 09/10] team icon hash can be null --- src/structures/Team.js | 4 ++-- typings/index.d.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/Team.js b/src/structures/Team.js index bb4cb44febaa..0832a31f3817 100644 --- a/src/structures/Team.js +++ b/src/structures/Team.js @@ -30,9 +30,9 @@ class Team extends Base { /** * The Team's icon hash - * @type {string} + * @type {?string} */ - this.icon = data.icon; + this.icon = data.icon || null; /** * The Team's owner id diff --git a/typings/index.d.ts b/typings/index.d.ts index 399130471d9b..0b77e4c05909 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -268,7 +268,7 @@ declare module 'discord.js' { constructor(client: Client, data: object); public id: Snowflake; public name: string; - public icon: string; + public icon: string | null; public ownerID: Snowflake | null; public members: Collection; From 58888000e38ff17a0982ef204aaf5b75009739cf Mon Sep 17 00:00:00 2001 From: bdistin Date: Wed, 19 Jun 2019 16:36:55 -0500 Subject: [PATCH 10/10] fix owner typings --- typings/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 0b77e4c05909..558e12eb9c8a 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -255,7 +255,7 @@ declare module 'discord.js' { public icon: string; public id: Snowflake; public name: string; - public owner: User | null; + public owner: User | Team; public rpcOrigins: string[]; public coverImage(options?: AvatarOptions): string; public fetchAssets(): Promise;