feat: GuildSettingManager

Co-Authored-By: Yellowy <64450187+TheDevYellowy@users.noreply.github.com>
This commit is contained in:
March 7th 2023-01-08 14:06:42 +07:00
parent e88521fb1f
commit 6dcef09024
9 changed files with 247 additions and 25 deletions

View File

@ -15,7 +15,7 @@ const Discord = require('../index');
const BaseGuildEmojiManager = require('../managers/BaseGuildEmojiManager'); const BaseGuildEmojiManager = require('../managers/BaseGuildEmojiManager');
const BillingManager = require('../managers/BillingManager'); const BillingManager = require('../managers/BillingManager');
const ChannelManager = require('../managers/ChannelManager'); const ChannelManager = require('../managers/ChannelManager');
const ClientSettingManager = require('../managers/ClientSettingManager'); const ClientUserSettingManager = require('../managers/ClientUserSettingManager');
const DeveloperPortalManager = require('../managers/DeveloperPortalManager'); const DeveloperPortalManager = require('../managers/DeveloperPortalManager');
const GuildManager = require('../managers/GuildManager'); const GuildManager = require('../managers/GuildManager');
const RelationshipManager = require('../managers/RelationshipManager'); const RelationshipManager = require('../managers/RelationshipManager');
@ -151,9 +151,9 @@ class Client extends BaseClient {
this.relationships = new RelationshipManager(this); this.relationships = new RelationshipManager(this);
/** /**
* All of the settings {@link Object} * All of the settings {@link Object}
* @type {ClientSettingManager} * @type {ClientUserSettingManager}
*/ */
this.settings = new ClientSettingManager(this); this.settings = new ClientUserSettingManager(this);
/** /**
* All of the guilds the client is currently handling, mapped by their ids - * All of the guilds the client is currently handling, mapped by their ids -
* as long as sharding isn't being used, this will be *every* guild the bot is a member of * as long as sharding isn't being used, this will be *every* guild the bot is a member of

View File

@ -141,6 +141,11 @@ module.exports = async (client, { d: data }, shard) => {
client.guilds._add(guild); client.guilds._add(guild);
} }
for (const gSetting of data.user_guild_settings) {
const guild = client.guilds.cache.get(gSetting.guild_id);
if (guild) guild.settings._patch(gSetting);
}
const largeGuilds = data.guilds.filter(g => g.large); const largeGuilds = data.guilds.filter(g => g.large);
client.emit('debug', `Received ${data.guilds.length} guilds, ${largeGuilds.length} large guilds`); client.emit('debug', `Received ${data.guilds.length} guilds, ${largeGuilds.length} large guilds`);

View File

@ -0,0 +1,12 @@
'use strict';
const { Events } = require('../../../util/Constants');
module.exports = (client, { d: data }) => {
const guild = client.guilds.cache.get(data.guild_id);
guild?.settings._patch(data);
/**
* Emitted whenever guild settings are updated
* @event Client#userGuildSettingsUpdate
* @param {Guild} guild Guild
*/
return client.emit(Events.USER_GUILD_SETTINGS_UPDATE, guild);
};

View File

@ -57,6 +57,7 @@ const handlers = Object.fromEntries([
['THREAD_MEMBER_UPDATE', require('./THREAD_MEMBER_UPDATE')], ['THREAD_MEMBER_UPDATE', require('./THREAD_MEMBER_UPDATE')],
['THREAD_MEMBERS_UPDATE', require('./THREAD_MEMBERS_UPDATE')], ['THREAD_MEMBERS_UPDATE', require('./THREAD_MEMBERS_UPDATE')],
['USER_SETTINGS_UPDATE', require('./USER_SETTINGS_UPDATE')], // Opcode 0 ['USER_SETTINGS_UPDATE', require('./USER_SETTINGS_UPDATE')], // Opcode 0
['USER_GUILD_SETTINGS_UPDATE', require('./USER_GUILD_SETTINGS_UPDATE')],
// USER_SETTINGS_PROTO_UPDATE // opcode 0 // USER_SETTINGS_PROTO_UPDATE // opcode 0
['USER_NOTE_UPDATE', require('./USER_NOTE_UPDATE')], ['USER_NOTE_UPDATE', require('./USER_NOTE_UPDATE')],
['USER_UPDATE', require('./USER_UPDATE')], ['USER_UPDATE', require('./USER_UPDATE')],

View File

@ -12,7 +12,7 @@ const { localeSetting, DMScanLevel, stickerAnimationMode } = require('../util/Co
* @extends {BaseManager} * @extends {BaseManager}
* @see {@link https://luna.gitlab.io/discord-unofficial-docs/user_settings.html} * @see {@link https://luna.gitlab.io/discord-unofficial-docs/user_settings.html}
*/ */
class ClientSettingManager extends BaseManager { class ClientUserSettingManager extends BaseManager {
constructor(client) { constructor(client) {
super(client); super(client);
/** /**
@ -487,4 +487,4 @@ class ClientSettingManager extends BaseManager {
} }
} }
module.exports = ClientSettingManager; module.exports = ClientUserSettingManager;

View File

@ -0,0 +1,148 @@
'use strict';
const BaseManager = require('./BaseManager');
/**
* Manages API methods for users and stores their cache.
* @extends {BaseManager}
* @see {@link https://luna.gitlab.io/discord-unofficial-docs/user_settings.html}
*/
class GuildSettingManager extends BaseManager {
constructor(client, guildId = null) {
super(client);
/**
* Raw data
* @type {Object}
*/
this.rawSetting = {};
/**
* Guild Id
* @type {?Snowflake}
*/
this.guildId = guildId;
}
/**
* Get the guild
* @type {?Guild}
* @readonly
*/
get guild() {
return this.client.guilds.cache.get(this.guildId);
}
/**
* Patch data file
* @private
* @param {Object} data Raw Data to patch
*/
_patch(data = {}) {
this.rawSetting = Object.assign(this.rawSetting, data);
if ('suppress_everyone' in data) {
/**
* Notification setting > Suppress `@everyone` and `@here`
* @type {?boolean}
*/
this.suppressEveryone = data.suppress_everyone;
}
if ('suppress_roles' in data) {
/**
* Notification setting > Suppress all role `@mention`
* @type {?boolean}
*/
this.suppressRoles = data.suppress_roles;
}
if ('mute_scheduled_events' in data) {
/**
* Notification setting > Mute new events
* @type {?boolean}
*/
this.muteScheduledEvents = data.mute_scheduled_events;
}
if ('message_notifications' in data) {
/**
* Notification setting > Message notifications
* * `0` = All messages
* * `1` = Only @mentions
* * `2` = Nothing
* @type {?number}
*/
this.messageNotifications = data.message_notifications;
}
if ('flags' in data) {
/**
* Flags (unknown)
* @type {?number}
*/
this.flags = data.flags;
}
if ('mobile_push' in data) {
/**
* Notification setting > Mobile push notifications
* @type {?boolean}
*/
this.mobilePush = data.mobile_push;
}
if ('muted' in data) {
/**
* Mute server
* @type {?boolean}
*/
this.muted = data.muted;
}
if ('mute_config' in data) {
/**
* Mute config (muted = true)
* * `muteConfig.endTime`: End time (Date)
* * `muteConfig.selectedTimeWindow`: Selected time window (seconds) (number)
* @type {?Date}
*/
this.muteConfig = {
endTime: new Date(data.mute_config.end_time),
selectedTimeWindow: data.mute_config.selected_time_window,
};
} else {
this.muteConfig = null;
}
if ('hide_muted_channels' in data) {
/**
* Hide muted channels
* @type {?boolean}
*/
this.hideMutedChannels = data.hide_muted_channels;
}
if ('channel_overrides' in data) {
/**
* Channel overrides (unknown)
* @type {?Array}
*/
this.channelOverrides = data.channel_overrides;
}
if ('notify_highlights' in data) {
/**
* Notification setting > Suppress highlights
* * `0` = ??? (unknown)
* * `1` = Enable
* * `2` = Disable
* @type {?number}
*/
this.notifyHighlights = data.notify_highlights;
}
if ('version' in data) {
/**
* Version (unknown)
* @type {?number}
*/
this.version = data.version;
}
}
/**
* Edit guild settings
* @param {Object} data Data to edit
* @returns {Promise<GuildSettingManager>}
*/
async edit(data) {
const data_ = await this.client.api.users('@me').settings.patch(data_);
this._patch(data);
return this;
}
}
module.exports = GuildSettingManager;

View File

@ -17,6 +17,7 @@ const GuildEmojiManager = require('../managers/GuildEmojiManager');
const GuildInviteManager = require('../managers/GuildInviteManager'); const GuildInviteManager = require('../managers/GuildInviteManager');
const GuildMemberManager = require('../managers/GuildMemberManager'); const GuildMemberManager = require('../managers/GuildMemberManager');
const GuildScheduledEventManager = require('../managers/GuildScheduledEventManager'); const GuildScheduledEventManager = require('../managers/GuildScheduledEventManager');
const GuildSettingManager = require('../managers/GuildSettingManager');
const GuildStickerManager = require('../managers/GuildStickerManager'); const GuildStickerManager = require('../managers/GuildStickerManager');
const PresenceManager = require('../managers/PresenceManager'); const PresenceManager = require('../managers/PresenceManager');
const RoleManager = require('../managers/RoleManager'); const RoleManager = require('../managers/RoleManager');
@ -136,6 +137,8 @@ class Guild extends AnonymousGuild {
* @type {number} * @type {number}
*/ */
this.shardId = data.shardId; this.shardId = data.shardId;
this.settings = new GuildSettingManager(this.client, this.id);
} }
/** /**
@ -649,22 +652,17 @@ class Guild extends AnonymousGuild {
* guild.mute(false); // unmutes the guild * guild.mute(false); // unmutes the guild
*/ */
async mute(mute, time) { async mute(mute, time) {
try { if (mute && time == null) return false;
if (mute && time == null) return false; if (time == null && !mute) await this.client.api.guilds(this.id).settings.patch({ muted: false });
if (time == null && !mute) await this.client.api.guilds(this.id).settings.patch({ muted: false }); let ms = time * 1000;
let ms = time * 1000; let date = new Date(Date.now() + ms).toISOString();
let date = new Date(Date.now() + ms).toISOString(); return this.settings.edit({
await this.client.api.guilds(this.id).settings.patch({ mute_config: {
mute_config: { end_time: date,
end_time: date, selected_time_window: time,
selected_time_window: time, },
}, muted: true,
muted: true, });
});
return true;
} catch (e) {
return false;
}
} }
/** /**

View File

@ -471,6 +471,7 @@ exports.Events = {
THREAD_MEMBERS_UPDATE: 'threadMembersUpdate', THREAD_MEMBERS_UPDATE: 'threadMembersUpdate',
USER_UPDATE: 'userUpdate', USER_UPDATE: 'userUpdate',
USER_SETTINGS_UPDATE: 'userSettingsUpdate', USER_SETTINGS_UPDATE: 'userSettingsUpdate',
USER_GUILD_SETTINGS_UPDATE: 'userGuildSettingsUpdate',
PRESENCE_UPDATE: 'presenceUpdate', PRESENCE_UPDATE: 'presenceUpdate',
VOICE_SERVER_UPDATE: 'voiceServerUpdate', VOICE_SERVER_UPDATE: 'voiceServerUpdate',
VOICE_STATE_UPDATE: 'voiceStateUpdate', VOICE_STATE_UPDATE: 'voiceStateUpdate',

65
typings/index.d.ts vendored
View File

@ -878,7 +878,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
public application: If<Ready, ClientApplication>; public application: If<Ready, ClientApplication>;
// Added // Added
public settings: ClientSettingManager; public settings: ClientUserSettingManager;
public relationships: RelationshipManager; public relationships: RelationshipManager;
public readonly callVoice?: VoiceConnection; public readonly callVoice?: VoiceConnection;
public voiceStates: VoiceStateManager; public voiceStates: VoiceStateManager;
@ -3760,7 +3760,7 @@ export class GuildFolder extends Base {
public toJSON(): RawGuildFolderData; public toJSON(): RawGuildFolderData;
} }
export class ClientSettingManager extends BaseManager { export class ClientUserSettingManager extends BaseManager {
private constructor(client: Client); private constructor(client: Client);
public rawSetting: RawUserSettingsData | object; public rawSetting: RawUserSettingsData | object;
public locale: localeSetting | null; public locale: localeSetting | null;
@ -3793,6 +3793,7 @@ export class ClientSettingManager extends BaseManager {
public guildFolder: GuildFolderManager; public guildFolder: GuildFolderManager;
public disableDMfromServer: Collection<Snowflake, boolean>; public disableDMfromServer: Collection<Snowflake, boolean>;
public fetch(): Promise<RawUserSettingsData>; public fetch(): Promise<RawUserSettingsData>;
public edit(data: Partial<RawUserSettingsData>): Promise<this>;
public setDisplayCompactMode(value?: boolean): Promise<this>; public setDisplayCompactMode(value?: boolean): Promise<this>;
public setTheme(value?: 'dark' | 'light'): Promise<this>; public setTheme(value?: 'dark' | 'light'): Promise<this>;
public setLocale(value: localeSetting): Promise<this>; public setLocale(value: localeSetting): Promise<this>;
@ -3803,6 +3804,26 @@ export class ClientSettingManager extends BaseManager {
public removeRestrictedGuild(guildId: GuildResolvable): Promise<void>; public removeRestrictedGuild(guildId: GuildResolvable): Promise<void>;
} }
export class GuildSettingManager extends BaseManager {
private constructor(client: Client, guildId: Snowflake);
public rawSetting?: RawGuildSettingsData;
public suppressEveryone?: boolean;
public suppressRoles?: boolean;
public muteScheduledEvents?: boolean;
public messageNotifications?: number;
public flags?: number;
public mobilePush?: boolean;
public muted?: boolean;
public muteConfig?: MuteConfigData;
public hideMutedChannels?: boolean;
public channelOverrides?: object[];
public notifyHighlights?: number;
public version?: number;
public guildId?: Snowflake;
public readonly guild?: Guild;
public edit(data: Partial<RawGuildSettingsData>): Promise<this>;
}
export class GuildApplicationCommandManager extends ApplicationCommandManager<ApplicationCommand, {}, Guild> { export class GuildApplicationCommandManager extends ApplicationCommandManager<ApplicationCommand, {}, Guild> {
private constructor(guild: Guild, iterable?: Iterable<RawApplicationCommandData>); private constructor(guild: Guild, iterable?: Iterable<RawApplicationCommandData>);
public guild: Guild; public guild: Guild;
@ -4582,6 +4603,7 @@ export interface ClientEvents extends BaseClientEvents {
typingStart: [typing: Typing]; typingStart: [typing: Typing];
userUpdate: [oldUser: User | PartialUser, newUser: User]; userUpdate: [oldUser: User | PartialUser, newUser: User];
userSettingsUpdate: [setting: RawUserSettingsData]; userSettingsUpdate: [setting: RawUserSettingsData];
userGuildSettingsUpdate: [guild: Guild];
voiceStateUpdate: [oldState: VoiceState, newState: VoiceState]; voiceStateUpdate: [oldState: VoiceState, newState: VoiceState];
webhookUpdate: [channel: TextChannel | NewsChannel | VoiceChannel | ForumChannel]; webhookUpdate: [channel: TextChannel | NewsChannel | VoiceChannel | ForumChannel];
/** @deprecated Use interactionCreate instead */ /** @deprecated Use interactionCreate instead */
@ -4673,6 +4695,7 @@ export interface ConstantsEvents {
THREAD_MEMBERS_UPDATE: 'threadMembersUpdate'; THREAD_MEMBERS_UPDATE: 'threadMembersUpdate';
USER_UPDATE: 'userUpdate'; USER_UPDATE: 'userUpdate';
USER_SETTINGS_UPDATE: 'userSettingsUpdate'; USER_SETTINGS_UPDATE: 'userSettingsUpdate';
USER_GUILD_SETTINGS_UPDATE: 'userGuildSettingsUpdate';
PRESENCE_UPDATE: 'presenceUpdate'; PRESENCE_UPDATE: 'presenceUpdate';
VOICE_SERVER_UPDATE: 'voiceServerUpdate'; VOICE_SERVER_UPDATE: 'voiceServerUpdate';
VOICE_STATE_UPDATE: 'voiceStateUpdate'; VOICE_STATE_UPDATE: 'voiceStateUpdate';
@ -4767,6 +4790,40 @@ export interface RawUserSettingsData {
view_nsfw_guilds?: boolean; view_nsfw_guilds?: boolean;
} }
export interface RawGuildSettingsData {
guild_id: Snowflake;
suppress_everyone: boolean;
suppress_roles: boolean;
mute_scheduled_events: boolean;
message_notifications: 2;
flags: 0;
mobile_push: boolean;
muted: boolean;
mute_config?: RawMuteConfigData;
hide_muted_channels: boolean;
channel_overrides: RawGuildChannelSettingsData[];
notify_highlights: number;
version: number;
}
export interface RawGuildChannelSettingsData {
channel_id: Snowflake;
message_notifications: number;
muted: boolean;
mute_config?: RawMuteConfigData;
collapsed: boolean;
}
export interface RawMuteConfigData {
end_time: string;
selected_time_window: number;
}
export interface MuteConfigData {
endTime: Date;
selectedTimeWindow: number;
}
export interface ClientOptions { export interface ClientOptions {
shards?: number | number[] | 'auto'; shards?: number | number[] | 'auto';
shardCount?: number; shardCount?: number;
@ -5250,8 +5307,8 @@ export type CacheConstructors = {
// Narrowing the type of `manager.name` doesn't propagate type information to `holds` and the return type. // Narrowing the type of `manager.name` doesn't propagate type information to `holds` and the return type.
export type CacheFactory = ( export type CacheFactory = (
manager: CacheConstructors[keyof Caches], manager: CacheConstructors[keyof Caches],
holds: Caches[(typeof manager)['name']][1], holds: Caches[typeof manager['name']][1],
) => (typeof manager)['prototype'] extends DataManager<infer K, infer V, any> ? Collection<K, V> : never; ) => typeof manager['prototype'] extends DataManager<infer K, infer V, any> ? Collection<K, V> : never;
export type CacheWithLimitsOptions = { export type CacheWithLimitsOptions = {
[K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager<infer K, infer V, any> [K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager<infer K, infer V, any>