Skip to content

Commit

Permalink
feat(Role): role tags (#4628)
Browse files Browse the repository at this point in the history
* feat(Role): role tags

* fix(RoleManager): fix js docs and mark nullable

* fix(Role): typings tags are be null, not undefined

* fix(Role): getters should actually return a bool

* fix(RoleManager): typo

* fix(Role): should always return a boolean

* fix(Gmrm): getter should return null

* fix(RoleManager): getters should return null

* fix: typing getters should return null

* fix(Role): docs grammar and consistency

* chore: prefer in operator over Reflect#has

* feat(GmRm): botRole getter

* fix(GmRm): use the actual properties

* feat(RoleManager): rem myRole in pref o botRoleFor

* fix(Role): remove obsolete is- getters

* fix:  checking tags after getter removal

* chore: identifier naming consistency

* chore: prefer explicit true type over boolean

* fix: typo

* feat(Integration): Add Integration#roles getter (#1)

* fix(RoleManager): remove bot check r:partials

* feat(RoleManager): robustness against uncached u

* docs: possibly undefined

Co-authored-by: Jan <66554238+Vaporox@users.noreply.github.com>
  • Loading branch information
almostSouji and vaporoxx committed Dec 14, 2020
1 parent 8883a01 commit d6234b7
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 1 deletion.
20 changes: 20 additions & 0 deletions src/managers/GuildMemberRoleManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,26 @@ class GuildMemberRoleManager {
return this._roles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this._roles.first());
}

/**
* The premium subscriber role of the guild, if present on the member
* @type {?Role}
* @readonly
*/
get premiumSubscriberRole() {
return this.cache.find(role => role.tags && role.tags.premiumSubscriberRole) || null;
}

/**
* The managed role this member created when joining the guild, if any
* <info>Only ever available on bots</info>
* @type {?Role}
* @readonly
*/
get botRole() {
if (!this.member.user.bot) return null;
return this.cache.find(role => role.tags && role.tags.botID === this.member.user.id) || null;
}

/**
* Adds a role (or multiple roles) to the member.
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
Expand Down
21 changes: 21 additions & 0 deletions src/managers/RoleManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ class RoleManager extends BaseManager {
});
}

/**
* Gets the managed role a user created when joining the guild, if any
* <info>Only ever available for bots</info>
* @param {UserResolvable} user The user to access the bot role for
* @returns {?Role}
*/
botRoleFor(user) {
const userID = this.client.users.resolveID(user);
if (!userID) return null;
return this.cache.find(role => role.tags && role.tags.botID === userID) || null;
}

/**
* The `@everyone` role of the guild
* @type {Role}
Expand All @@ -135,6 +147,15 @@ class RoleManager extends BaseManager {
return this.cache.get(this.guild.id);
}

/**
* The premium subscriber role of the guild, if any
* @type {?Role}
* @readonly
*/
get premiumSubscriberRole() {
return this.cache.find(role => role.tags && role.tags.premiumSubscriberRole) || null;
}

/**
* The role with the highest position in the cache
* @type {Role}
Expand Down
10 changes: 10 additions & 0 deletions src/structures/Integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ class Integration extends Base {
this._patch(data);
}

/**
* All roles that are managed by this integration
* @type {Collection<Snowflake, Role>}
* @readonly
*/
get roles() {
const roles = this.guild.roles.cache;
return roles.filter(role => role.tags && role.tags.integrationID === this.id);
}

_patch(data) {
/**
* The behavior of expiring subscribers
Expand Down
20 changes: 20 additions & 0 deletions src/structures/Role.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,26 @@ class Role extends Base {
* @type {boolean}
*/
this.deleted = false;

/**
* The tags this role has
* @type {?Object}
* @property {Snowflake} [botID] The id of the bot this role belongs to
* @property {Snowflake} [integrationID] The id of the integration this role belongs to
* @property {true} [premiumSubscriberRole] Whether this is the guild's premium subscription role
*/
this.tags = data.tags ? {} : null;
if (data.tags) {
if ('bot_id' in data.tags) {
this.tags.botID = data.tags.bot_id;
}
if ('integration_id' in data.tags) {
this.tags.integrationID = data.tags.integration_id;
}
if ('premium_subscriber' in data.tags) {
this.tags.premiumSubscriberRole = true;
}
}
}

/**
Expand Down
13 changes: 12 additions & 1 deletion typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,7 @@ declare module 'discord.js' {
public id: Snowflake;
public name: string;
public role: Role;
public readonly roles: Collection<Snowflake, Role>;
public syncedAt: number;
public syncing: boolean;
public type: string;
Expand Down Expand Up @@ -1287,6 +1288,7 @@ declare module 'discord.js' {
public permissions: Readonly<Permissions>;
public readonly position: number;
public rawPosition: number;
public tags: RoleTagData | null;
public comparePositionTo(role: Role): number;
public delete(reason?: string): Promise<Role>;
public edit(data: RoleData, reason?: string): Promise<Role>;
Expand Down Expand Up @@ -1954,6 +1956,8 @@ declare module 'discord.js' {
public readonly hoist: Role | null;
public readonly color: Role | null;
public readonly highest: Role;
public readonly premiumSubscriberRole: Role | null;
public readonly botRole: Role | null;
public member: GuildMember;
public guild: Guild;

Expand Down Expand Up @@ -2015,7 +2019,8 @@ declare module 'discord.js' {
public readonly everyone: Role;
public readonly highest: Role;
public guild: Guild;

public readonly premiumSubscriberRole: Role | null;
public botRoleFor(user: UserResolvable): Role | null;
public create(options?: { data?: RoleData; reason?: string }): Promise<Role>;
public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise<Role | null>;
public fetch(id?: Snowflake, cache?: boolean, force?: boolean): Promise<Collection<Snowflake, Role>>;
Expand Down Expand Up @@ -3115,6 +3120,12 @@ declare module 'discord.js' {

type RoleResolvable = Role | string;

interface RoleTagData {
botID?: Snowflake;
integrationID?: Snowflake;
premiumSubscriberRole?: true;
}

type ShardingManagerMode = 'process' | 'worker';

type Snowflake = string;
Expand Down

0 comments on commit d6234b7

Please sign in to comment.