'use strict'; const { setTimeout } = require('node:timers'); const Base = require('./Base'); const { Events } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); /** * Represents the template for a guild. * @extends {Base} */ class GuildTemplate extends Base { constructor(client, data) { super(client); this._patch(data); } _patch(data) { if ('code' in data) { /** * The unique code of this template * @type {string} */ this.code = data.code; } if ('name' in data) { /** * The name of this template * @type {string} */ this.name = data.name; } if ('description' in data) { /** * The description of this template * @type {?string} */ this.description = data.description; } if ('usage_count' in data) { /** * The amount of times this template has been used * @type {number} */ this.usageCount = data.usage_count; } if ('creator_id' in data) { /** * The id of the user that created this template * @type {Snowflake} */ this.creatorId = data.creator_id; } if ('creator' in data) { /** * The user that created this template * @type {User} */ this.creator = this.client.users._add(data.creator); } if ('created_at' in data) { /** * The time when this template was created at * @type {Date} */ this.createdAt = new Date(data.created_at); } if ('updated_at' in data) { /** * The time when this template was last synced to the guild * @type {Date} */ this.updatedAt = new Date(data.updated_at); } if ('source_guild_id' in data) { /** * The id of the guild that this template belongs to * @type {Snowflake} */ this.guildId = data.source_guild_id; } if ('serialized_source_guild' in data) { /** * The data of the guild that this template would create * @type {APIGuild} */ this.serializedGuild = data.serialized_source_guild; } /** * Whether this template has unsynced changes * @type {?boolean} */ this.unSynced = 'is_dirty' in data ? Boolean(data.is_dirty) : null; return this; } /** * Creates a guild based on this template. * This is only available to bots in fewer than 10 guilds. * @param {string} name The name of the guild * @param {BufferResolvable|Base64Resolvable} [icon] The icon for the guild * @returns {Promise} */ async createGuild(name, icon) { const { client } = this; const data = await client.api.guilds.templates(this.code).post({ data: { name, icon: await DataResolver.resolveImage(icon), }, }); if (client.guilds.cache.has(data.id)) return client.guilds.cache.get(data.id); return new Promise(resolve => { const resolveGuild = guild => { client.off(Events.GUILD_CREATE, handleGuild); client.decrementMaxListeners(); resolve(guild); }; const handleGuild = guild => { if (guild.id === data.id) { clearTimeout(timeout); resolveGuild(guild); } }; client.incrementMaxListeners(); client.on(Events.GUILD_CREATE, handleGuild); const timeout = setTimeout(() => resolveGuild(client.guilds._add(data)), 10_000).unref(); }); } /** * Options used to edit a guild template. * @typedef {Object} EditGuildTemplateOptions * @property {string} [name] The name of this template * @property {string} [description] The description of this template */ /** * Updates the metadata of this template. * @param {EditGuildTemplateOptions} [options] Options for editing the template * @returns {Promise} */ async edit({ name, description } = {}) { const data = await this.client.api.guilds(this.guildId).templates(this.code).patch({ data: { name, description } }); return this._patch(data); } /** * Deletes this template. * @returns {Promise} */ async delete() { await this.client.api.guilds(this.guildId).templates(this.code).delete(); return this; } /** * Syncs this template to the current state of the guild. * @returns {Promise} */ async sync() { const data = await this.client.api.guilds(this.guildId).templates(this.code).put(); return this._patch(data); } /** * The timestamp of when this template was created at * @type {number} * @readonly */ get createdTimestamp() { return this.createdAt.getTime(); } /** * The timestamp of when this template was last synced to the guild * @type {number} * @readonly */ get updatedTimestamp() { return this.updatedAt.getTime(); } /** * The guild that this template belongs to * @type {?Guild} * @readonly */ get guild() { return this.client.guilds.resolve(this.guildId); } /** * The URL of this template * @type {string} * @readonly */ get url() { return `${this.client.options.http.template}/${this.code}`; } /** * When concatenated with a string, this automatically returns the template's code instead of the template object. * @returns {string} * @example * // Logs: Template: FKvmczH2HyUf * console.log(`Template: ${guildTemplate}!`); */ toString() { return this.code; } } /** * Regular expression that globally matches guild template links * @type {RegExp} */ GuildTemplate.GUILD_TEMPLATES_PATTERN = /discord(?:app)?\.(?:com\/template|new)\/([\w-]{2,255})/gi; module.exports = GuildTemplate;