feat: update rawDataTypes with new API components and types; add biome configuration file
Some checks failed
Lint / ESLint (push) Has been cancelled

This commit is contained in:
MythEclipse
2026-05-15 06:26:08 +07:00
parent bf38318902
commit 6e947f299e
206 changed files with 8329 additions and 3077 deletions

View File

@@ -93,7 +93,10 @@ class ApplicationCommandManager extends CachedManager {
* .then(commands => console.log(`Fetched ${commands.size} commands`))
* .catch(console.error);
*/
async fetch(id, { guildId, cache = true, force = false, locale, withLocalizations } = {}) {
async fetch(
id,
{ guildId, cache = true, force = false, locale, withLocalizations } = {},
) {
if (typeof id === 'object') {
({ guildId, cache = true, locale, withLocalizations } = id);
} else if (id) {
@@ -109,9 +112,16 @@ class ApplicationCommandManager extends CachedManager {
headers: {
'X-Discord-Locale': locale,
},
query: typeof withLocalizations === 'boolean' ? { with_localizations: withLocalizations } : undefined,
query:
typeof withLocalizations === 'boolean'
? { with_localizations: withLocalizations }
: undefined,
});
return data.reduce((coll, command) => coll.set(command.id, this._add(command, cache, guildId)), new Collection());
return data.reduce(
(coll, command) =>
coll.set(command.id, this._add(command, cache, guildId)),
new Collection(),
);
}
/**
@@ -160,9 +170,13 @@ class ApplicationCommandManager extends CachedManager {
*/
async set(commands, guildId) {
const data = await this.commandPath({ guildId }).put({
data: commands.map(c => this.constructor.transformCommand(c)),
data: commands.map((c) => this.constructor.transformCommand(c)),
});
return data.reduce((coll, command) => coll.set(command.id, this._add(command, true, guildId)), new Collection());
return data.reduce(
(coll, command) =>
coll.set(command.id, this._add(command, true, guildId)),
new Collection(),
);
}
/**
@@ -182,7 +196,12 @@ class ApplicationCommandManager extends CachedManager {
*/
async edit(command, data, guildId) {
const id = this.resolveId(command);
if (!id) throw new TypeError('INVALID_TYPE', 'command', 'ApplicationCommandResolvable');
if (!id)
throw new TypeError(
'INVALID_TYPE',
'command',
'ApplicationCommandResolvable',
);
const patched = await this.commandPath({ id, guildId }).patch({
data: this.constructor.transformCommand(data),
@@ -204,7 +223,12 @@ class ApplicationCommandManager extends CachedManager {
*/
async delete(command, guildId) {
const id = this.resolveId(command);
if (!id) throw new TypeError('INVALID_TYPE', 'command', 'ApplicationCommandResolvable');
if (!id)
throw new TypeError(
'INVALID_TYPE',
'command',
'ApplicationCommandResolvable',
);
await this.commandPath({ id, guildId }).delete();
@@ -226,25 +250,37 @@ class ApplicationCommandManager extends CachedManager {
if ('default_member_permissions' in command) {
default_member_permissions = command.default_member_permissions
? new Permissions(BigInt(command.default_member_permissions)).bitfield.toString()
? new Permissions(
BigInt(command.default_member_permissions),
).bitfield.toString()
: command.default_member_permissions;
}
if ('defaultMemberPermissions' in command) {
default_member_permissions =
command.defaultMemberPermissions !== null
? new Permissions(command.defaultMemberPermissions).bitfield.toString()
? new Permissions(
command.defaultMemberPermissions,
).bitfield.toString()
: command.defaultMemberPermissions;
}
return {
name: command.name,
name_localizations: command.nameLocalizations ?? command.name_localizations,
name_localizations:
command.nameLocalizations ?? command.name_localizations,
description: command.description,
description_localizations: command.descriptionLocalizations ?? command.description_localizations,
type: typeof command.type === 'number' ? command.type : ApplicationCommandTypes[command.type],
options: command.options?.map(o => ApplicationCommand.transformOption(o)),
default_permission: command.defaultPermission ?? command.default_permission,
description_localizations:
command.descriptionLocalizations ?? command.description_localizations,
type:
typeof command.type === 'number'
? command.type
: ApplicationCommandTypes[command.type],
options: command.options?.map((o) =>
ApplicationCommand.transformOption(o),
),
default_permission:
command.defaultPermission ?? command.default_permission,
default_member_permissions,
dm_permission: command.dmPermission ?? command.dm_permission,
};

View File

@@ -3,7 +3,10 @@
const { Collection } = require('@discordjs/collection');
const BaseManager = require('./BaseManager');
const { Error, TypeError } = require('../errors');
const { ApplicationCommandPermissionTypes, APIErrors } = require('../util/Constants');
const {
ApplicationCommandPermissionTypes,
APIErrors,
} = require('../util/Constants');
/**
* Manages API methods for permissions of Application Commands.
@@ -47,7 +50,10 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* @private
*/
permissionsPath(guildId, commandId) {
return this.client.api.applications(this.client.application.id).guilds(guildId).commands(commandId).permissions;
return this.client.api
.applications(this.client.application.id)
.guilds(guildId)
.commands(commandId).permissions;
}
/**
@@ -96,7 +102,9 @@ class ApplicationCommandPermissionsManager extends BaseManager {
const { guildId, commandId } = this._validateOptions(guild, command);
if (commandId) {
const data = await this.permissionsPath(guildId, commandId).get();
return data.permissions.map(perm => this.constructor.transformPermissions(perm, true));
return data.permissions.map((perm) =>
this.constructor.transformPermissions(perm, true),
);
}
const data = await this.permissionsPath(guildId).get();
@@ -104,7 +112,9 @@ class ApplicationCommandPermissionsManager extends BaseManager {
(coll, perm) =>
coll.set(
perm.id,
perm.permissions.map(p => this.constructor.transformPermissions(p, true)),
perm.permissions.map((p) =>
this.constructor.transformPermissions(p, true),
),
),
new Collection(),
);
@@ -163,24 +173,48 @@ class ApplicationCommandPermissionsManager extends BaseManager {
if (commandId) {
if (!Array.isArray(permissions)) {
throw new TypeError('INVALID_TYPE', 'permissions', 'Array of ApplicationCommandPermissionData', true);
throw new TypeError(
'INVALID_TYPE',
'permissions',
'Array of ApplicationCommandPermissionData',
true,
);
}
const data = await this.permissionsPath(guildId, commandId).put({
data: { permissions: permissions.map(perm => this.constructor.transformPermissions(perm)) },
data: {
permissions: permissions.map((perm) =>
this.constructor.transformPermissions(perm),
),
},
});
return data.permissions.map(perm => this.constructor.transformPermissions(perm, true));
return data.permissions.map((perm) =>
this.constructor.transformPermissions(perm, true),
);
}
if (!Array.isArray(fullPermissions)) {
throw new TypeError('INVALID_TYPE', 'fullPermissions', 'Array of GuildApplicationCommandPermissionData', true);
throw new TypeError(
'INVALID_TYPE',
'fullPermissions',
'Array of GuildApplicationCommandPermissionData',
true,
);
}
const APIPermissions = [];
for (const perm of fullPermissions) {
if (!Array.isArray(perm.permissions)) throw new TypeError('INVALID_ELEMENT', 'Array', 'fullPermissions', perm);
if (!Array.isArray(perm.permissions))
throw new TypeError(
'INVALID_ELEMENT',
'Array',
'fullPermissions',
perm,
);
APIPermissions.push({
id: perm.id,
permissions: perm.permissions.map(p => this.constructor.transformPermissions(p)),
permissions: perm.permissions.map((p) =>
this.constructor.transformPermissions(p),
),
});
}
const data = await this.permissionsPath(guildId).put({
@@ -190,7 +224,9 @@ class ApplicationCommandPermissionsManager extends BaseManager {
(coll, perm) =>
coll.set(
perm.id,
perm.permissions.map(p => this.constructor.transformPermissions(p, true)),
perm.permissions.map((p) =>
this.constructor.transformPermissions(p, true),
),
),
new Collection(),
);
@@ -221,26 +257,41 @@ class ApplicationCommandPermissionsManager extends BaseManager {
*/
async add({ guild, command, permissions }) {
const { guildId, commandId } = this._validateOptions(guild, command);
if (!commandId) throw new TypeError('INVALID_TYPE', 'command', 'ApplicationCommandResolvable');
if (!commandId)
throw new TypeError(
'INVALID_TYPE',
'command',
'ApplicationCommandResolvable',
);
if (!Array.isArray(permissions)) {
throw new TypeError('INVALID_TYPE', 'permissions', 'Array of ApplicationCommandPermissionData', true);
throw new TypeError(
'INVALID_TYPE',
'permissions',
'Array of ApplicationCommandPermissionData',
true,
);
}
let existing = [];
try {
existing = await this.fetch({ guild: guildId, command: commandId });
} catch (error) {
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS) throw error;
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS)
throw error;
}
const newPermissions = permissions.slice();
for (const perm of existing) {
if (!newPermissions.some(x => x.id === perm.id)) {
if (!newPermissions.some((x) => x.id === perm.id)) {
newPermissions.push(perm);
}
}
return this.set({ guild: guildId, command: commandId, permissions: newPermissions });
return this.set({
guild: guildId,
command: commandId,
permissions: newPermissions,
});
}
/**
@@ -272,15 +323,27 @@ class ApplicationCommandPermissionsManager extends BaseManager {
*/
async remove({ guild, command, users, roles }) {
const { guildId, commandId } = this._validateOptions(guild, command);
if (!commandId) throw new TypeError('INVALID_TYPE', 'command', 'ApplicationCommandResolvable');
if (!commandId)
throw new TypeError(
'INVALID_TYPE',
'command',
'ApplicationCommandResolvable',
);
if (!users && !roles) throw new TypeError('INVALID_TYPE', 'users OR roles', 'Array or Resolvable', true);
if (!users && !roles)
throw new TypeError(
'INVALID_TYPE',
'users OR roles',
'Array or Resolvable',
true,
);
let resolvedIds = [];
if (Array.isArray(users)) {
users.forEach(user => {
users.forEach((user) => {
const userId = this.client.users.resolveId(user);
if (!userId) throw new TypeError('INVALID_ELEMENT', 'Array', 'users', user);
if (!userId)
throw new TypeError('INVALID_ELEMENT', 'Array', 'users', user);
resolvedIds.push(userId);
});
} else if (users) {
@@ -292,14 +355,15 @@ class ApplicationCommandPermissionsManager extends BaseManager {
}
if (Array.isArray(roles)) {
roles.forEach(role => {
roles.forEach((role) => {
if (typeof role === 'string') {
resolvedIds.push(role);
return;
}
if (!this.guild) throw new Error('GUILD_UNCACHED_ROLE_RESOLVE');
const roleId = this.guild.roles.resolveId(role);
if (!roleId) throw new TypeError('INVALID_ELEMENT', 'Array', 'users', role);
if (!roleId)
throw new TypeError('INVALID_ELEMENT', 'Array', 'users', role);
resolvedIds.push(roleId);
});
} else if (roles) {
@@ -309,7 +373,11 @@ class ApplicationCommandPermissionsManager extends BaseManager {
if (!this.guild) throw new Error('GUILD_UNCACHED_ROLE_RESOLVE');
const roleId = this.guild.roles.resolveId(roles);
if (!roleId) {
throw new TypeError('INVALID_TYPE', 'users', 'Array or RoleResolvable');
throw new TypeError(
'INVALID_TYPE',
'users',
'Array or RoleResolvable',
);
}
resolvedIds.push(roleId);
}
@@ -319,10 +387,13 @@ class ApplicationCommandPermissionsManager extends BaseManager {
try {
existing = await this.fetch({ guild: guildId, command: commandId });
} catch (error) {
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS) throw error;
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS)
throw error;
}
const permissions = existing.filter(perm => !resolvedIds.includes(perm.id));
const permissions = existing.filter(
(perm) => !resolvedIds.includes(perm.id),
);
return this.set({ guild: guildId, command: commandId, permissions });
}
@@ -347,9 +418,19 @@ class ApplicationCommandPermissionsManager extends BaseManager {
*/
async has({ guild, command, permissionId }) {
const { guildId, commandId } = this._validateOptions(guild, command);
if (!commandId) throw new TypeError('INVALID_TYPE', 'command', 'ApplicationCommandResolvable');
if (!commandId)
throw new TypeError(
'INVALID_TYPE',
'command',
'ApplicationCommandResolvable',
);
if (!permissionId) throw new TypeError('INVALID_TYPE', 'permissionId', 'UserResolvable or RoleResolvable');
if (!permissionId)
throw new TypeError(
'INVALID_TYPE',
'permissionId',
'UserResolvable or RoleResolvable',
);
let resolvedId = permissionId;
if (typeof permissionId !== 'string') {
resolvedId = this.client.users.resolveId(permissionId);
@@ -358,7 +439,11 @@ class ApplicationCommandPermissionsManager extends BaseManager {
resolvedId = this.guild.roles.resolveId(permissionId);
}
if (!resolvedId) {
throw new TypeError('INVALID_TYPE', 'permissionId', 'UserResolvable or RoleResolvable');
throw new TypeError(
'INVALID_TYPE',
'permissionId',
'UserResolvable or RoleResolvable',
);
}
}
@@ -366,10 +451,11 @@ class ApplicationCommandPermissionsManager extends BaseManager {
try {
existing = await this.fetch({ guild: guildId, command: commandId });
} catch (error) {
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS) throw error;
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS)
throw error;
}
return existing.some(perm => perm.id === resolvedId);
return existing.some((perm) => perm.id === resolvedId);
}
_validateOptions(guild, command) {
@@ -383,7 +469,12 @@ class ApplicationCommandPermissionsManager extends BaseManager {
}
commandId ??= this.client.application?.commands.resolveId(command);
if (!commandId) {
throw new TypeError('INVALID_TYPE', 'command', 'ApplicationCommandResolvable', true);
throw new TypeError(
'INVALID_TYPE',
'command',
'ApplicationCommandResolvable',
true,
);
}
}
return { guildId, commandId };

View File

@@ -116,35 +116,55 @@ class AutoModerationRuleManager extends CachedManager {
exemptChannels,
reason,
}) {
const data = await this.client.api.guilds(this.guild.id)['auto-moderation'].rules.post({
data: {
name,
event_type: typeof eventType === 'number' ? eventType : AutoModerationRuleEventTypes[eventType],
trigger_type: typeof triggerType === 'number' ? triggerType : AutoModerationRuleTriggerTypes[triggerType],
trigger_metadata: triggerMetadata && {
keyword_filter: triggerMetadata.keywordFilter,
regex_patterns: triggerMetadata.regexPatterns,
presets: triggerMetadata.presets?.map(preset =>
typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset],
),
allow_list: triggerMetadata.allowList,
mention_total_limit: triggerMetadata.mentionTotalLimit,
mention_raid_protection_enabled: triggerMetadata.mentionRaidProtectionEnabled,
},
actions: actions.map(action => ({
type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type],
metadata: {
duration_seconds: action.metadata?.durationSeconds,
channel_id: action.metadata?.channel && this.guild.channels.resolveId(action.metadata.channel),
custom_message: action.metadata?.customMessage,
const data = await this.client.api
.guilds(this.guild.id)
['auto-moderation'].rules.post({
data: {
name,
event_type:
typeof eventType === 'number'
? eventType
: AutoModerationRuleEventTypes[eventType],
trigger_type:
typeof triggerType === 'number'
? triggerType
: AutoModerationRuleTriggerTypes[triggerType],
trigger_metadata: triggerMetadata && {
keyword_filter: triggerMetadata.keywordFilter,
regex_patterns: triggerMetadata.regexPatterns,
presets: triggerMetadata.presets?.map((preset) =>
typeof preset === 'number'
? preset
: AutoModerationRuleKeywordPresetTypes[preset],
),
allow_list: triggerMetadata.allowList,
mention_total_limit: triggerMetadata.mentionTotalLimit,
mention_raid_protection_enabled:
triggerMetadata.mentionRaidProtectionEnabled,
},
})),
enabled,
exempt_roles: exemptRoles?.map(exemptRole => this.guild.roles.resolveId(exemptRole)),
exempt_channels: exemptChannels?.map(exemptChannel => this.guild.channels.resolveId(exemptChannel)),
},
reason,
});
actions: actions.map((action) => ({
type:
typeof action.type === 'number'
? action.type
: AutoModerationActionTypes[action.type],
metadata: {
duration_seconds: action.metadata?.durationSeconds,
channel_id:
action.metadata?.channel &&
this.guild.channels.resolveId(action.metadata.channel),
custom_message: action.metadata?.customMessage,
},
})),
enabled,
exempt_roles: exemptRoles?.map((exemptRole) =>
this.guild.roles.resolveId(exemptRole),
),
exempt_channels: exemptChannels?.map((exemptChannel) =>
this.guild.channels.resolveId(exemptChannel),
),
},
reason,
});
return this._add(data);
}
@@ -173,7 +193,16 @@ class AutoModerationRuleManager extends CachedManager {
*/
async edit(
autoModerationRule,
{ name, eventType, triggerMetadata, actions, enabled, exemptRoles, exemptChannels, reason },
{
name,
eventType,
triggerMetadata,
actions,
enabled,
exemptRoles,
exemptChannels,
reason,
},
) {
const autoModerationRuleId = this.resolveId(autoModerationRule);
@@ -183,28 +212,43 @@ class AutoModerationRuleManager extends CachedManager {
.patch({
data: {
name,
event_type: typeof eventType === 'number' ? eventType : AutoModerationRuleEventTypes[eventType],
event_type:
typeof eventType === 'number'
? eventType
: AutoModerationRuleEventTypes[eventType],
trigger_metadata: triggerMetadata && {
keyword_filter: triggerMetadata.keywordFilter,
regex_patterns: triggerMetadata.regexPatterns,
presets: triggerMetadata.presets?.map(preset =>
typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset],
presets: triggerMetadata.presets?.map((preset) =>
typeof preset === 'number'
? preset
: AutoModerationRuleKeywordPresetTypes[preset],
),
allow_list: triggerMetadata.allowList,
mention_total_limit: triggerMetadata.mentionTotalLimit,
mention_raid_protection_enabled: triggerMetadata.mentionRaidProtectionEnabled,
mention_raid_protection_enabled:
triggerMetadata.mentionRaidProtectionEnabled,
},
actions: actions?.map(action => ({
type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type],
actions: actions?.map((action) => ({
type:
typeof action.type === 'number'
? action.type
: AutoModerationActionTypes[action.type],
metadata: {
duration_seconds: action.metadata?.durationSeconds,
channel_id: action.metadata?.channel && this.guild.channels.resolveId(action.metadata.channel),
channel_id:
action.metadata?.channel &&
this.guild.channels.resolveId(action.metadata.channel),
custom_message: action.metadata?.customMessage,
},
})),
enabled,
exempt_roles: exemptRoles?.map(exemptRole => this.guild.roles.resolveId(exemptRole)),
exempt_channels: exemptChannels?.map(exemptChannel => this.guild.channels.resolveId(exemptChannel)),
exempt_roles: exemptRoles?.map((exemptRole) =>
this.guild.roles.resolveId(exemptRole),
),
exempt_channels: exemptChannels?.map((exemptChannel) =>
this.guild.channels.resolveId(exemptChannel),
),
},
reason,
});
@@ -255,9 +299,15 @@ class AutoModerationRuleManager extends CachedManager {
fetch(options) {
if (!options) return this._fetchMany();
const { autoModerationRule, cache, force } = options;
const resolvedAutoModerationRule = this.resolveId(autoModerationRule ?? options);
const resolvedAutoModerationRule = this.resolveId(
autoModerationRule ?? options,
);
if (resolvedAutoModerationRule) {
return this._fetchSingle({ autoModerationRule: resolvedAutoModerationRule, cache, force });
return this._fetchSingle({
autoModerationRule: resolvedAutoModerationRule,
cache,
force,
});
}
return this._fetchMany(options);
}
@@ -268,15 +318,24 @@ class AutoModerationRuleManager extends CachedManager {
if (existing) return existing;
}
const data = await this.client.api.guilds(this.guild.id)('auto-moderation').rules(autoModerationRule).get();
const data = await this.client.api
.guilds(this.guild.id)('auto-moderation')
.rules(autoModerationRule)
.get();
return this._add(data, cache);
}
async _fetchMany(options = {}) {
const data = await this.client.api.guilds(this.guild.id)('auto-moderation').rules.get();
const data = await this.client.api
.guilds(this.guild.id)('auto-moderation')
.rules.get();
return data.reduce(
(col, autoModerationRule) => col.set(autoModerationRule.id, this._add(autoModerationRule, options.cache)),
(col, autoModerationRule) =>
col.set(
autoModerationRule.id,
this._add(autoModerationRule, options.cache),
),
new Collection(),
);
}
@@ -289,7 +348,10 @@ class AutoModerationRuleManager extends CachedManager {
*/
async delete(autoModerationRule, reason) {
const autoModerationRuleId = this.resolveId(autoModerationRule);
await this.client.api.guilds(this.guild.id)('auto-moderation').rules(autoModerationRuleId).delete({ reason });
await this.client.api
.guilds(this.guild.id)('auto-moderation')
.rules(autoModerationRuleId)
.delete({ reason });
}
}

View File

@@ -34,9 +34,11 @@ class BillingManager extends BaseManager {
*/
async fetchPaymentSources() {
// https://discord.com/api/v9/users/@me/billing/payment-sources
const d = await this.client.api.users('@me').billing['payment-sources'].get();
const d = await this.client.api
.users('@me')
.billing['payment-sources'].get();
// ! TODO: Create a PaymentSource class
this.paymentSources = new Collection(d.map(s => [s.id, s]));
this.paymentSources = new Collection(d.map((s) => [s.id, s]));
return this.paymentSources;
}
@@ -46,8 +48,12 @@ class BillingManager extends BaseManager {
*/
async fetchGuildBoosts() {
// https://discord.com/api/v9/users/@me/guilds/premium/subscription-slots
const d = await this.client.api.users('@me').guilds.premium['subscription-slots'].get();
this.guildBoosts = new Collection(d.map(s => [s.id, new GuildBoost(this.client, s)]));
const d = await this.client.api
.users('@me')
.guilds.premium['subscription-slots'].get();
this.guildBoosts = new Collection(
d.map((s) => [s.id, new GuildBoost(this.client, s)]),
);
return this.guildBoosts;
}
@@ -58,7 +64,7 @@ class BillingManager extends BaseManager {
async fetchCurrentSubscription() {
// https://discord.com/api/v9/users/@me/billing/subscriptions
const d = await this.client.api.users('@me').billing.subscriptions.get();
this.currentSubscription = new Collection(d.map(s => [s.id, s]));
this.currentSubscription = new Collection(d.map((s) => [s.id, s]));
return this.currentSubscription;
}
}

View File

@@ -19,7 +19,9 @@ class CachedManager extends DataManager {
* @readonly
* @name CachedManager#_cache
*/
Object.defineProperty(this, '_cache', { value: this.client.options.makeCache(this.constructor, this.holds) });
Object.defineProperty(this, '_cache', {
value: this.client.options.makeCache(this.constructor, this.holds),
});
let cleanup = this._cache[_cleanupSymbol]?.();
if (cleanup) {
@@ -62,7 +64,9 @@ class CachedManager extends DataManager {
return clone;
}
const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
const entry = this.holds
? new this.holds(this.client, data, ...extras)
: data;
if (cache) this.cache.set(id ?? entry.id, entry);
return entry;
}

View File

@@ -3,7 +3,11 @@
const process = require('node:process');
const CachedManager = require('./CachedManager');
const { Channel } = require('../structures/Channel');
const { Events, ThreadChannelTypes, RelationshipTypes } = require('../util/Constants');
const {
Events,
ThreadChannelTypes,
RelationshipTypes,
} = require('../util/Constants');
let cacheWarningEmitted = false;
@@ -16,8 +20,10 @@ class ChannelManager extends CachedManager {
super(client, Channel, iterable);
const defaultCaching =
this._cache.constructor.name === 'Collection' ||
((this._cache.maxSize === undefined || this._cache.maxSize === Infinity) &&
(this._cache.sweepFilter === undefined || this._cache.sweepFilter.isDefault));
((this._cache.maxSize === undefined ||
this._cache.maxSize === Infinity) &&
(this._cache.sweepFilter === undefined ||
this._cache.sweepFilter.isDefault));
if (!cacheWarningEmitted && !defaultCaching) {
cacheWarningEmitted = true;
process.emitWarning(
@@ -44,10 +50,15 @@ class ChannelManager extends CachedManager {
return existing;
}
const channel = Channel.create(this.client, data, guild, { allowUnknownGuild });
const channel = Channel.create(this.client, data, guild, {
allowUnknownGuild,
});
if (!channel) {
this.client.emit(Events.DEBUG, `Failed to find guild, or unknown type for channel ${data.id} ${data.type}`);
this.client.emit(
Events.DEBUG,
`Failed to find guild, or unknown type for channel ${data.id} ${data.type}`,
);
return null;
}
@@ -115,7 +126,10 @@ class ChannelManager extends CachedManager {
* .then(channel => console.log(channel.name))
* .catch(console.error);
*/
async fetch(id, { allowUnknownGuild = false, cache = true, force = false } = {}) {
async fetch(
id,
{ allowUnknownGuild = false, cache = true, force = false } = {},
) {
if (!force) {
const existing = this.cache.get(id);
if (existing && !existing.partial) return existing;
@@ -133,11 +147,19 @@ class ChannelManager extends CachedManager {
* client.channels.createGroupDM();
*/
async createGroupDM(recipients = []) {
if (!Array.isArray(recipients)) throw new Error(`Expected an array of recipients (got ${typeof recipients})`);
if (!Array.isArray(recipients))
throw new Error(
`Expected an array of recipients (got ${typeof recipients})`,
);
recipients = recipients
.map(r => this.client.users.resolveId(r))
.filter(r => r && this.client.relationships.cache.get(r) == RelationshipTypes.FRIEND);
if (recipients.length == 1 || recipients.length > 9) throw new Error('Invalid Users length (max=9)');
.map((r) => this.client.users.resolveId(r))
.filter(
(r) =>
r &&
this.client.relationships.cache.get(r) == RelationshipTypes.FRIEND,
);
if (recipients.length == 1 || recipients.length > 9)
throw new Error('Invalid Users length (max=9)');
const data = await this.client.api.users['@me'].channels.post({
data: { recipients },
});

View File

@@ -186,7 +186,7 @@ class ClientUserSettingManager extends BaseManager {
if ('custom_status' in data) {
this.customStatus = data.custom_status;
const activities = this.client.presence.activities.filter(
a => ![ActivityTypes.CUSTOM, 'CUSTOM'].includes(a.type),
(a) => ![ActivityTypes.CUSTOM, 'CUSTOM'].includes(a.type),
);
if (data.custom_status) {
const custom = new CustomStatus(this.client);
@@ -200,7 +200,10 @@ class ClientUserSettingManager extends BaseManager {
if (emoji) custom.setEmoji(emoji);
activities.push(custom);
}
this.client.emit('debug', '[SETTING > ClientUser] Sync activities & status');
this.client.emit(
'debug',
'[SETTING > ClientUser] Sync activities & status',
);
this.client.user.setPresence({ activities });
}
if ('friend_source_flags' in data) {
@@ -212,7 +215,10 @@ class ClientUserSettingManager extends BaseManager {
* @type {Collection<Snowflake, Guild>}
*/
this.disableDMfromGuilds = new Collection(
data.restricted_guilds.map(guildId => [guildId, this.client.guilds.cache.get(guildId)]),
data.restricted_guilds.map((guildId) => [
guildId,
this.client.guilds.cache.get(guildId),
]),
);
}
}
@@ -293,7 +299,10 @@ class ClientUserSettingManager extends BaseManager {
data.emoji_name = options.emoji?.name;
data.emoji_id = options.emoji?.id;
} else {
data.emoji_name = typeof options.emoji?.name === 'string' ? options.emoji?.name : null;
data.emoji_name =
typeof options.emoji?.name === 'string'
? options.emoji?.name
: null;
}
}
return this.edit({ custom_status: data });
@@ -305,7 +314,9 @@ class ClientUserSettingManager extends BaseManager {
};
if (typeof options.text === 'string') {
if (options.text.length > 128) {
throw new RangeError('[INVALID_VALUE] Custom status text must be less than 128 characters');
throw new RangeError(
'[INVALID_VALUE] Custom status text must be less than 128 characters',
);
}
data.text = options.text;
}
@@ -315,16 +326,20 @@ class ClientUserSettingManager extends BaseManager {
data.emoji_name = emoji.name;
data.emoji_id = emoji.id;
} else {
data.emoji_name = typeof options.emoji === 'string' ? options.emoji : null;
data.emoji_name =
typeof options.emoji === 'string' ? options.emoji : null;
}
}
if (typeof options.expires === 'number') {
if (options.expires < Date.now()) {
throw new RangeError(`[INVALID_VALUE] Custom status expiration must be greater than ${Date.now()}`);
throw new RangeError(
`[INVALID_VALUE] Custom status expiration must be greater than ${Date.now()}`,
);
}
data.expires_at = new Date(options.expires).toISOString();
}
if (['online', 'idle', 'dnd', 'invisible'].includes(options.status)) this.edit({ status: options.status });
if (['online', 'idle', 'dnd', 'invisible'].includes(options.status))
this.edit({ status: options.status });
return this.edit({ custom_status: data });
}
}
@@ -340,7 +355,9 @@ class ClientUserSettingManager extends BaseManager {
}
return this.edit({
default_guilds_restricted: status,
restricted_guilds: status ? this.client.guilds.cache.map(v => v.id) : [],
restricted_guilds: status
? this.client.guilds.cache.map((v) => v.id)
: [],
});
}
/**
@@ -364,8 +381,11 @@ class ClientUserSettingManager extends BaseManager {
* @returns {Promise}
*/
removeRestrictedGuild(guildId) {
if (!this.disableDMfromServer.delete(guildId)) throw new Error('Guild is already restricted');
return this.edit({ restricted_guilds: this.disableDMfromServer.map((v, k) => k) });
if (!this.disableDMfromServer.delete(guildId))
throw new Error('Guild is already restricted');
return this.edit({
restricted_guilds: this.disableDMfromServer.map((v, k) => k),
});
}
}

View File

@@ -38,7 +38,8 @@ class DataManager extends BaseManager {
*/
resolve(idOrInstance) {
if (idOrInstance instanceof this.holds) return idOrInstance;
if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) ?? null;
if (typeof idOrInstance === 'string')
return this.cache.get(idOrInstance) ?? null;
return null;
}

View File

@@ -47,7 +47,9 @@ class GuildBanManager extends CachedManager {
* @returns {?GuildBan}
*/
resolve(ban) {
return super.resolve(ban) ?? super.resolve(this.client.users.resolveId(ban));
return (
super.resolve(ban) ?? super.resolve(this.client.users.resolveId(ban))
);
}
/**
@@ -99,7 +101,8 @@ class GuildBanManager extends CachedManager {
if (!options) return this._fetchMany();
const { user, cache, force, limit, before, after } = options;
const resolvedUser = this.client.users.resolveId(user ?? options);
if (resolvedUser) return this._fetchSingle({ user: resolvedUser, cache, force });
if (resolvedUser)
return this._fetchSingle({ user: resolvedUser, cache, force });
if (!before && !after && !limit && typeof cache === 'undefined') {
throw new Error('FETCH_BAN_RESOLVE_ID');
@@ -123,7 +126,10 @@ class GuildBanManager extends CachedManager {
query: options,
});
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, options.cache)), new Collection());
return data.reduce(
(col, ban) => col.set(ban.user.id, this._add(ban, options.cache)),
new Collection(),
);
}
/**
* Options used to ban a user from a guild.
@@ -149,7 +155,8 @@ class GuildBanManager extends CachedManager {
* .catch(console.error);
*/
async create(user, options = {}) {
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
if (typeof options !== 'object')
throw new TypeError('INVALID_TYPE', 'options', 'object', true);
const id = this.client.users.resolveId(user);
if (!id) throw new Error('BAN_RESOLVE_ID', true);
@@ -232,18 +239,32 @@ class GuildBanManager extends CachedManager {
*/
async bulkCreate(users, options = {}) {
if (!users || !(Array.isArray(users) || users instanceof Collection)) {
throw new TypeError('INVALID_TYPE', 'users', 'Array or Collection of UserResolvable', true);
throw new TypeError(
'INVALID_TYPE',
'users',
'Array or Collection of UserResolvable',
true,
);
}
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
if (typeof options !== 'object')
throw new TypeError('INVALID_TYPE', 'options', 'object', true);
const userIds = users.map(user => this.client.users.resolveId(user));
const userIds = users.map((user) => this.client.users.resolveId(user));
if (userIds.length === 0) throw new Error('BULK_BAN_USERS_OPTION_EMPTY');
const result = await this.client.api.guilds(this.guild.id)['bulk-ban'].post({
data: { delete_message_days: options.deleteMessageSeconds, user_ids: userIds },
reason: options.reason,
});
return { bannedUsers: result.banned_users, failedUsers: result.failed_users };
const result = await this.client.api
.guilds(this.guild.id)
['bulk-ban'].post({
data: {
delete_message_days: options.deleteMessageSeconds,
user_ids: userIds,
},
reason: options.reason,
});
return {
bannedUsers: result.banned_users,
failedUsers: result.failed_users,
};
}
}

View File

@@ -18,7 +18,11 @@ const {
} = require('../util/Constants');
const DataResolver = require('../util/DataResolver');
const Util = require('../util/Util');
const { resolveAutoArchiveMaxLimit, transformGuildForumTag, transformGuildDefaultReaction } = require('../util/Util');
const {
resolveAutoArchiveMaxLimit,
transformGuildForumTag,
transformGuildDefaultReaction,
} = require('../util/Util');
let cacheWarningEmitted = false;
let storeChannelDeprecationEmitted = false;
@@ -32,8 +36,10 @@ class GuildChannelManager extends CachedManager {
super(guild.client, GuildChannel, iterable);
const defaultCaching =
this._cache.constructor.name === 'Collection' ||
((this._cache.maxSize === undefined || this._cache.maxSize === Infinity) &&
(this._cache.sweepFilter === undefined || this._cache.sweepFilter.isDefault));
((this._cache.maxSize === undefined ||
this._cache.maxSize === Infinity) &&
(this._cache.sweepFilter === undefined ||
this._cache.sweepFilter.isDefault));
if (!cacheWarningEmitted && !defaultCaching) {
cacheWarningEmitted = true;
process.emitWarning(
@@ -89,7 +95,8 @@ class GuildChannelManager extends CachedManager {
* @returns {?(GuildChannel|ThreadChannel)}
*/
resolve(channel) {
if (channel instanceof ThreadChannel) return this.cache.get(channel.id) ?? null;
if (channel instanceof ThreadChannel)
return this.cache.get(channel.id) ?? null;
return super.resolve(channel);
}
@@ -154,17 +161,33 @@ class GuildChannelManager extends CachedManager {
} = {},
) {
parent &&= this.client.channels.resolveId(parent);
permissionOverwrites &&= permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
const intType = typeof type === 'number' ? type : ChannelTypes[type] ?? ChannelTypes.GUILD_TEXT;
permissionOverwrites &&= permissionOverwrites.map((o) =>
PermissionOverwrites.resolve(o, this.guild),
);
const intType =
typeof type === 'number'
? type
: (ChannelTypes[type] ?? ChannelTypes.GUILD_TEXT);
const videoMode = typeof videoQualityMode === 'number' ? videoQualityMode : VideoQualityModes[videoQualityMode];
const videoMode =
typeof videoQualityMode === 'number'
? videoQualityMode
: VideoQualityModes[videoQualityMode];
const sortMode = typeof defaultSortOrder === 'number' ? defaultSortOrder : SortOrderTypes[defaultSortOrder];
const sortMode =
typeof defaultSortOrder === 'number'
? defaultSortOrder
: SortOrderTypes[defaultSortOrder];
const layoutMode =
typeof defaultForumLayout === 'number' ? defaultForumLayout : ForumLayoutTypes[defaultForumLayout];
typeof defaultForumLayout === 'number'
? defaultForumLayout
: ForumLayoutTypes[defaultForumLayout];
if (intType === ChannelTypes.GUILD_STORE && !storeChannelDeprecationEmitted) {
if (
intType === ChannelTypes.GUILD_STORE &&
!storeChannelDeprecationEmitted
) {
storeChannelDeprecationEmitted = true;
process.emitWarning(
// eslint-disable-next-line max-len
@@ -187,8 +210,12 @@ class GuildChannelManager extends CachedManager {
rate_limit_per_user: rateLimitPerUser,
rtc_region: rtcRegion,
video_quality_mode: videoMode,
available_tags: availableTags?.map(availableTag => transformGuildForumTag(availableTag)),
default_reaction_emoji: defaultReactionEmoji && transformGuildDefaultReaction(defaultReactionEmoji),
available_tags: availableTags?.map((availableTag) =>
transformGuildForumTag(availableTag),
),
default_reaction_emoji:
defaultReactionEmoji &&
transformGuildDefaultReaction(defaultReactionEmoji),
default_sort_order: sortMode,
default_forum_layout: layoutMode,
default_thread_rate_limit_per_user: defaultThreadRateLimitPerUser,
@@ -215,7 +242,8 @@ class GuildChannelManager extends CachedManager {
*/
async createWebhook(channel, name, { avatar, reason } = {}) {
const id = this.resolveId(channel);
if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
if (!id)
throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
const resolvedImage = await DataResolver.resolveImage(avatar);
@@ -239,8 +267,11 @@ class GuildChannelManager extends CachedManager {
async addFollower(channel, targetChannel, reason) {
const channelId = this.resolveId(channel);
const targetChannelId = this.resolveId(targetChannel);
if (!channelId || !targetChannelId) throw new Error('GUILD_CHANNEL_RESOLVE');
const { webhook_id } = await this.client.api.channels[channelId].followers.post({
if (!channelId || !targetChannelId)
throw new Error('GUILD_CHANNEL_RESOLVE');
const { webhook_id } = await this.client.api.channels[
channelId
].followers.post({
data: { webhook_channel_id: targetChannelId },
reason,
});
@@ -288,31 +319,36 @@ class GuildChannelManager extends CachedManager {
*/
async edit(channel, data, reason) {
channel = this.resolve(channel);
if (!channel) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
if (!channel)
throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
const parentId = data.parent && this.client.channels.resolveId(data.parent);
if (typeof data.position !== 'undefined') await this.setPosition(channel, data.position, { reason });
if (typeof data.position !== 'undefined')
await this.setPosition(channel, data.position, { reason });
let permission_overwrites = data.permissionOverwrites?.map(o => PermissionOverwrites.resolve(o, this.guild));
let permission_overwrites = data.permissionOverwrites?.map((o) =>
PermissionOverwrites.resolve(o, this.guild),
);
if (data.lockPermissions) {
if (parentId) {
const newParent = this.cache.get(parentId);
if (newParent?.type === 'GUILD_CATEGORY') {
permission_overwrites = newParent.permissionOverwrites.cache.map(o =>
PermissionOverwrites.resolve(o, this.guild),
permission_overwrites = newParent.permissionOverwrites.cache.map(
(o) => PermissionOverwrites.resolve(o, this.guild),
);
}
} else if (channel.parent) {
permission_overwrites = channel.parent.permissionOverwrites.cache.map(o =>
PermissionOverwrites.resolve(o, this.guild),
permission_overwrites = channel.parent.permissionOverwrites.cache.map(
(o) => PermissionOverwrites.resolve(o, this.guild),
);
}
}
let defaultAutoArchiveDuration = data.defaultAutoArchiveDuration;
if (defaultAutoArchiveDuration === 'MAX') defaultAutoArchiveDuration = resolveAutoArchiveMaxLimit(this.guild);
if (defaultAutoArchiveDuration === 'MAX')
defaultAutoArchiveDuration = resolveAutoArchiveMaxLimit(this.guild);
const newData = await this.client.api.channels(channel.id).patch({
data: {
@@ -324,18 +360,26 @@ class GuildChannelManager extends CachedManager {
user_limit: data.userLimit ?? channel.userLimit,
rtc_region: 'rtcRegion' in data ? data.rtcRegion : channel.rtcRegion,
video_quality_mode:
typeof data.videoQualityMode === 'string' ? VideoQualityModes[data.videoQualityMode] : data.videoQualityMode,
typeof data.videoQualityMode === 'string'
? VideoQualityModes[data.videoQualityMode]
: data.videoQualityMode,
parent_id: parentId,
lock_permissions: data.lockPermissions,
rate_limit_per_user: data.rateLimitPerUser,
default_auto_archive_duration: defaultAutoArchiveDuration,
permission_overwrites,
available_tags: data.availableTags?.map(availableTag => transformGuildForumTag(availableTag)),
default_reaction_emoji: data.defaultReactionEmoji && transformGuildDefaultReaction(data.defaultReactionEmoji),
available_tags: data.availableTags?.map((availableTag) =>
transformGuildForumTag(availableTag),
),
default_reaction_emoji:
data.defaultReactionEmoji &&
transformGuildDefaultReaction(data.defaultReactionEmoji),
default_thread_rate_limit_per_user: data.defaultThreadRateLimitPerUser,
flags: 'flags' in data ? ChannelFlags.resolve(data.flags) : undefined,
default_sort_order:
typeof data.defaultSortOrder === 'string' ? SortOrderTypes[data.defaultSortOrder] : data.defaultSortOrder,
typeof data.defaultSortOrder === 'string'
? SortOrderTypes[data.defaultSortOrder]
: data.defaultSortOrder,
},
reason,
});
@@ -357,7 +401,8 @@ class GuildChannelManager extends CachedManager {
*/
async setPosition(channel, position, { relative, reason } = {}) {
channel = this.resolve(channel);
if (!channel) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
if (!channel)
throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
const updatedChannels = await Util.setPosition(
channel,
position,
@@ -399,13 +444,18 @@ class GuildChannelManager extends CachedManager {
if (id) {
const data = await this.client.api.channels(id).get();
// Since this is the guild manager, throw if on a different guild
if (this.guild.id !== data.guild_id) throw new Error('GUILD_CHANNEL_UNOWNED');
if (this.guild.id !== data.guild_id)
throw new Error('GUILD_CHANNEL_UNOWNED');
return this.client.channels._add(data, this.guild, { cache });
}
const data = await this.client.api.guilds(this.guild.id).channels.get();
const channels = new Collection();
for (const channel of data) channels.set(channel.id, this.client.channels._add(channel, this.guild, { cache }));
for (const channel of data)
channels.set(
channel.id,
this.client.channels._add(channel, this.guild, { cache }),
);
return channels;
}
@@ -421,9 +471,13 @@ class GuildChannelManager extends CachedManager {
*/
async fetchWebhooks(channel) {
const id = this.resolveId(channel);
if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
if (!id)
throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
const data = await this.client.api.channels[id].webhooks.get();
return data.reduce((hooks, hook) => hooks.set(hook.id, new Webhook(this.client, hook)), new Collection());
return data.reduce(
(hooks, hook) => hooks.set(hook.id, new Webhook(this.client, hook)),
new Collection(),
);
}
/**
@@ -453,14 +507,17 @@ class GuildChannelManager extends CachedManager {
* .catch(console.error);
*/
async setPositions(channelPositions) {
channelPositions = channelPositions.map(r => ({
channelPositions = channelPositions.map((r) => ({
id: this.client.channels.resolveId(r.channel),
position: r.position,
lock_permissions: r.lockPermissions,
parent_id: typeof r.parent !== 'undefined' ? this.resolveId(r.parent) : undefined,
parent_id:
typeof r.parent !== 'undefined' ? this.resolveId(r.parent) : undefined,
}));
await this.client.api.guilds(this.guild.id).channels.patch({ data: channelPositions });
await this.client.api
.guilds(this.guild.id)
.channels.patch({ data: channelPositions });
return this.client.actions.GuildChannelsPositionUpdate.handle({
guild_id: this.guild.id,
channels: channelPositions,
@@ -480,7 +537,8 @@ class GuildChannelManager extends CachedManager {
*/
async delete(channel, reason) {
const id = this.resolveId(channel);
if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
if (!id)
throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
await this.client.api.channels(id).delete({ reason });
}
}

View File

@@ -56,17 +56,30 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
const data = { image: attachment, name };
if (roles) {
if (!Array.isArray(roles) && !(roles instanceof Collection)) {
throw new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true);
throw new TypeError(
'INVALID_TYPE',
'options.roles',
'Array or Collection of Roles or Snowflakes',
true,
);
}
data.roles = [];
for (const role of roles.values()) {
const resolvedRole = this.guild.roles.resolveId(role);
if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'options.roles', role);
if (!resolvedRole)
throw new TypeError(
'INVALID_ELEMENT',
'Array or Collection',
'options.roles',
role,
);
data.roles.push(resolvedRole);
}
}
const emoji = await this.client.api.guilds(this.guild.id).emojis.post({ data, reason });
const emoji = await this.client.api
.guilds(this.guild.id)
.emojis.post({ data, reason });
return this.client.actions.GuildEmojiCreate.handle(this.guild, emoji).emoji;
}
@@ -92,7 +105,10 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
const existing = this.cache.get(id);
if (existing) return existing;
}
const emoji = await this.client.api.guilds(this.guild.id).emojis(id).get();
const emoji = await this.client.api
.guilds(this.guild.id)
.emojis(id)
.get();
return this._add(emoji, cache);
}
@@ -110,7 +126,8 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
*/
async delete(emoji, reason) {
const id = this.resolveId(emoji);
if (!id) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
if (!id)
throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
await this.client.api.guilds(this.guild.id).emojis(id).delete({ reason });
}
@@ -123,8 +140,9 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
*/
async edit(emoji, data, reason) {
const id = this.resolveId(emoji);
if (!id) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
const roles = data.roles?.map(r => this.guild.roles.resolveId(r));
if (!id)
throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
const roles = data.roles?.map((r) => this.guild.roles.resolveId(r));
const newData = await this.client.api
.guilds(this.guild.id)
.emojis(id)
@@ -151,7 +169,8 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
*/
async fetchAuthor(emoji) {
emoji = this.resolve(emoji);
if (!emoji) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
if (!emoji)
throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
if (emoji.managed) {
throw new Error('EMOJI_MANAGED');
}
@@ -159,10 +178,16 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
const { me } = this.guild.members;
if (!me) throw new Error('GUILD_UNCACHED_ME');
if (!me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS)) {
throw new Error('MISSING_MANAGE_EMOJIS_AND_STICKERS_PERMISSION', this.guild);
throw new Error(
'MISSING_MANAGE_EMOJIS_AND_STICKERS_PERMISSION',
this.guild,
);
}
const data = await this.client.api.guilds(this.guild.id).emojis(emoji.id).get();
const data = await this.client.api
.guilds(this.guild.id)
.emojis(emoji.id)
.get();
emoji._patch(data);
return emoji.author;
}

View File

@@ -31,7 +31,9 @@ class GuildEmojiRoleManager extends DataManager {
* @readonly
*/
get cache() {
return this.guild.roles.cache.filter(role => this.emoji._roles.includes(role.id));
return this.guild.roles.cache.filter((role) =>
this.emoji._roles.includes(role.id),
);
}
/**
@@ -40,13 +42,19 @@ class GuildEmojiRoleManager extends DataManager {
* @returns {Promise<GuildEmoji>}
*/
async add(roleOrRoles) {
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection))
roleOrRoles = [roleOrRoles];
const resolvedRoles = [];
for (const role of roleOrRoles.values()) {
const resolvedRole = this.guild.roles.resolveId(role);
if (!resolvedRole) {
throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role);
throw new TypeError(
'INVALID_ELEMENT',
'Array or Collection',
'roles',
role,
);
}
resolvedRoles.push(resolvedRole);
}
@@ -61,18 +69,26 @@ class GuildEmojiRoleManager extends DataManager {
* @returns {Promise<GuildEmoji>}
*/
async remove(roleOrRoles) {
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection))
roleOrRoles = [roleOrRoles];
const resolvedRoleIds = [];
for (const role of roleOrRoles.values()) {
const roleId = this.guild.roles.resolveId(role);
if (!roleId) {
throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role);
throw new TypeError(
'INVALID_ELEMENT',
'Array or Collection',
'roles',
role,
);
}
resolvedRoleIds.push(roleId);
}
const newRoles = [...this.cache.keys()].filter(id => !resolvedRoleIds.includes(id));
const newRoles = [...this.cache.keys()].filter(
(id) => !resolvedRoleIds.includes(id),
);
return this.set(newRoles);
}

View File

@@ -3,7 +3,11 @@
const ThreadManager = require('./ThreadManager');
const { TypeError } = require('../errors');
const MessagePayload = require('../structures/MessagePayload');
const { resolveAutoArchiveMaxLimit, getUploadURL, uploadFile } = require('../util/Util');
const {
resolveAutoArchiveMaxLimit,
getUploadURL,
uploadFile,
} = require('../util/Util');
/**
* Manages API methods for threads in forum channels and stores their cache.
@@ -72,7 +76,7 @@ class GuildForumThreadManager extends ThreadManager {
// New API
const attachments = await getUploadURL(this.client, this.channel.id, files);
const requestPromises = attachments.map(async attachment => {
const requestPromises = attachments.map(async (attachment) => {
await uploadFile(files[attachment.id].file, attachment.upload_url);
return {
id: attachment.id,
@@ -86,20 +90,23 @@ class GuildForumThreadManager extends ThreadManager {
const attachmentsData = await Promise.all(requestPromises);
attachmentsData.sort((a, b) => parseInt(a.id) - parseInt(b.id));
if (autoArchiveDuration === 'MAX') autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
if (autoArchiveDuration === 'MAX')
autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
const post_data = await this.client.api.channels(this.channel.id).threads.post({
data: {
name,
auto_archive_duration: autoArchiveDuration,
rate_limit_per_user: rateLimitPerUser,
applied_tags: appliedTags,
message: body,
attachments: attachmentsData,
},
files: [],
reason,
});
const post_data = await this.client.api
.channels(this.channel.id)
.threads.post({
data: {
name,
auto_archive_duration: autoArchiveDuration,
rate_limit_per_user: rateLimitPerUser,
applied_tags: appliedTags,
message: body,
attachments: attachmentsData,
},
files: [],
reason,
});
return this.client.actions.ThreadCreate.handle(post_data).thread;
}

View File

@@ -156,12 +156,18 @@ class GuildInviteManager extends CachedManager {
async _fetchMany(cache) {
const data = await this.client.api.guilds(this.guild.id).invites.get();
return data.reduce((col, invite) => col.set(invite.code, this._add(invite, cache)), new Collection());
return data.reduce(
(col, invite) => col.set(invite.code, this._add(invite, cache)),
new Collection(),
);
}
async _fetchChannelMany(channelId, cache) {
const data = await this.client.api.channels(channelId).invites.get();
return data.reduce((col, invite) => col.set(invite.code, this._add(invite, cache)), new Collection());
return data.reduce(
(col, invite) => col.set(invite.code, this._add(invite, cache)),
new Collection(),
);
}
/**
@@ -177,7 +183,16 @@ class GuildInviteManager extends CachedManager {
*/
async create(
channel,
{ temporary = false, maxAge = 86400, maxUses = 0, unique, targetUser, targetApplication, targetType, reason } = {},
{
temporary = false,
maxAge = 86400,
maxUses = 0,
unique,
targetUser,
targetApplication,
targetType,
reason,
} = {},
) {
const id = this.guild.channels.resolveId(channel);
if (!id) throw new Error('GUILD_CHANNEL_RESOLVE');
@@ -189,7 +204,10 @@ class GuildInviteManager extends CachedManager {
max_uses: maxUses,
unique,
target_user_id: this.client.users.resolveId(targetUser),
target_application_id: targetApplication?.id ?? targetApplication?.applicationId ?? targetApplication,
target_application_id:
targetApplication?.id ??
targetApplication?.applicationId ??
targetApplication,
target_type: targetType,
},
reason,

View File

@@ -187,13 +187,18 @@ class GuildManager extends CachedManager {
verificationLevel = VerificationLevels[verificationLevel];
}
if (typeof defaultMessageNotifications === 'string') {
defaultMessageNotifications = DefaultMessageNotificationLevels[defaultMessageNotifications];
defaultMessageNotifications =
DefaultMessageNotificationLevels[defaultMessageNotifications];
}
if (typeof explicitContentFilter === 'string') {
explicitContentFilter = ExplicitContentFilterLevels[explicitContentFilter];
explicitContentFilter =
ExplicitContentFilterLevels[explicitContentFilter];
}
for (const channel of channels) {
channel.type &&= typeof channel.type === 'number' ? channel.type : ChannelTypes[channel.type];
channel.type &&=
typeof channel.type === 'number'
? channel.type
: ChannelTypes[channel.type];
channel.parent_id = channel.parentId;
delete channel.parentId;
channel.user_limit = channel.userLimit;
@@ -242,10 +247,11 @@ class GuildManager extends CachedManager {
},
});
if (this.client.guilds.cache.has(data.id)) return this.client.guilds.cache.get(data.id);
if (this.client.guilds.cache.has(data.id))
return this.client.guilds.cache.get(data.id);
return new Promise(resolve => {
const handleGuild = guild => {
return new Promise((resolve) => {
const handleGuild = (guild) => {
if (guild.id === data.id) {
clearTimeout(timeout);
this.client.removeListener(Events.GUILD_CREATE, handleGuild);
@@ -293,12 +299,19 @@ class GuildManager extends CachedManager {
if (existing) return existing;
}
const data = await this.client.api.guilds(id).get({ query: { with_counts: options.withCounts ?? true } });
const data = await this.client.api
.guilds(id)
.get({ query: { with_counts: options.withCounts ?? true } });
return this._add(data, options.cache);
}
const data = await this.client.api.users('@me').guilds.get({ query: options });
return data.reduce((coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)), new Collection());
const data = await this.client.api
.users('@me')
.guilds.get({ query: options });
return data.reduce(
(coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)),
new Collection(),
);
}
/**
@@ -319,8 +332,10 @@ class GuildManager extends CachedManager {
const data = await this.client.api.guilds(guildId)['incident-actions'].put({
data: {
invites_disabled_until: invitesDisabledUntil && new Date(invitesDisabledUntil).toISOString(),
dms_disabled_until: dmsDisabledUntil && new Date(dmsDisabledUntil).toISOString(),
invites_disabled_until:
invitesDisabledUntil && new Date(invitesDisabledUntil).toISOString(),
dms_disabled_until:
dmsDisabledUntil && new Date(dmsDisabledUntil).toISOString(),
},
});

View File

@@ -106,20 +106,41 @@ class GuildMemberManager extends CachedManager {
deaf: options.deaf,
};
if (options.roles) {
if (!Array.isArray(options.roles) && !(options.roles instanceof Collection)) {
throw new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true);
if (
!Array.isArray(options.roles) &&
!(options.roles instanceof Collection)
) {
throw new TypeError(
'INVALID_TYPE',
'options.roles',
'Array or Collection of Roles or Snowflakes',
true,
);
}
const resolvedRoles = [];
for (const role of options.roles.values()) {
const resolvedRole = this.guild.roles.resolveId(role);
if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'options.roles', role);
if (!resolvedRole)
throw new TypeError(
'INVALID_ELEMENT',
'Array or Collection',
'options.roles',
role,
);
resolvedRoles.push(resolvedRole);
}
resolvedOptions.roles = resolvedRoles;
}
const data = await this.client.api.guilds(this.guild.id).members(userId).put({ data: resolvedOptions });
const data = await this.client.api
.guilds(this.guild.id)
.members(userId)
.put({ data: resolvedOptions });
// Data is an empty buffer if the member is already part of the guild.
return data instanceof Buffer ? (options.fetchWhenExisting === false ? null : this.fetch(userId)) : this._add(data);
return data instanceof Buffer
? options.fetchWhenExisting === false
? null
: this.fetch(userId)
: this._add(data);
}
/**
@@ -207,12 +228,13 @@ class GuildMemberManager extends CachedManager {
if (user) return this._fetchSingle({ user, cache: true });
if (options.user) {
if (Array.isArray(options.user)) {
options.user = options.user.map(u => this.client.users.resolveId(u));
options.user = options.user.map((u) => this.client.users.resolveId(u));
return this._fetchMany(options);
} else {
options.user = this.client.users.resolveId(options.user);
}
if (!options.limit && !options.withPresences) return this._fetchSingle(options);
if (!options.limit && !options.withPresences)
return this._fetchSingle(options);
}
return this._fetchMany(options);
}
@@ -240,8 +262,13 @@ class GuildMemberManager extends CachedManager {
* @returns {Promise<Collection<Snowflake, GuildMember>>}
*/
async search({ query, limit = 1, cache = true } = {}) {
const data = await this.client.api.guilds(this.guild.id).members.search.get({ query: { query, limit } });
return data.reduce((col, member) => col.set(member.user.id, this._add(member, cache)), new Collection());
const data = await this.client.api
.guilds(this.guild.id)
.members.search.get({ query: { query, limit } });
return data.reduce(
(col, member) => col.set(member.user.id, this._add(member, cache)),
new Collection(),
);
}
/**
@@ -286,10 +313,13 @@ class GuildMemberManager extends CachedManager {
_data.channel_id = null;
_data.channel = undefined;
}
_data.roles &&= _data.roles.map(role => (role instanceof Role ? role.id : role));
_data.roles &&= _data.roles.map((role) =>
role instanceof Role ? role.id : role,
);
_data.communication_disabled_until =
_data.communicationDisabledUntil && new Date(_data.communicationDisabledUntil).toISOString();
_data.communicationDisabledUntil &&
new Date(_data.communicationDisabledUntil).toISOString();
_data.flags = _data.flags && GuildMemberFlags.resolve(_data.flags);
@@ -304,7 +334,10 @@ class GuildMemberManager extends CachedManager {
let endpoint = this.client.api.guilds(this.guild.id);
if (id === this.client.user.id) {
const keys = Object.keys(data);
if (keys.length === 1 && ['nick', 'avatar', 'banner', 'bio'].includes(keys[0])) {
if (
keys.length === 1 &&
['nick', 'avatar', 'banner', 'bio'].includes(keys[0])
) {
endpoint = endpoint.members('@me');
} else {
endpoint = endpoint.members(id);
@@ -351,7 +384,13 @@ class GuildMemberManager extends CachedManager {
* .then(pruned => console.log(`I just pruned ${pruned} people!`))
* .catch(console.error);
*/
async prune({ days = 7, dry = false, count: compute_prune_count = true, roles = [], reason } = {}) {
async prune({
days = 7,
dry = false,
count: compute_prune_count = true,
roles = [],
reason,
} = {}) {
if (typeof days !== 'number') throw new TypeError('PRUNE_DAYS_TYPE');
const query = { days };
@@ -440,7 +479,10 @@ class GuildMemberManager extends CachedManager {
if (existing && !existing.partial) return existing;
}
const data = await this.client.api.guilds(this.guild.id).members(user).get();
const data = await this.client.api
.guilds(this.guild.id)
.members(user)
.get();
return this._add(data, cache);
}
@@ -455,7 +497,11 @@ class GuildMemberManager extends CachedManager {
const userId = this.resolveId(user);
const roleId = this.guild.roles.resolveId(role);
await this.client.api.guilds(this.guild.id).members(userId).roles(roleId).put({ reason });
await this.client.api
.guilds(this.guild.id)
.members(userId)
.roles(roleId)
.put({ reason });
return this.resolve(user) ?? this.client.users.resolve(user) ?? userId;
}
@@ -471,7 +517,11 @@ class GuildMemberManager extends CachedManager {
const userId = this.resolveId(user);
const roleId = this.guild.roles.resolveId(role);
await this.client.api.guilds(this.guild.id).members(userId).roles(roleId).delete({ reason });
await this.client.api
.guilds(this.guild.id)
.members(userId)
.roles(roleId)
.delete({ reason });
return this.resolve(user) ?? this.client.users.resolve(user) ?? userId;
}
@@ -483,7 +533,7 @@ class GuildMemberManager extends CachedManager {
* @returns {Promise<Collection<Snowflake, GuildMember>>}
*/
fetchByMemberSafety(timeout = 15_000) {
return new Promise(resolve => {
return new Promise((resolve) => {
const nonce = SnowflakeUtil.generate();
const fetchedMembers = new Collection();
let timeout_ = setTimeout(() => {
@@ -556,12 +606,17 @@ class GuildMemberManager extends CachedManager {
for (const member of members.values()) {
fetchedMembers.set(member.id, member);
}
if (members.size < 1_000 || (limit && fetchedMembers.size >= limit) || i === chunk.count) {
if (
members.size < 1_000 ||
(limit && fetchedMembers.size >= limit) ||
i === chunk.count
) {
clearTimeout(timeout);
this.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler);
this.client.decrementMaxListeners();
let fetched = fetchedMembers;
if (user_ids && !Array.isArray(user_ids) && fetched.size) fetched = fetched.first();
if (user_ids && !Array.isArray(user_ids) && fetched.size)
fetched = fetched.first();
resolve(fetched);
}
};

View File

@@ -33,7 +33,9 @@ class GuildMemberRoleManager extends DataManager {
*/
get cache() {
const everyone = this.guild.roles.everyone;
return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone);
return this.guild.roles.cache
.filter((role) => this.member._roles.includes(role.id))
.set(everyone.id, everyone);
}
/**
@@ -42,9 +44,11 @@ class GuildMemberRoleManager extends DataManager {
* @readonly
*/
get hoist() {
const hoistedRoles = this.cache.filter(role => role.hoist);
const hoistedRoles = this.cache.filter((role) => role.hoist);
if (!hoistedRoles.size) return null;
return hoistedRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
return hoistedRoles.reduce((prev, role) =>
role.comparePositionTo(prev) > 0 ? role : prev,
);
}
/**
@@ -53,9 +57,13 @@ class GuildMemberRoleManager extends DataManager {
* @readonly
*/
get icon() {
const iconRoles = this.cache.filter(role => role.icon || role.unicodeEmoji);
const iconRoles = this.cache.filter(
(role) => role.icon || role.unicodeEmoji,
);
if (!iconRoles.size) return null;
return iconRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
return iconRoles.reduce((prev, role) =>
role.comparePositionTo(prev) > 0 ? role : prev,
);
}
/**
@@ -64,9 +72,11 @@ class GuildMemberRoleManager extends DataManager {
* @readonly
*/
get color() {
const coloredRoles = this.cache.filter(role => role.colors.primaryColor);
const coloredRoles = this.cache.filter((role) => role.colors.primaryColor);
if (!coloredRoles.size) return null;
return coloredRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
return coloredRoles.reduce((prev, role) =>
role.comparePositionTo(prev) > 0 ? role : prev,
);
}
/**
@@ -75,7 +85,10 @@ class GuildMemberRoleManager extends DataManager {
* @readonly
*/
get highest() {
return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first());
return this.cache.reduce(
(prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev),
this.cache.first(),
);
}
/**
@@ -84,7 +97,7 @@ class GuildMemberRoleManager extends DataManager {
* @readonly
*/
get premiumSubscriberRole() {
return this.cache.find(role => role.tags?.premiumSubscriberRole) ?? null;
return this.cache.find((role) => role.tags?.premiumSubscriberRole) ?? null;
}
/**
@@ -95,7 +108,10 @@ class GuildMemberRoleManager extends DataManager {
*/
get botRole() {
if (!this.member.user.bot) return null;
return this.cache.find(role => role.tags?.botId === this.member.user.id) ?? null;
return (
this.cache.find((role) => role.tags?.botId === this.member.user.id) ??
null
);
}
/**
@@ -111,7 +127,13 @@ class GuildMemberRoleManager extends DataManager {
const resolvedRoles = [];
for (const role of roleOrRoles.values()) {
const resolvedRole = this.guild.roles.resolveId(role);
if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role);
if (!resolvedRole)
throw new TypeError(
'INVALID_ELEMENT',
'Array or Collection',
'roles',
role,
);
resolvedRoles.push(resolvedRole);
}
@@ -120,10 +142,16 @@ class GuildMemberRoleManager extends DataManager {
} else {
roleOrRoles = this.guild.roles.resolveId(roleOrRoles);
if (roleOrRoles === null) {
throw new TypeError('INVALID_TYPE', 'roles', 'Role, Snowflake or Array or Collection of Roles or Snowflakes');
throw new TypeError(
'INVALID_TYPE',
'roles',
'Role, Snowflake or Array or Collection of Roles or Snowflakes',
);
}
await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles].put({ reason });
await this.client.api.guilds[this.guild.id].members[this.member.id].roles[
roleOrRoles
].put({ reason });
const clone = this.member._clone();
clone._roles = [...this.cache.keys(), roleOrRoles];
@@ -144,22 +172,36 @@ class GuildMemberRoleManager extends DataManager {
const resolvedRoles = [];
for (const role of roleOrRoles.values()) {
const resolvedRole = this.guild.roles.resolveId(role);
if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role);
if (!resolvedRole)
throw new TypeError(
'INVALID_ELEMENT',
'Array or Collection',
'roles',
role,
);
resolvedRoles.push(resolvedRole);
}
const newRoles = this.cache.filter(role => !resolvedRoles.includes(role.id));
const newRoles = this.cache.filter(
(role) => !resolvedRoles.includes(role.id),
);
return this.set(newRoles, reason);
} else {
roleOrRoles = this.guild.roles.resolveId(roleOrRoles);
if (roleOrRoles === null) {
throw new TypeError('INVALID_TYPE', 'roles', 'Role, Snowflake or Array or Collection of Roles or Snowflakes');
throw new TypeError(
'INVALID_TYPE',
'roles',
'Role, Snowflake or Array or Collection of Roles or Snowflakes',
);
}
await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles].delete({ reason });
await this.client.api.guilds[this.guild.id].members[this.member.id].roles[
roleOrRoles
].delete({ reason });
const clone = this.member._clone();
const newRoles = this.cache.filter(role => role.id !== roleOrRoles);
const newRoles = this.cache.filter((role) => role.id !== roleOrRoles);
clone._roles = [...newRoles.keys()];
return clone;
}

View File

@@ -4,7 +4,11 @@ const { Collection } = require('@discordjs/collection');
const CachedManager = require('./CachedManager');
const { TypeError, Error } = require('../errors');
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
const { PrivacyLevels, GuildScheduledEventEntityTypes, GuildScheduledEventStatuses } = require('../util/Constants');
const {
PrivacyLevels,
GuildScheduledEventEntityTypes,
GuildScheduledEventStatuses,
} = require('../util/Constants');
const DataResolver = require('../util/DataResolver');
const Util = require('../util/Util');
@@ -82,7 +86,8 @@ class GuildScheduledEventManager extends CachedManager {
* @returns {Promise<GuildScheduledEvent>}
*/
async create(options) {
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
if (typeof options !== 'object')
throw new TypeError('INVALID_TYPE', 'options', 'object', true);
let {
privacyLevel,
entityType,
@@ -97,8 +102,10 @@ class GuildScheduledEventManager extends CachedManager {
recurrenceRule,
} = options;
if (typeof privacyLevel === 'string') privacyLevel = PrivacyLevels[privacyLevel];
if (typeof entityType === 'string') entityType = GuildScheduledEventEntityTypes[entityType];
if (typeof privacyLevel === 'string')
privacyLevel = PrivacyLevels[privacyLevel];
if (typeof entityType === 'string')
entityType = GuildScheduledEventEntityTypes[entityType];
let entity_metadata, channel_id;
if (entityType === GuildScheduledEventEntityTypes.EXTERNAL) {
@@ -107,24 +114,31 @@ class GuildScheduledEventManager extends CachedManager {
} else {
channel_id = this.guild.channels.resolveId(channel);
if (!channel_id) throw new Error('GUILD_VOICE_CHANNEL_RESOLVE');
entity_metadata = typeof entityMetadata === 'undefined' ? entityMetadata : null;
entity_metadata =
typeof entityMetadata === 'undefined' ? entityMetadata : null;
}
const data = await this.client.api.guilds(this.guild.id, 'scheduled-events').post({
data: {
channel_id,
name,
privacy_level: privacyLevel,
scheduled_start_time: new Date(scheduledStartTime).toISOString(),
scheduled_end_time: scheduledEndTime ? new Date(scheduledEndTime).toISOString() : scheduledEndTime,
description,
image: image && (await DataResolver.resolveImage(image)),
entity_type: entityType,
entity_metadata,
recurrence_rule: recurrenceRule && Util.transformGuildScheduledEventRecurrenceRule(recurrenceRule),
},
reason,
});
const data = await this.client.api
.guilds(this.guild.id, 'scheduled-events')
.post({
data: {
channel_id,
name,
privacy_level: privacyLevel,
scheduled_start_time: new Date(scheduledStartTime).toISOString(),
scheduled_end_time: scheduledEndTime
? new Date(scheduledEndTime).toISOString()
: scheduledEndTime,
description,
image: image && (await DataResolver.resolveImage(image)),
entity_type: entityType,
entity_metadata,
recurrence_rule:
recurrenceRule &&
Util.transformGuildScheduledEventRecurrenceRule(recurrenceRule),
},
reason,
});
return this._add(data);
}
@@ -171,7 +185,10 @@ class GuildScheduledEventManager extends CachedManager {
return data.reduce(
(coll, rawGuildScheduledEventData) =>
coll.set(rawGuildScheduledEventData.id, this._add(rawGuildScheduledEventData, options.cache)),
coll.set(
rawGuildScheduledEventData.id,
this._add(rawGuildScheduledEventData, options.cache),
),
new Collection(),
);
}
@@ -204,9 +221,11 @@ class GuildScheduledEventManager extends CachedManager {
*/
async edit(guildScheduledEvent, options) {
const guildScheduledEventId = this.resolveId(guildScheduledEvent);
if (!guildScheduledEventId) throw new Error('GUILD_SCHEDULED_EVENT_RESOLVE');
if (!guildScheduledEventId)
throw new Error('GUILD_SCHEDULED_EVENT_RESOLVE');
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
if (typeof options !== 'object')
throw new TypeError('INVALID_TYPE', 'options', 'object', true);
let {
privacyLevel,
entityType,
@@ -222,9 +241,12 @@ class GuildScheduledEventManager extends CachedManager {
recurrenceRule,
} = options;
if (typeof privacyLevel === 'string') privacyLevel = PrivacyLevels[privacyLevel];
if (typeof entityType === 'string') entityType = GuildScheduledEventEntityTypes[entityType];
if (typeof status === 'string') status = GuildScheduledEventStatuses[status];
if (typeof privacyLevel === 'string')
privacyLevel = PrivacyLevels[privacyLevel];
if (typeof entityType === 'string')
entityType = GuildScheduledEventEntityTypes[entityType];
if (typeof status === 'string')
status = GuildScheduledEventStatuses[status];
let entity_metadata;
if (entityMetadata) {
@@ -233,22 +255,33 @@ class GuildScheduledEventManager extends CachedManager {
};
}
const data = await this.client.api.guilds(this.guild.id, 'scheduled-events', guildScheduledEventId).patch({
data: {
channel_id: typeof channel === 'undefined' ? channel : this.guild.channels.resolveId(channel),
name,
privacy_level: privacyLevel,
scheduled_start_time: scheduledStartTime ? new Date(scheduledStartTime).toISOString() : undefined,
scheduled_end_time: scheduledEndTime ? new Date(scheduledEndTime).toISOString() : scheduledEndTime,
description,
entity_type: entityType,
status,
image: image && (await DataResolver.resolveImage(image)),
entity_metadata,
recurrence_rule: recurrenceRule && Util.transformGuildScheduledEventRecurrenceRule(recurrenceRule),
},
reason,
});
const data = await this.client.api
.guilds(this.guild.id, 'scheduled-events', guildScheduledEventId)
.patch({
data: {
channel_id:
typeof channel === 'undefined'
? channel
: this.guild.channels.resolveId(channel),
name,
privacy_level: privacyLevel,
scheduled_start_time: scheduledStartTime
? new Date(scheduledStartTime).toISOString()
: undefined,
scheduled_end_time: scheduledEndTime
? new Date(scheduledEndTime).toISOString()
: scheduledEndTime,
description,
entity_type: entityType,
status,
image: image && (await DataResolver.resolveImage(image)),
entity_metadata,
recurrence_rule:
recurrenceRule &&
Util.transformGuildScheduledEventRecurrenceRule(recurrenceRule),
},
reason,
});
return this._add(data);
}
@@ -260,9 +293,12 @@ class GuildScheduledEventManager extends CachedManager {
*/
async delete(guildScheduledEvent) {
const guildScheduledEventId = this.resolveId(guildScheduledEvent);
if (!guildScheduledEventId) throw new Error('GUILD_SCHEDULED_EVENT_RESOLVE');
if (!guildScheduledEventId)
throw new Error('GUILD_SCHEDULED_EVENT_RESOLVE');
await this.client.api.guilds(this.guild.id, 'scheduled-events', guildScheduledEventId).delete();
await this.client.api
.guilds(this.guild.id, 'scheduled-events', guildScheduledEventId)
.delete();
}
/**
@@ -291,20 +327,25 @@ class GuildScheduledEventManager extends CachedManager {
*/
async fetchSubscribers(guildScheduledEvent, options = {}) {
const guildScheduledEventId = this.resolveId(guildScheduledEvent);
if (!guildScheduledEventId) throw new Error('GUILD_SCHEDULED_EVENT_RESOLVE');
if (!guildScheduledEventId)
throw new Error('GUILD_SCHEDULED_EVENT_RESOLVE');
let { limit, withMember, before, after } = options;
const data = await this.client.api.guilds(this.guild.id, 'scheduled-events', guildScheduledEventId).users.get({
query: { limit, with_member: withMember, before, after },
});
const data = await this.client.api
.guilds(this.guild.id, 'scheduled-events', guildScheduledEventId)
.users.get({
query: { limit, with_member: withMember, before, after },
});
return data.reduce(
(coll, rawData) =>
coll.set(rawData.user.id, {
guildScheduledEventId: rawData.guild_scheduled_event_id,
user: this.client.users._add(rawData.user),
member: rawData.member ? this.guild.members._add({ ...rawData.member, user: rawData.user }) : null,
member: rawData.member
? this.guild.members._add({ ...rawData.member, user: rawData.user })
: null,
}),
new Collection(),
);

View File

@@ -66,7 +66,8 @@ class GuildStickerManager extends CachedManager {
const sticker = await this.client.api
.guilds(this.guild.id)
.stickers.post({ data, files: [file], reason, dontUsePayloadJSON: true });
return this.client.actions.GuildStickerCreate.handle(this.guild, sticker).sticker;
return this.client.actions.GuildStickerCreate.handle(this.guild, sticker)
.sticker;
}
/**
@@ -103,12 +104,16 @@ class GuildStickerManager extends CachedManager {
*/
async edit(sticker, data, reason) {
const stickerId = this.resolveId(sticker);
if (!stickerId) throw new TypeError('INVALID_TYPE', 'sticker', 'StickerResolvable');
if (!stickerId)
throw new TypeError('INVALID_TYPE', 'sticker', 'StickerResolvable');
const d = await this.client.api.guilds(this.guild.id).stickers(stickerId).patch({
data,
reason,
});
const d = await this.client.api
.guilds(this.guild.id)
.stickers(stickerId)
.patch({
data,
reason,
});
const existing = this.cache.get(stickerId);
if (existing) {
@@ -127,9 +132,13 @@ class GuildStickerManager extends CachedManager {
*/
async delete(sticker, reason) {
sticker = this.resolveId(sticker);
if (!sticker) throw new TypeError('INVALID_TYPE', 'sticker', 'StickerResolvable');
if (!sticker)
throw new TypeError('INVALID_TYPE', 'sticker', 'StickerResolvable');
await this.client.api.guilds(this.guild.id).stickers(sticker).delete({ reason });
await this.client.api
.guilds(this.guild.id)
.stickers(sticker)
.delete({ reason });
}
/**
@@ -154,12 +163,17 @@ class GuildStickerManager extends CachedManager {
const existing = this.cache.get(id);
if (existing) return existing;
}
const sticker = await this.client.api.guilds(this.guild.id).stickers(id).get();
const sticker = await this.client.api
.guilds(this.guild.id)
.stickers(id)
.get();
return this._add(sticker, cache);
}
const data = await this.client.api.guilds(this.guild.id).stickers.get();
return new Collection(data.map(sticker => [sticker.id, this._add(sticker, cache)]));
return new Collection(
data.map((sticker) => [sticker.id, this._add(sticker, cache)]),
);
}
/**
@@ -169,8 +183,12 @@ class GuildStickerManager extends CachedManager {
*/
async fetchUser(sticker) {
sticker = this.resolve(sticker);
if (!sticker) throw new TypeError('INVALID_TYPE', 'sticker', 'StickerResolvable');
const data = await this.client.api.guilds(this.guild.id).stickers(sticker.id).get();
if (!sticker)
throw new TypeError('INVALID_TYPE', 'sticker', 'StickerResolvable');
const data = await this.client.api
.guilds(this.guild.id)
.stickers(sticker.id)
.get();
sticker._patch(data);
return sticker.user;
}

View File

@@ -66,26 +66,42 @@ class GuildTextThreadManager extends ThreadManager {
} = {}) {
let path = this.client.api.channels(this.channel.id);
if (type && typeof type !== 'string' && typeof type !== 'number') {
throw new TypeError('INVALID_TYPE', 'type', 'ThreadChannelType or Number');
throw new TypeError(
'INVALID_TYPE',
'type',
'ThreadChannelType or Number',
);
}
let resolvedType =
this.channel.type === 'GUILD_NEWS' ? ChannelTypes.GUILD_NEWS_THREAD : ChannelTypes.GUILD_PUBLIC_THREAD;
this.channel.type === 'GUILD_NEWS'
? ChannelTypes.GUILD_NEWS_THREAD
: ChannelTypes.GUILD_PUBLIC_THREAD;
if (startMessage) {
const startMessageId = this.channel.messages.resolveId(startMessage);
if (!startMessageId) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable');
if (!startMessageId)
throw new TypeError(
'INVALID_TYPE',
'startMessage',
'MessageResolvable',
);
path = path.messages(startMessageId);
} else if (this.channel.type !== 'GUILD_NEWS') {
resolvedType = typeof type === 'string' ? ChannelTypes[type] : type ?? resolvedType;
resolvedType =
typeof type === 'string' ? ChannelTypes[type] : (type ?? resolvedType);
}
if (autoArchiveDuration === 'MAX') autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
if (autoArchiveDuration === 'MAX')
autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
const data = await path.threads.post({
data: {
name,
auto_archive_duration: autoArchiveDuration,
type: resolvedType,
invitable: resolvedType === ChannelTypes.GUILD_PRIVATE_THREAD ? invitable : undefined,
invitable:
resolvedType === ChannelTypes.GUILD_PRIVATE_THREAD
? invitable
: undefined,
rate_limit_per_user: rateLimitPerUser,
},
reason,

View File

@@ -66,7 +66,9 @@ class MessageManager extends CachedManager {
* .catch(console.error);
*/
fetch(message, { cache = true, force = false } = {}) {
return typeof message === 'string' ? this._fetchId(message, cache, force) : this._fetchMany(message, cache);
return typeof message === 'string'
? this._fetchId(message, cache, force)
: this._fetchMany(message, cache);
}
/**
@@ -82,11 +84,14 @@ class MessageManager extends CachedManager {
* .catch(console.error);
*/
async fetchPinned(cache = true) {
const data = await this.client.api.channels[this.channel.id].messages.pins.get({
const data = await this.client.api.channels[
this.channel.id
].messages.pins.get({
query: { limit: 50 },
});
const messages = new Collection();
for (const message of data?.items || []) messages.set(message.id, this._add(message, cache));
for (const message of data?.items || [])
messages.set(message.id, this._add(message, cache));
return messages;
}
@@ -123,18 +128,26 @@ class MessageManager extends CachedManager {
*/
async edit(message, options) {
const messageId = this.resolveId(message);
if (!messageId) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
if (!messageId)
throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
const { data, files } = await (options instanceof MessagePayload
? options
: MessagePayload.create(message instanceof Message ? message : this, options)
: MessagePayload.create(
message instanceof Message ? message : this,
options,
)
)
.resolveData()
.resolveFiles();
// New API
const attachments = await Util.getUploadURL(this.client, this.channel.id, files);
const requestPromises = attachments.map(async attachment => {
const attachments = await Util.getUploadURL(
this.client,
this.channel.id,
files,
);
const requestPromises = attachments.map(async (attachment) => {
await Util.uploadFile(files[attachment.id].file, attachment.upload_url);
return {
id: attachment.id,
@@ -150,7 +163,9 @@ class MessageManager extends CachedManager {
data.attachments = attachmentsData;
// Empty Files
const d = await this.client.api.channels[this.channel.id].messages[messageId].patch({ data });
const d = await this.client.api.channels[this.channel.id].messages[
messageId
].patch({ data });
const existing = this.cache.get(messageId);
if (existing) {
@@ -168,9 +183,13 @@ class MessageManager extends CachedManager {
*/
async crosspost(message) {
message = this.resolveId(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
if (!message)
throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
const data = await this.client.api.channels(this.channel.id).messages(message).crosspost.post();
const data = await this.client.api
.channels(this.channel.id)
.messages(message)
.crosspost.post();
return this.cache.get(data.id) ?? this._add(data);
}
@@ -182,9 +201,13 @@ class MessageManager extends CachedManager {
*/
async pin(message, reason) {
message = this.resolveId(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
if (!message)
throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
await this.client.api.channels(this.channel.id).messages.pins(message).put({ reason });
await this.client.api
.channels(this.channel.id)
.messages.pins(message)
.put({ reason });
}
/**
@@ -195,9 +218,13 @@ class MessageManager extends CachedManager {
*/
async unpin(message, reason) {
message = this.resolveId(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
if (!message)
throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
await this.client.api.channels(this.channel.id).messages.pins(message).delete({ reason });
await this.client.api
.channels(this.channel.id)
.messages.pins(message)
.delete({ reason });
}
/**
@@ -209,10 +236,12 @@ class MessageManager extends CachedManager {
*/
async react(message, emoji, burst = false) {
message = this.resolveId(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
if (!message)
throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
emoji = Util.resolvePartialEmoji(emoji);
if (!emoji) throw new TypeError('EMOJI_TYPE', 'emoji', 'EmojiIdentifierResolvable');
if (!emoji)
throw new TypeError('EMOJI_TYPE', 'emoji', 'EmojiIdentifierResolvable');
const emojiId = emoji.id
? `${emoji.animated ? 'a:' : ''}${emoji.name}:${emoji.id}`
@@ -237,7 +266,8 @@ class MessageManager extends CachedManager {
*/
async delete(message) {
message = this.resolveId(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
if (!message)
throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
await this.client.api.channels(this.channel.id).messages(message).delete();
}
@@ -257,8 +287,10 @@ class MessageManager extends CachedManager {
},
cache,
)
.then(data_ =>
data_.has(messageId) ? resolve(data_.get(messageId)) : reject(new Error('MESSAGE_ID_NOT_FOUND')),
.then((data_) =>
data_.has(messageId)
? resolve(data_.get(messageId))
: reject(new Error('MESSAGE_ID_NOT_FOUND')),
)
.catch(reject);
});
@@ -296,37 +328,53 @@ class MessageManager extends CachedManager {
*/
async search(options = {}) {
// eslint-disable-next-line no-unused-vars
let { authors, content, mentions, has, maxId, minId, channels, pinned, nsfw, offset, limit, sortBy, sortOrder } =
Object.assign(
{
authors: [],
content: '',
mentions: [],
has: [],
maxId: null,
minId: null,
channels: [],
pinned: false,
nsfw: false,
offset: 0,
limit: 25,
sortBy: 'timestamp',
sortOrder: 'desc',
},
options,
);
let {
authors,
content,
mentions,
has,
maxId,
minId,
channels,
pinned,
nsfw,
offset,
limit,
sortBy,
sortOrder,
} = Object.assign(
{
authors: [],
content: '',
mentions: [],
has: [],
maxId: null,
minId: null,
channels: [],
pinned: false,
nsfw: false,
offset: 0,
limit: 25,
sortBy: 'timestamp',
sortOrder: 'desc',
},
options,
);
// Validate
if (authors.length > 0) authors = authors.map(u => this.client.users.resolveId(u));
if (mentions.length > 0) mentions = mentions.map(u => this.client.users.resolveId(u));
if (authors.length > 0)
authors = authors.map((u) => this.client.users.resolveId(u));
if (mentions.length > 0)
mentions = mentions.map((u) => this.client.users.resolveId(u));
if (channels.length > 0) {
channels = channels
.map(c => this.client.channels.resolveId(c))
.filter(id => {
.map((c) => this.client.channels.resolveId(c))
.filter((id) => {
if (this.channel.guildId) {
const c = this.channel.guild.channels.cache.get(id);
if (!c || !c.messages) return false;
const perm = c.permissionsFor(this.client.user);
if (!perm.has('READ_MESSAGE_HISTORY') || !perm.has('VIEW_CHANNEL')) return false;
if (!perm.has('READ_MESSAGE_HISTORY') || !perm.has('VIEW_CHANNEL'))
return false;
return true;
} else {
return true;
@@ -337,11 +385,18 @@ class MessageManager extends CachedManager {
let stringQuery = [];
const result = new Collection();
let data;
if (authors.length > 0) stringQuery.push(authors.map(id => `author_id=${id}`).join('&'));
if (content && content.length) stringQuery.push(`content=${encodeURIComponent(content)}`);
if (mentions.length > 0) stringQuery.push(mentions.map(id => `mentions=${id}`).join('&'));
has = has.filter(v => ['link', 'embed', 'file', 'video', 'image', 'sound', 'sticker'].includes(v));
if (has.length > 0) stringQuery.push(has.map(v => `has=${v}`).join('&'));
if (authors.length > 0)
stringQuery.push(authors.map((id) => `author_id=${id}`).join('&'));
if (content && content.length)
stringQuery.push(`content=${encodeURIComponent(content)}`);
if (mentions.length > 0)
stringQuery.push(mentions.map((id) => `mentions=${id}`).join('&'));
has = has.filter((v) =>
['link', 'embed', 'file', 'video', 'image', 'sound', 'sticker'].includes(
v,
),
);
if (has.length > 0) stringQuery.push(has.map((v) => `has=${v}`).join('&'));
if (maxId) stringQuery.push(`max_id=${maxId}`);
if (minId) stringQuery.push(`min_id=${minId}`);
if (nsfw) stringQuery.push('include_nsfw=true');
@@ -358,7 +413,7 @@ class MessageManager extends CachedManager {
stringQuery.push('sort_order=desc');
}
if (this.channel.guildId && channels.length > 0) {
stringQuery.push(channels.map(id => `channel_id=${id}`).join('&'));
stringQuery.push(channels.map((id) => `channel_id=${id}`).join('&'));
}
if (typeof pinned == 'boolean') stringQuery.push(`pinned=${pinned}`);
// Main
@@ -369,13 +424,22 @@ class MessageManager extends CachedManager {
};
}
if (this.channel.guildId) {
data = await this.client.api.guilds[this.channel.guildId].messages[`search?${stringQuery.join('&')}`].get();
data =
await this.client.api.guilds[this.channel.guildId].messages[
`search?${stringQuery.join('&')}`
].get();
} else {
stringQuery = stringQuery.filter(v => !v.startsWith('channel_id') && !v.startsWith('include_nsfw'));
data = await this.client.api.channels[this.channel.id].messages[`search?${stringQuery.join('&')}`].get();
stringQuery = stringQuery.filter(
(v) => !v.startsWith('channel_id') && !v.startsWith('include_nsfw'),
);
data =
await this.client.api.channels[this.channel.id].messages[
`search?${stringQuery.join('&')}`
].get();
}
for await (const message of data.messages) result.set(message[0].id, new Message(this.client, message[0]));
for await (const message of data.messages)
result.set(message[0].id, new Message(this.client, message[0]));
return {
messages: result,
total: data.total_results,
@@ -383,9 +447,12 @@ class MessageManager extends CachedManager {
}
async _fetchMany(options = {}, cache) {
const data = await this.client.api.channels[this.channel.id].messages.get({ query: options });
const data = await this.client.api.channels[this.channel.id].messages.get({
query: options,
});
const messages = new Collection();
for (const message of data) messages.set(message.id, this._add(message, cache));
for (const message of data)
messages.set(message.id, this._add(message, cache));
return messages;
}
@@ -395,7 +462,10 @@ class MessageManager extends CachedManager {
* @returns {Promise<Message>}
*/
async endPoll(messageId) {
const message = await this.client.api.channels(this.channel.id).polls(messageId).expire.post();
const message = await this.client.api
.channels(this.channel.id)
.polls(messageId)
.expire.post();
return this._add(message, false);
}
@@ -412,11 +482,18 @@ class MessageManager extends CachedManager {
* @returns {Promise<Collection<Snowflake, User>>}
*/
async fetchPollAnswerVoters({ messageId, answerId, after, limit }) {
const voters = await this.client.channels(this.channel.id).polls(messageId).answers(answerId).get({
query: { limit, after },
});
const voters = await this.client
.channels(this.channel.id)
.polls(messageId)
.answers(answerId)
.get({
query: { limit, after },
});
return voters.users.reduce((acc, user) => acc.set(user.id, this.client.users._add(user, false)), new Collection());
return voters.users.reduce(
(acc, user) => acc.set(user.id, this.client.users._add(user, false)),
new Collection(),
);
}
}

View File

@@ -64,7 +64,12 @@ class PermissionOverwriteManager extends CachedManager {
*/
async set(overwrites, reason) {
if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) {
throw new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true);
throw new TypeError(
'INVALID_TYPE',
'overwrites',
'Array or Collection of Permission Overwrites',
true,
);
}
return this.channel.edit({ permissionOverwrites: overwrites, reason });
}
@@ -87,15 +92,26 @@ class PermissionOverwriteManager extends CachedManager {
* @private
*/
async upsert(userOrRole, options, overwriteOptions = {}, existing) {
let userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
let userOrRoleId =
this.channel.guild.roles.resolveId(userOrRole) ??
this.client.users.resolveId(userOrRole);
let { type, reason } = overwriteOptions;
if (typeof type !== 'number') {
userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole);
if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role');
type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member;
userOrRole =
this.channel.guild.roles.resolve(userOrRole) ??
this.client.users.resolve(userOrRole);
if (!userOrRole)
throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role');
type =
userOrRole instanceof Role
? OverwriteTypes.role
: OverwriteTypes.member;
}
const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options, existing);
const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(
options,
existing,
);
await this.client.api
.channels(this.channel.id)
@@ -141,7 +157,8 @@ class PermissionOverwriteManager extends CachedManager {
*/
edit(userOrRole, options, overwriteOptions) {
const existing = this.cache.get(
this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole),
this.channel.guild.roles.resolveId(userOrRole) ??
this.client.users.resolveId(userOrRole),
);
return this.upsert(userOrRole, options, overwriteOptions, existing);
}
@@ -153,10 +170,16 @@ class PermissionOverwriteManager extends CachedManager {
* @returns {Promise<GuildChannel>}
*/
async delete(userOrRole, reason) {
const userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
if (!userOrRoleId) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role');
const userOrRoleId =
this.channel.guild.roles.resolveId(userOrRole) ??
this.client.users.resolveId(userOrRole);
if (!userOrRoleId)
throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role');
await this.client.api.channels(this.channel.id).permissions(userOrRoleId).delete({ reason });
await this.client.api
.channels(this.channel.id)
.permissions(userOrRoleId)
.delete({ reason });
return this.channel;
}
}

View File

@@ -61,7 +61,7 @@ class PresenceManager extends CachedManager {
async fetch() {
const data = await this.client.api.presences.get();
// https://docs.discord.food/resources/presence#endpoints
data.presences.forEach(presence => {
data.presences.forEach((presence) => {
this._add(presence, true);
});
return this.cache;

View File

@@ -19,7 +19,10 @@ class ReactionManager extends CachedManager {
}
_add(data, cache) {
return super._add(data, cache, { id: data.emoji.id ?? data.emoji.name, extras: [this.message] });
return super._add(data, cache, {
id: data.emoji.id ?? data.emoji.name,
extras: [this.message],
});
}
/**
@@ -59,7 +62,10 @@ class ReactionManager extends CachedManager {
* @returns {Promise<Message>}
*/
async removeAll() {
await this.client.api.channels(this.message.channelId).messages(this.message.id).reactions.delete();
await this.client.api
.channels(this.message.channelId)
.messages(this.message.id)
.reactions.delete();
return this.message;
}
}

View File

@@ -42,9 +42,15 @@ class ReactionUserManager extends CachedManager {
*/
async fetch({ limit = 100, after, type = 'NORMAL' } = {}) {
const message = this.reaction.message;
const data = await this.client.api.channels[message.channelId].messages[message.id].reactions[
this.reaction.emoji.identifier
].get({ query: { limit, after, type: typeof type == 'number' ? type : ReactionTypes[type] } });
const data = await this.client.api.channels[message.channelId].messages[
message.id
].reactions[this.reaction.emoji.identifier].get({
query: {
limit,
after,
type: typeof type == 'number' ? type : ReactionTypes[type],
},
});
const users = new Collection();
for (const rawUser of data) {
const user = this.client.users._add(rawUser);
@@ -63,7 +69,9 @@ class ReactionUserManager extends CachedManager {
const userId = this.client.users.resolveId(user);
if (!userId) throw new Error('REACTION_RESOLVE_USER');
const message = this.reaction.message;
await this.client.api.channels[message.channelId].messages[message.id].reactions[this.reaction.emoji.identifier][
await this.client.api.channels[message.channelId].messages[
message.id
].reactions[this.reaction.emoji.identifier][
userId === this.client.user.id ? '@me' : userId
].delete();
return this.reaction;

View File

@@ -37,7 +37,7 @@ class RelationshipManager extends BaseManager {
*/
get friendCache() {
const users = this.cache
.filter(value => value === RelationshipTypes.FRIEND)
.filter((value) => value === RelationshipTypes.FRIEND)
.map((_, key) => [key, this.client.users.cache.get(key)]);
return new Collection(users);
}
@@ -49,7 +49,7 @@ class RelationshipManager extends BaseManager {
*/
get blockedCache() {
const users = this.cache
.filter(value => value === RelationshipTypes.BLOCKED)
.filter((value) => value === RelationshipTypes.BLOCKED)
.map((_, key) => [key, this.client.users.cache.get(key)]);
return new Collection(users);
}
@@ -61,7 +61,7 @@ class RelationshipManager extends BaseManager {
*/
get incomingCache() {
const users = this.cache
.filter(value => value === RelationshipTypes.PENDING_INCOMING)
.filter((value) => value === RelationshipTypes.PENDING_INCOMING)
.map((_, key) => [key, this.client.users.cache.get(key)]);
return new Collection(users);
}
@@ -73,7 +73,7 @@ class RelationshipManager extends BaseManager {
*/
get outgoingCache() {
const users = this.cache
.filter(value => value === RelationshipTypes.PENDING_OUTGOING)
.filter((value) => value === RelationshipTypes.PENDING_OUTGOING)
.map((_, key) => [key, this.client.users.cache.get(key)]);
return new Collection(users);
}
@@ -172,9 +172,11 @@ class RelationshipManager extends BaseManager {
// eslint-disable-next-line no-unreachable
const id = this.resolveId(user);
if (
![RelationshipTypes.FRIEND, RelationshipTypes.BLOCKED, RelationshipTypes.PENDING_OUTGOING].includes(
this.cache.get(id),
)
![
RelationshipTypes.FRIEND,
RelationshipTypes.BLOCKED,
RelationshipTypes.PENDING_OUTGOING,
].includes(this.cache.get(id))
) {
return Promise.resolve(false);
}
@@ -222,9 +224,11 @@ class RelationshipManager extends BaseManager {
// eslint-disable-next-line no-unreachable
const id = this.resolveId(user);
// Check if already friends
if (this.cache.get(id) === RelationshipTypes.FRIEND) return Promise.resolve(false);
if (this.cache.get(id) === RelationshipTypes.FRIEND)
return Promise.resolve(false);
// Check if outgoing request
if (this.cache.get(id) === RelationshipTypes.PENDING_OUTGOING) return Promise.resolve(false);
if (this.cache.get(id) === RelationshipTypes.PENDING_OUTGOING)
return Promise.resolve(false);
await this.client.api.users['@me'].relationships[id].put({
data: { confirm_stranger_request: true },
DiscordContext: { location: 'Friends' },
@@ -240,7 +244,8 @@ class RelationshipManager extends BaseManager {
*/
async setNickname(user, nickname = null) {
const id = this.resolveId(user);
if (this.cache.get(id) !== RelationshipTypes.FRIEND) return Promise.resolve(false);
if (this.cache.get(id) !== RelationshipTypes.FRIEND)
return Promise.resolve(false);
await this.client.api.users['@me'].relationships[id].patch({
data: {
nickname: typeof nickname === 'string' ? nickname : null,
@@ -264,7 +269,8 @@ class RelationshipManager extends BaseManager {
// eslint-disable-next-line no-unreachable
const id = this.resolveId(user);
// Check
if (this.cache.get(id) === RelationshipTypes.BLOCKED) return Promise.resolve(false);
if (this.cache.get(id) === RelationshipTypes.BLOCKED)
return Promise.resolve(false);
await this.client.api.users['@me'].relationships[id].put({
data: {
type: RelationshipTypes.BLOCKED,

View File

@@ -72,7 +72,7 @@ class RoleManager extends CachedManager {
const data = await this.client.api.guilds(this.guild.id).roles.get();
const roles = new Collection();
for (const role of data) roles.set(role.id, this._add(role, cache));
return id ? roles.get(id) ?? null : roles;
return id ? (roles.get(id) ?? null) : roles;
}
/**
@@ -80,7 +80,10 @@ class RoleManager extends CachedManager {
* @returns {Promise<Record<Snowflake, number>>}
*/
async fetchMemberCounts() {
const data = await this.client.api.guilds(this.guild.id).roles('member-counts').get();
const data = await this.client.api
.guilds(this.guild.id)
.roles('member-counts')
.get();
return data;
}
@@ -95,7 +98,10 @@ class RoleManager extends CachedManager {
const id = this.resolveId(role);
if (!id) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable');
const data = await this.client.api.guilds(this.guild.id).roles(id, 'member-ids').get();
const data = await this.client.api
.guilds(this.guild.id)
.roles(id, 'member-ids')
.get();
return data;
}
@@ -191,24 +197,34 @@ class RoleManager extends CachedManager {
*/
async create(options = {}) {
let { permissions, icon } = options;
const { name, color, hoist, position, mentionable, reason, unicodeEmoji } = options;
const { name, color, hoist, position, mentionable, reason, unicodeEmoji } =
options;
if (typeof permissions !== 'undefined') permissions = new Permissions(permissions);
if (typeof permissions !== 'undefined')
permissions = new Permissions(permissions);
if (icon) {
const guildEmojiURL = this.guild.emojis.resolve(icon)?.url;
icon = guildEmojiURL ? await DataResolver.resolveImage(guildEmojiURL) : await DataResolver.resolveImage(icon);
icon = guildEmojiURL
? await DataResolver.resolveImage(guildEmojiURL)
: await DataResolver.resolveImage(icon);
if (typeof icon !== 'string') icon = undefined;
}
let colors = options.colors && {
primary_color: resolveColor(options.colors.primaryColor),
secondary_color: options.colors.secondaryColor && resolveColor(options.colors.secondaryColor),
tertiary_color: options.colors.tertiaryColor && resolveColor(options.colors.tertiaryColor),
secondary_color:
options.colors.secondaryColor &&
resolveColor(options.colors.secondaryColor),
tertiary_color:
options.colors.tertiaryColor &&
resolveColor(options.colors.tertiaryColor),
};
if (color !== undefined) {
if (!deprecationEmittedForCreate) {
process.emitWarning(`Passing "color" to RoleManager#create() is deprecated. Use "colors" instead.`);
process.emitWarning(
`Passing "color" to RoleManager#create() is deprecated. Use "colors" instead.`,
);
}
deprecationEmittedForCreate = true;
@@ -256,24 +272,31 @@ class RoleManager extends CachedManager {
role = this.resolve(role);
if (!role) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable');
if (typeof data.position === 'number') await this.setPosition(role, data.position, { reason });
if (typeof data.position === 'number')
await this.setPosition(role, data.position, { reason });
let icon = data.icon;
if (icon) {
const guildEmojiURL = this.guild.emojis.resolve(icon)?.url;
icon = guildEmojiURL ? await DataResolver.resolveImage(guildEmojiURL) : await DataResolver.resolveImage(icon);
icon = guildEmojiURL
? await DataResolver.resolveImage(guildEmojiURL)
: await DataResolver.resolveImage(icon);
if (typeof icon !== 'string') icon = undefined;
}
let colors = data.colors && {
primary_color: resolveColor(data.colors.primaryColor),
secondary_color: data.colors.secondaryColor && resolveColor(data.colors.secondaryColor),
tertiary_color: data.colors.tertiaryColor && resolveColor(data.colors.tertiaryColor),
secondary_color:
data.colors.secondaryColor && resolveColor(data.colors.secondaryColor),
tertiary_color:
data.colors.tertiaryColor && resolveColor(data.colors.tertiaryColor),
};
if (data.color !== undefined) {
if (!deprecationEmittedForEdit) {
process.emitWarning(`Passing "color" to RoleManager#edit() is deprecated. Use "colors" instead.`);
process.emitWarning(
`Passing "color" to RoleManager#edit() is deprecated. Use "colors" instead.`,
);
}
deprecationEmittedForEdit = true;
@@ -289,13 +312,19 @@ class RoleManager extends CachedManager {
name: data.name,
colors,
hoist: data.hoist,
permissions: typeof data.permissions === 'undefined' ? undefined : new Permissions(data.permissions),
permissions:
typeof data.permissions === 'undefined'
? undefined
: new Permissions(data.permissions),
mentionable: data.mentionable,
icon,
unicode_emoji: data.unicodeEmoji,
};
const d = await this.client.api.guilds(this.guild.id).roles(role.id).patch({ data: _data, reason });
const d = await this.client.api
.guilds(this.guild.id)
.roles(role.id)
.patch({ data: _data, reason });
const clone = role._clone();
clone._patch(d);
@@ -316,7 +345,10 @@ class RoleManager extends CachedManager {
async delete(role, reason) {
const id = this.resolveId(role);
await this.client.api.guilds[this.guild.id].roles[id].delete({ reason });
this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: id });
this.client.actions.GuildRoleDelete.handle({
guild_id: this.guild.id,
role_id: id,
});
}
/**
@@ -368,7 +400,7 @@ class RoleManager extends CachedManager {
*/
async setPositions(rolePositions) {
// Make sure rolePositions are prepared for API
rolePositions = rolePositions.map(o => ({
rolePositions = rolePositions.map((o) => ({
id: this.resolveId(o.role),
position: o.position,
}));
@@ -393,7 +425,8 @@ class RoleManager extends CachedManager {
comparePositions(role1, role2) {
const resolvedRole1 = this.resolve(role1);
const resolvedRole2 = this.resolve(role2);
if (!resolvedRole1 || !resolvedRole2) throw new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake');
if (!resolvedRole1 || !resolvedRole2)
throw new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake');
const role1Position = resolvedRole1.position;
const role2Position = resolvedRole2.position;
@@ -414,7 +447,7 @@ class RoleManager extends CachedManager {
botRoleFor(user) {
const userId = this.client.users.resolveId(user);
if (!userId) return null;
return this.cache.find(role => role.tags?.botId === userId) ?? null;
return this.cache.find((role) => role.tags?.botId === userId) ?? null;
}
/**
@@ -432,7 +465,7 @@ class RoleManager extends CachedManager {
* @readonly
*/
get premiumSubscriberRole() {
return this.cache.find(role => role.tags?.premiumSubscriberRole) ?? null;
return this.cache.find((role) => role.tags?.premiumSubscriberRole) ?? null;
}
/**
@@ -441,7 +474,10 @@ class RoleManager extends CachedManager {
* @readonly
*/
get highest() {
return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first());
return this.cache.reduce(
(prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev),
this.cache.first(),
);
}
}

View File

@@ -28,7 +28,7 @@ class SessionManager extends CachedManager {
* @returns {Promise<Collection<string, Session>>}
*/
fetch() {
return this.client.api.auth.sessions.get().then(data => {
return this.client.api.auth.sessions.get().then((data) => {
const allData = data.user_sessions;
this.cache.clear();
for (const session of allData) {
@@ -45,7 +45,7 @@ class SessionManager extends CachedManager {
logoutAllDevices() {
return this.client.api.auth.sessions.logout({
data: {
session_id_hashes: this.cache.map(session => session.id),
session_id_hashes: this.cache.map((session) => session.id),
},
});
}

View File

@@ -60,11 +60,17 @@ class StageInstanceManager extends CachedManager {
async create(channel, options) {
const channelId = this.guild.channels.resolveId(channel);
if (!channelId) throw new Error('STAGE_CHANNEL_RESOLVE');
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
let { guildScheduledEvent, topic, privacyLevel, sendStartNotification } = options;
if (typeof options !== 'object')
throw new TypeError('INVALID_TYPE', 'options', 'object', true);
let { guildScheduledEvent, topic, privacyLevel, sendStartNotification } =
options;
privacyLevel &&= typeof privacyLevel === 'number' ? privacyLevel : PrivacyLevels[privacyLevel];
const guildScheduledEventId = guildScheduledEvent && this.resolveId(guildScheduledEvent);
privacyLevel &&=
typeof privacyLevel === 'number'
? privacyLevel
: PrivacyLevels[privacyLevel];
const guildScheduledEventId =
guildScheduledEvent && this.resolveId(guildScheduledEvent);
const data = await this.client.api['stage-instances'].post({
data: {
@@ -95,7 +101,9 @@ class StageInstanceManager extends CachedManager {
if (!channelId) throw new Error('STAGE_CHANNEL_RESOLVE');
if (!force) {
const existing = this.cache.find(stageInstance => stageInstance.channelId === channelId);
const existing = this.cache.find(
(stageInstance) => stageInstance.channelId === channelId,
);
if (existing) return existing;
}
@@ -122,13 +130,17 @@ class StageInstanceManager extends CachedManager {
* .catch(console.error);
*/
async edit(channel, options) {
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
if (typeof options !== 'object')
throw new TypeError('INVALID_TYPE', 'options', 'object', true);
const channelId = this.guild.channels.resolveId(channel);
if (!channelId) throw new Error('STAGE_CHANNEL_RESOLVE');
let { topic, privacyLevel } = options;
privacyLevel &&= typeof privacyLevel === 'number' ? privacyLevel : PrivacyLevels[privacyLevel];
privacyLevel &&=
typeof privacyLevel === 'number'
? privacyLevel
: PrivacyLevels[privacyLevel];
const data = await this.client.api('stage-instances', channelId).patch({
data: {

View File

@@ -139,27 +139,35 @@ class ThreadManager extends CachedManager {
* @returns {Promise<FetchedThreads>}
*/
async fetchActive(cache = true, options = {}) {
const raw = await this.client.api.channels(this.channel.id).threads.search.get({
query: {
archived: options?.archived ?? false,
limit: options?.limit ?? 25,
offset: options?.offset ?? 0,
sort_by: options?.sortBy ?? 'last_message_time',
sort_order: options?.sortOrder ?? 'desc',
},
});
const raw = await this.client.api
.channels(this.channel.id)
.threads.search.get({
query: {
archived: options?.archived ?? false,
limit: options?.limit ?? 25,
offset: options?.offset ?? 0,
sort_by: options?.sortBy ?? 'last_message_time',
sort_order: options?.sortOrder ?? 'desc',
},
});
return this.constructor._mapThreads(raw, this.client, { parent: this.channel, cache });
return this.constructor._mapThreads(raw, this.client, {
parent: this.channel,
cache,
});
}
static _mapThreads(rawThreads, client, { parent, guild, cache }) {
const threads = rawThreads.threads.reduce((coll, raw) => {
const thread = client.channels._add(raw, guild ?? parent?.guild, { cache });
const thread = client.channels._add(raw, guild ?? parent?.guild, {
cache,
});
if (parent && thread.parentId !== parent.id) return coll;
return coll.set(thread.id, thread);
}, new Collection());
// Discord sends the thread id as id in this object
for (const rawMember of rawThreads.members) client.channels.cache.get(rawMember.id)?.members._add(rawMember);
for (const rawMember of rawThreads.members)
client.channels.cache.get(rawMember.id)?.members._add(rawMember);
// Patch firstMessage
// According to https://github.com/aiko-chan-ai/discord.js-selfbot-v13/issues/1502, rawThreads.first_messages could be null.
for (const rawMessage of rawThreads?.first_messages || []) {

View File

@@ -98,7 +98,9 @@ class ThreadMemberManager extends CachedManager {
async add(member, reason) {
const id = member === '@me' ? member : this.client.users.resolveId(member);
if (!id) throw new TypeError('INVALID_TYPE', 'member', 'UserResolvable');
await this.client.api.channels(this.thread.id, 'thread-members', id).put({ reason });
await this.client.api
.channels(this.thread.id, 'thread-members', id)
.put({ reason });
return id;
}
@@ -109,7 +111,9 @@ class ThreadMemberManager extends CachedManager {
* @returns {Promise<Snowflake>}
*/
async remove(id, reason) {
await this.client.api.channels(this.thread.id, 'thread-members', id).delete({ reason });
await this.client.api
.channels(this.thread.id, 'thread-members', id)
.delete({ reason });
return id;
}
@@ -119,17 +123,24 @@ class ThreadMemberManager extends CachedManager {
if (existing) return existing;
}
const data = await this.client.api.channels(this.thread.id, 'thread-members', memberId).get({
query: { with_member: withMember },
});
const data = await this.client.api
.channels(this.thread.id, 'thread-members', memberId)
.get({
query: { with_member: withMember },
});
return this._add(data, cache);
}
async _fetchMany({ cache, limit, after, withMember } = {}) {
const raw = await this.client.api.channels(this.thread.id, 'thread-members').get({
query: { with_member: withMember, limit, after },
});
return raw.reduce((col, member) => col.set(member.user_id, this._add(member, cache)), new Collection());
const raw = await this.client.api
.channels(this.thread.id, 'thread-members')
.get({
query: { with_member: withMember, limit, after },
});
return raw.reduce(
(col, member) => col.set(member.user_id, this._add(member, cache)),
new Collection(),
);
}
/**
@@ -179,7 +190,9 @@ class ThreadMemberManager extends CachedManager {
const id = this.resolveId(member);
return id
? this._fetchOne(id, options)
: this._fetchMany(typeof member === 'boolean' ? { ...options, cache: member } : options);
: this._fetchMany(
typeof member === 'boolean' ? { ...options, cache: member } : options,
);
}
}

View File

@@ -39,7 +39,11 @@ class UserManager extends CachedManager {
* @private
*/
dmChannel(userId) {
return this.client.channels.cache.find(c => c.type === 'DM' && c.recipient.id === userId) ?? null;
return (
this.client.channels.cache.find(
(c) => c.type === 'DM' && c.recipient.id === userId,
) ?? null
);
}
/**
@@ -115,7 +119,8 @@ class UserManager extends CachedManager {
* @returns {?User}
*/
resolve(user) {
if (user instanceof GuildMember || user instanceof ThreadMember) return user.user;
if (user instanceof GuildMember || user instanceof ThreadMember)
return user.user;
if (user instanceof Message) return user.author;
return super.resolve(user);
}

View File

@@ -43,7 +43,7 @@ class UserNoteManager extends BaseManager {
}
const data = await this.client.api.users['@me'].notes[id]
.get()
.then(d => d.note)
.then((d) => d.note)
.catch(() => '');
if (cache) this.cache.set(id, data);
return data;

View File

@@ -51,7 +51,9 @@ class VoiceStateManager extends CachedManager {
const existing = this.cache.get(id === '@me' ? this.client.user.id : id);
if (existing) return existing;
}
const data = await this.client.api.guilds(this.guild.id)['voice-states'][id].get();
const data = await this.client.api
.guilds(this.guild.id)
['voice-states'][id].get();
return this._add(data, cache);
}
}