diff --git a/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js b/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js new file mode 100644 index 00000000..2b6dec1 --- /dev/null +++ b/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = (client, { d: data }) => { + const guild = client.guilds.cache.get(data.guild_id); + if (guild) guild?.settings._patch(data); +}; diff --git a/src/client/websocket/handlers/index.js b/src/client/websocket/handlers/index.js index 709d68f..45423cd 100644 --- a/src/client/websocket/handlers/index.js +++ b/src/client/websocket/handlers/index.js @@ -74,6 +74,7 @@ const handlers = Object.fromEntries([ ['CALL_UPDATE', require('./CALL_UPDATE')], ['CALL_DELETE', require('./CALL_DELETE')], ['USER_SETTINGS_UPDATE', require('./USER_SETTINGS_UPDATE')], + ['USER_GUILD_SETTINGS_UPDATE', require('./USER_GUILD_SETTINGS_UPDATE')], ]); module.exports = handlers; diff --git a/src/managers/GuildSettingManager.js b/src/managers/GuildSettingManager.js new file mode 100644 index 00000000..6e37fa4 --- /dev/null +++ b/src/managers/GuildSettingManager.js @@ -0,0 +1,154 @@ +'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 { + #raw = {}; + constructor(guild) { + super(guild.client); + /** + * Guild Id + * @type {?Snowflake} + */ + this.guildId = guild.id; + } + + /** + * Raw data + * @type {Object} + */ + get raw() { + return this.#raw; + } + + /** + * 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.#raw = Object.assign(this.#raw, 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 && data.mute_config !== null) { + /** + * Mute config (muted = true) + * * `muteConfig.endTime`: End time (Date) + * * `muteConfig.selectedTimeWindow`: Selected time window (seconds) (number) + * @type {?Object} + */ + 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} + */ + async edit(data) { + const data_ = await this.client.api.users('@me').settings.patch(data); + this._patch(data_); + return this; + } +} + +module.exports = GuildSettingManager; diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 7bf2e4d..7d5b7dc 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -17,6 +17,7 @@ const GuildEmojiManager = require('../managers/GuildEmojiManager'); const GuildInviteManager = require('../managers/GuildInviteManager'); const GuildMemberManager = require('../managers/GuildMemberManager'); const GuildScheduledEventManager = require('../managers/GuildScheduledEventManager'); +const GuildSettingManager = require('../managers/GuildSettingManager'); const GuildStickerManager = require('../managers/GuildStickerManager'); const PresenceManager = require('../managers/PresenceManager'); const RoleManager = require('../managers/RoleManager'); @@ -117,6 +118,12 @@ class Guild extends AnonymousGuild { */ this.autoModerationRules = new AutoModerationRuleManager(this); + /** + * All of the settings {@link Object} + * @type {GuildSettingManager} + */ + this.settings = new GuildSettingManager(this); + if (!data) return; if (data.unavailable) { /** diff --git a/typings/index.d.ts b/typings/index.d.ts index fc52ce7..56aa1a1 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1205,6 +1205,7 @@ export class Guild extends AnonymousGuild { public readonly safetyAlertsChannel: TextChannel | null; public safetyAlertsChannelId: Snowflake | null; public scheduledEvents: GuildScheduledEventManager; + public settings: GuildSettingManager; public readonly shard: WebSocketShard; public shardId: number; public stageInstances: StageInstanceManager; @@ -3799,6 +3800,26 @@ export class ClientUserSettingManager extends BaseManager { public removeRestrictedGuild(guildId: GuildResolvable): Promise; } +export class GuildSettingManager extends BaseManager { + private constructor(guild: Guild); + public readonly raw?: 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): Promise; +} + export interface CustomStatusOption { text?: string | null; expires_at?: string | null; @@ -3842,6 +3863,40 @@ export interface RawUserSettingsData { 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 type MappedGuildChannelTypes = EnumValueMapped< typeof ChannelTypes, {