feat(GuildMember): add flags (#9087)

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Almeida
2023-02-17 21:09:49 +00:00
committed by GitHub
parent 4e0a89f58f
commit 76b21162ac
7 changed files with 91 additions and 0 deletions

View File

@@ -28,6 +28,7 @@ exports.Colors = require('./util/Colors');
exports.DataResolver = require('./util/DataResolver'); exports.DataResolver = require('./util/DataResolver');
exports.Events = require('./util/Events'); exports.Events = require('./util/Events');
exports.Formatters = require('./util/Formatters'); exports.Formatters = require('./util/Formatters');
exports.GuildMemberFlagsBitField = require('./util/GuildMemberFlagsBitField').GuildMemberFlagsBitField;
exports.IntentsBitField = require('./util/IntentsBitField'); exports.IntentsBitField = require('./util/IntentsBitField');
exports.LimitedCollection = require('./util/LimitedCollection'); exports.LimitedCollection = require('./util/LimitedCollection');
exports.MessageFlagsBitField = require('./util/MessageFlagsBitField'); exports.MessageFlagsBitField = require('./util/MessageFlagsBitField');

View File

@@ -11,6 +11,7 @@ const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
const { GuildMember } = require('../structures/GuildMember'); const { GuildMember } = require('../structures/GuildMember');
const { Role } = require('../structures/Role'); const { Role } = require('../structures/Role');
const Events = require('../util/Events'); const Events = require('../util/Events');
const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField');
const Partials = require('../util/Partials'); const Partials = require('../util/Partials');
/** /**
@@ -279,6 +280,7 @@ class GuildMemberManager extends CachedManager {
* (if they are connected to voice), or `null` if you want to disconnect them from voice * (if they are connected to voice), or `null` if you want to disconnect them from voice
* @property {DateResolvable|null} [communicationDisabledUntil] The date or timestamp * @property {DateResolvable|null} [communicationDisabledUntil] The date or timestamp
* for the member's communication to be disabled until. Provide `null` to enable communication again. * for the member's communication to be disabled until. Provide `null` to enable communication again.
* @property {GuildMemberFlagsResolvable} [flags] The flags to set for the member
* @property {string} [reason] Reason for editing this user * @property {string} [reason] Reason for editing this user
*/ */
@@ -314,6 +316,10 @@ class GuildMemberManager extends CachedManager {
: options.communicationDisabledUntil; : options.communicationDisabledUntil;
} }
if (typeof options.flags !== 'undefined') {
options.flags = GuildMemberFlagsBitField.resolve(options.flags);
}
let endpoint; let endpoint;
if (id === this.client.user.id) { if (id === this.client.user.id) {
const keys = Object.keys(options); const keys = Object.keys(options);

View File

@@ -6,6 +6,7 @@ const VoiceState = require('./VoiceState');
const TextBasedChannel = require('./interfaces/TextBasedChannel'); const TextBasedChannel = require('./interfaces/TextBasedChannel');
const { DiscordjsError, ErrorCodes } = require('../errors'); const { DiscordjsError, ErrorCodes } = require('../errors');
const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager'); const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager');
const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField');
const PermissionsBitField = require('../util/PermissionsBitField'); const PermissionsBitField = require('../util/PermissionsBitField');
/** /**
@@ -93,6 +94,16 @@ class GuildMember extends Base {
this.communicationDisabledUntilTimestamp = this.communicationDisabledUntilTimestamp =
data.communication_disabled_until && Date.parse(data.communication_disabled_until); data.communication_disabled_until && Date.parse(data.communication_disabled_until);
} }
if ('flags' in data) {
/**
* The flags of this member
* @type {Readonly<GuildMemberFlagsBitField>}
*/
this.flags = new GuildMemberFlagsBitField(data.flags).freeze();
} else {
this.flags ??= new GuildMemberFlagsBitField().freeze();
}
} }
_clone() { _clone() {
@@ -314,6 +325,16 @@ class GuildMember extends Base {
return this.guild.members.edit(this, options); return this.guild.members.edit(this, options);
} }
/**
* Sets the flags for this member.
* @param {GuildMemberFlagsResolvable} flags The flags to set
* @param {string} [reason] Reason for setting the flags
* @returns {Promise<GuildMember>}
*/
setFlags(flags, reason) {
return this.edit({ flags, reason });
}
/** /**
* Sets the nickname for this member. * Sets the nickname for this member.
* @param {?string} nick The nickname for the guild member, or `null` if you want to reset their nickname * @param {?string} nick The nickname for the guild member, or `null` if you want to reset their nickname
@@ -423,6 +444,7 @@ class GuildMember extends Base {
this.avatar === member.avatar && this.avatar === member.avatar &&
this.pending === member.pending && this.pending === member.pending &&
this.communicationDisabledUntilTimestamp === member.communicationDisabledUntilTimestamp && this.communicationDisabledUntilTimestamp === member.communicationDisabledUntilTimestamp &&
this.flags.bitfield === member.flags.bitfield &&
(this._roles === member._roles || (this._roles === member._roles ||
(this._roles.length === member._roles.length && this._roles.every((role, i) => role === member._roles[i]))) (this._roles.length === member._roles.length && this._roles.every((role, i) => role === member._roles[i])))
); );

View File

@@ -273,6 +273,11 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildMFALevel} * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildMFALevel}
*/ */
/**
* @external GuildMemberFlags
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildMemberFlags}
*/
/** /**
* @external GuildNSFWLevel * @external GuildNSFWLevel
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildNSFWLevel} * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildNSFWLevel}

View File

@@ -0,0 +1,41 @@
'use strict';
const { GuildMemberFlags } = require('discord-api-types/v10');
const BitField = require('./BitField');
/**
* Data structure that makes it easy to interact with a {@link GuildMember#flags} bitfield.
* @extends {BitField}
*/
class GuildMemberFlagsBitField extends BitField {
/**
* Numeric guild guild member flags.
* @type {GuildMemberFlags}
* @memberof GuildMemberFlagsBitField
*/
static Flags = GuildMemberFlags;
}
/**
* @name GuildMemberFlagsBitField
* @kind constructor
* @memberof GuildMemberFlagsBitField
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/
/**
* Bitfield of the packed bits
* @type {number}
* @name GuildMemberFlagsBitField#bitfield
*/
/**
* Data that can be resolved to give a guild member flag bitfield. This can be:
* * A string (see {@link GuildMemberFlagsBitField.Flags})
* * A guild member flag
* * An instance of GuildMemberFlagsBitField
* * An Array of GuildMemberFlagsResolvable
* @typedef {string|number|GuildMemberFlagsBitField|GuildMemberFlagsResolvable[]} GuildMemberFlagsResolvable
*/
exports.GuildMemberFlagsBitField = GuildMemberFlagsBitField;

View File

@@ -154,6 +154,7 @@ import {
ApplicationRoleConnectionMetadataType, ApplicationRoleConnectionMetadataType,
APIApplicationRoleConnectionMetadata, APIApplicationRoleConnectionMetadata,
ImageFormat, ImageFormat,
GuildMemberFlags,
} from 'discord-api-types/v10'; } from 'discord-api-types/v10';
import { ChildProcess } from 'node:child_process'; import { ChildProcess } from 'node:child_process';
import { EventEmitter } from 'node:events'; import { EventEmitter } from 'node:events';
@@ -1474,6 +1475,15 @@ export class GuildEmoji extends BaseGuildEmoji {
public setName(name: string, reason?: string): Promise<GuildEmoji>; public setName(name: string, reason?: string): Promise<GuildEmoji>;
} }
export type GuildMemberFlagsString = keyof typeof GuildMemberFlags;
export type GuildMemberFlagsResolvable = BitFieldResolvable<GuildMemberFlagsString, number>;
export class GuildMemberFlagsBitField extends BitField<GuildMemberFlagsString> {
public static Flags: GuildMemberFlags;
public static resolve(bit?: BitFieldResolvable<GuildMemberFlagsString, GuildMemberFlags>): number;
}
export class GuildMember extends PartialTextBasedChannel(Base) { export class GuildMember extends PartialTextBasedChannel(Base) {
private constructor(client: Client<true>, data: RawGuildMemberData, guild: Guild); private constructor(client: Client<true>, data: RawGuildMemberData, guild: Guild);
public avatar: string | null; public avatar: string | null;
@@ -1487,6 +1497,7 @@ export class GuildMember extends PartialTextBasedChannel(Base) {
public pending: boolean; public pending: boolean;
public get communicationDisabledUntil(): Date | null; public get communicationDisabledUntil(): Date | null;
public communicationDisabledUntilTimestamp: number | null; public communicationDisabledUntilTimestamp: number | null;
public flags: Readonly<GuildMemberFlagsBitField>;
public get joinedAt(): Date | null; public get joinedAt(): Date | null;
public joinedTimestamp: number | null; public joinedTimestamp: number | null;
public get kickable(): boolean; public get kickable(): boolean;
@@ -1516,6 +1527,7 @@ export class GuildMember extends PartialTextBasedChannel(Base) {
}; };
public kick(reason?: string): Promise<GuildMember>; public kick(reason?: string): Promise<GuildMember>;
public permissionsIn(channel: GuildChannelResolvable): Readonly<PermissionsBitField>; public permissionsIn(channel: GuildChannelResolvable): Readonly<PermissionsBitField>;
public setFlags(flags: GuildMemberFlagsResolvable, reason?: string): Promise<GuildMember>;
public setNickname(nickname: string | null, reason?: string): Promise<GuildMember>; public setNickname(nickname: string | null, reason?: string): Promise<GuildMember>;
public toJSON(): unknown; public toJSON(): unknown;
public toString(): UserMention; public toString(): UserMention;
@@ -5482,6 +5494,7 @@ export interface GuildMemberEditOptions {
deaf?: boolean; deaf?: boolean;
channel?: GuildVoiceChannelResolvable | null; channel?: GuildVoiceChannelResolvable | null;
communicationDisabledUntil?: DateResolvable | null; communicationDisabledUntil?: DateResolvable | null;
flags?: GuildMemberFlagsResolvable;
reason?: string; reason?: string;
} }

View File

@@ -158,6 +158,7 @@ import {
AutoModerationRuleManager, AutoModerationRuleManager,
PrivateThreadChannel, PrivateThreadChannel,
PublicThreadChannel, PublicThreadChannel,
GuildMemberFlagsBitField,
} from '.'; } from '.';
import { expectAssignable, expectNotAssignable, expectNotType, expectType } from 'tsd'; import { expectAssignable, expectNotAssignable, expectNotType, expectType } from 'tsd';
import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders'; import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders';
@@ -2143,3 +2144,5 @@ client.on('guildAuditLogEntryCreate', (auditLogEntry, guild) => {
expectType<GuildAuditLogsEntry>(auditLogEntry); expectType<GuildAuditLogsEntry>(auditLogEntry);
expectType<Guild>(guild); expectType<Guild>(guild);
}); });
expectType<Readonly<GuildMemberFlagsBitField>>(guildMember.flags);