From 0cd7556934b587e517a484075f2bee5d8dc0f243 Mon Sep 17 00:00:00 2001 From: SpaceEEC Date: Thu, 11 Jul 2019 13:10:54 +0200 Subject: [PATCH] feat(Teams): backport support for teams (#3357) * feat(Teams): backport support for teams PR #3350 Commit: a22aabf6a827f8643cf84939e9065b6c37b289e0 * fix(TeamMember): fix name of client property * refactor(OAuth2Application): make team nullable instead of optional * typings(OAuth2Application): make team nullable instable of optional * docs(OAuth2Application): deprecate and add an info to team property --- src/structures/OAuth2Application.js | 9 +++ src/structures/Team.js | 109 ++++++++++++++++++++++++++++ src/structures/TeamMember.js | 67 +++++++++++++++++ src/util/Constants.js | 14 ++++ typings/index.d.ts | 32 ++++++++ 5 files changed, 231 insertions(+) create mode 100644 src/structures/Team.js create mode 100644 src/structures/TeamMember.js diff --git a/src/structures/OAuth2Application.js b/src/structures/OAuth2Application.js index 2cdcb8b3d461..710aae89d106 100644 --- a/src/structures/OAuth2Application.js +++ b/src/structures/OAuth2Application.js @@ -1,4 +1,5 @@ const Snowflake = require('../util/Snowflake'); +const Team = require('./Team'); const util = require('util'); /** @@ -103,6 +104,14 @@ class OAuth2Application { */ this.owner = this.client.dataManager.newUser(data.owner); } + + /** + * The owning team of this OAuth application + * In v12.0.0 this property moves to `Team#owner`. + * @type {?Team} + * @deprecated + */ + this.team = data.team ? new Team(this.client, data.team) : null; } /** diff --git a/src/structures/Team.js b/src/structures/Team.js new file mode 100644 index 000000000000..e0dc0e08d011 --- /dev/null +++ b/src/structures/Team.js @@ -0,0 +1,109 @@ +const Snowflake = require('../util/Snowflake'); +const Collection = require('../util/Collection'); +const TeamMember = require('./TeamMember'); +const Constants = require('../util/Constants'); + +/** + * Represents a Client OAuth2 Application Team. + */ +class Team { + constructor(client, data) { + /** + * The client that instantiated the team + * @name Team#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: 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 || null; + + /** + * 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 the team + * @type {?TeamMember} + * @readonly + */ + get owner() { + return this.members.get(this.ownerID) || null; + } + + /** + * The timestamp the team was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return Snowflake.deconstruct(this.id).timestamp; + } + + /** + * The time the team was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * A link to the teams's icon. + * @type {?string} + * @readonly + */ + get iconURL() { + if (!this.icon) return null; + return Constants.Endpoints.CDN(this.client.options.http.cdn).TeamIcon(this.id, this.icon); + } + + /** + * 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: ${team}`); + */ + toString() { + return this.name; + } +} + +module.exports = Team; diff --git a/src/structures/TeamMember.js b/src/structures/TeamMember.js new file mode 100644 index 000000000000..5dbc2ce2289a --- /dev/null +++ b/src/structures/TeamMember.js @@ -0,0 +1,67 @@ +const { MembershipStates } = require('../util/Constants'); + +/** + * Represents a Client OAuth2 Application Team Member. + */ +class TeamMember { + constructor(client, team, data) { + /** + * The client that instantiated the Team Member + * @name TeamMember#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * The Team this member is part of + * @type {Team} + */ + this.team = team; + + this._patch(data); + } + + _patch(data) { + /** + * The permissions this Team Member has with regard to the team + * @type {string[]} + */ + this.permissions = data.permissions; + + /** + * The membership state this Team Member has with regard to the team + * @type {MembershipStates} + */ + this.membershipState = MembershipStates[data.membership_state]; + + /** + * The user for this Team Member + * @type {User} + */ + this.user = this.client.dataManager.newUser(data.user); + } + + /** + * The ID of the Team Member + * @type {Snowflake} + * @readonly + */ + get id() { + return this.user.id; + } + + /** + * When concatenated with a string, this automatically returns the team members's mention instead of the + * TeamMember object. + * @returns {string} + * @example + * // Logs: Team Member's mention: <@123456789> + * console.log(`Team Member's mention: ${teamMember}`); + */ + toString() { + return this.user.toString(); + } +} + +module.exports = TeamMember; diff --git a/src/util/Constants.js b/src/util/Constants.js index 231622ecd905..4c8fd4b5866c 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -216,6 +216,7 @@ const Endpoints = exports.Endpoints = { AppAsset: (clientID, hash) => `${root}/app-assets/${clientID}/${hash}.png`, GDMIcon: (channelID, hash) => `${root}/channel-icons/${channelID}/${hash}.jpg?size=2048`, Splash: (guildID, hash) => `${root}/splashes/${guildID}/${hash}.jpg`, + TeamIcon: (teamID, hash) => `${root}/team-icons/${teamID}/${hash}.jpg`, }; }, OAUTH2: { @@ -853,3 +854,16 @@ exports.DefaultMessageNotifications = [ 'ALL', 'MENTIONS', ]; + +/** + * The value set for a team members's membership state: + * * INVITED + * * ACCEPTED + * @typedef {string} MembershipStates + */ +exports.MembershipStates = [ + // They start at 1 + null, + 'INVITED', + 'ACCEPTED', +]; diff --git a/typings/index.d.ts b/typings/index.d.ts index cb23635e3cfe..ec514ad6ce7d 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -935,6 +935,7 @@ declare module 'discord.js' { public rpcApplicationState: boolean; public rpcOrigins: string[]; public secret: string; + public team: Team | null; public reset(): OAuth2Application; public toString(): string; } @@ -1232,6 +1233,34 @@ declare module 'discord.js' { public setBitrate(bitrate: number | 'auto'): void; } + export class Team { + constructor(client: Client, data: object); + public readonly client: Client; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public icon: string | null; + public readonly iconURL: string; + public id: Snowflake; + public members: Collection; + public name: string; + public readonly owner: TeamMember; + public ownerID: Snowflake | null; + + public toString(): string; + } + + export class TeamMember { + constructor(client: Client, team: Team, data: object); + public readonly client: Client; + public id: Snowflake; + public membershipState: MembershipStates; + public permissions: string[]; + public team: Team; + public user: User; + + public toString(): string; + } + export class TextChannel extends TextBasedChannel(GuildChannel) { constructor(guild: Guild, data: object); public lastMessageID: string; @@ -1873,6 +1902,9 @@ declare module 'discord.js' { type InviteResolvable = string; + type MembershipStates = 'INVITED' + | 'ACCEPTED'; + type MessageCollectorOptions = CollectorOptions & { max?: number; maxMatches?: number;