import Client from "../Client.js";
import { INVITE_BASE_URL, TO_JSON_TYPES_ENUM } from "../constants.js";
import GluonCacheOptions from "../managers/GluonCacheOptions.js";
import GuildCacheOptions from "../managers/GuildCacheOptions.js";
import User from "./User.js";
import util from "util";
/**
* Represents a guild invite.
*/
class Invite {
#_client;
#_guild_id;
#_code;
#_channel_id;
#uses;
#expires;
#inviter;
#max_uses;
/**
* Creates the structure for an invite.
* @param {Client} client The client instance.
* @param {Object} data The raw invite data from Discord.
* @param {Object} options Additional options for this structure.
* @param {String} options.guildId The id of the guild that the invite belongs to.
* @param {Boolean?} options.nocache Whether this invite should be cached or not.
* @see {@link https://discord.com/developers/docs/resources/invite#invite-object-invite-structure}
*/
constructor(client, data, { guildId, nocache = false } = { nocache: false }) {
if (!(client instanceof Client))
throw new TypeError("GLUON: Client must be an instance of Client");
if (typeof data !== "object")
throw new TypeError("GLUON: Data must be an object");
if (typeof guildId !== "string")
throw new TypeError("GLUON: Guild ID must be a string");
if (typeof nocache !== "boolean")
throw new TypeError("GLUON: No cache must be a boolean");
/**
* The client instance.
* @type {Client}
* @private
*/
this.#_client = client;
/**
* The id of the guild that this role belongs to.
* @type {BigInt}
* @private
*/
this.#_guild_id = BigInt(guildId);
/**
* The code for the invite.
* @type {String}
* @private
*/
this.#_code = data.code;
/**
* The id of the channel the invite is directed to.
* @type {BigInt}
* @private
*/
if (data.channel?.id) this.#_channel_id = BigInt(data.channel.id);
if (data.inviter)
/**
* The user who created the invite.
* @type {User?}
* @private
*/
this.#inviter = new User(this.#_client, data.inviter, { nocache });
if (typeof data.uses == "number")
/**
* The number of times the invite has been used.
* @type {Number?}
* @private
*/
this.#uses = data.uses;
if (data.expires_at)
/**
* The UNIX timestamp of when the invite expires.
* @type {Number?}
* @private
*/
this.#expires = (new Date(data.expires_at).getTime() / 1000) | 0;
else if (typeof data.expires == "number")
this.#expires = data.expires / 1000;
else if (
typeof data.max_age == "number" &&
data.max_age != 0 &&
data.created_at
)
this.#expires =
((new Date(data.created_at).getTime() / 1000) | 0) + data.max_age;
if (typeof data.max_uses == "number")
/**
* The maximum number of uses allowed for the invite.
* @type {Number?}
* @private
*/
this.#max_uses = data.max_uses;
if (
nocache === false &&
Invite.shouldCache(
this.#_client._cacheOptions,
this.guild._cacheOptions,
) &&
this.#_code &&
((this.#expires && this.#expires > Date.now() / 1000) || !this.#expires)
)
this.guild.invites.set(data.code, this);
}
/**
* The id of the channel the invite is directed to.
* @type {String}
* @readonly
* @public
*/
get channelId() {
return String(this.#_channel_id);
}
/**
* The channel the invite is directed to.
* @type {(TextChannel | VoiceChannel)?}
* @readonly
* @public
*/
get channel() {
return this.guild.channels.get(this.channelId) || null;
}
/**
* The code of the invite.
* @type {String}
* @readonly
* @public
*/
get id() {
return this.code;
}
/**
* The code of the invite.
* @type {String}
* @readonly
* @public
*/
get code() {
return this.#_code;
}
/**
* The id of the guild that this invite belongs to.
* @type {String}
* @readonly
* @public
*/
get guildId() {
return String(this.#_guild_id);
}
/**
* The guild that this role belongs to.
* @type {Guild?}
* @readonly
* @public
*/
get guild() {
return this.#_client.guilds.get(this.guildId) || null;
}
/**
* The number of times the invite has been used.
* @type {Number?}
* @readonly
* @public
*/
get uses() {
return this.#uses;
}
/**
* The UNIX timestamp of when the invite expires.
* @type {Number?}
* @readonly
* @public
*/
get expires() {
return this.#expires;
}
/**
* The user who created the invite.
* @type {User?}
* @readonly
* @public
*/
get inviter() {
return this.#inviter;
}
/**
* The URL of the invite.
* @type {String}
* @readonly
* @public
*/
get url() {
return Invite.getUrl(this.code);
}
/**
* The maximum number of uses allowed for the invite.
* @type {Number?}
* @readonly
* @public
*/
get maxUses() {
return this.#max_uses;
}
/**
* Returns the URL of the invite.
* @param {String} code The code of the invite.
* @returns {String}
* @public
* @static
* @method
*/
static getUrl(code) {
if (typeof code != "string")
throw new TypeError("GLUON: Invalid invite code.");
return `${INVITE_BASE_URL}/${code}`;
}
/**
* Determines whether the invite should be cached.
* @param {GluonCacheOptions} gluonCacheOptions The cache options for the client.
* @param {GuildCacheOptions} guildCacheOptions The cache options for the guild.
* @returns {Boolean}
* @public
* @static
* @method
*/
static shouldCache(gluonCacheOptions, guildCacheOptions) {
if (!(gluonCacheOptions instanceof GluonCacheOptions))
throw new TypeError(
"GLUON: Gluon cache options must be a GluonCacheOptions.",
);
if (!(guildCacheOptions instanceof GuildCacheOptions))
throw new TypeError(
"GLUON: Guild cache options must be a GuildCacheOptions.",
);
if (gluonCacheOptions.cacheInvites === false) return false;
if (guildCacheOptions.inviteCaching === false) return false;
return true;
}
/**
* @method
* @public
*/
toString() {
return `<Invite: ${this.code}>`;
}
/**
* @method
* @public
*/
[util.inspect.custom]() {
return this.toString();
}
/**
* Returns the JSON representation of this structure.
* @param {Number} format The format to return the data in.
* @returns {Object}
* @public
* @method
*/
toJSON(format) {
switch (format) {
case TO_JSON_TYPES_ENUM.CACHE_FORMAT:
case TO_JSON_TYPES_ENUM.STORAGE_FORMAT: {
return {
code: this.code,
channel: this.channel.toJSON(format),
inviter: this.inviter.toJSON(format),
uses: this.uses,
expires: this.expires ? this.expires * 1000 : undefined,
max_uses: this.maxUses,
};
}
case TO_JSON_TYPES_ENUM.DISCORD_FORMAT:
default: {
return {
code: this.code,
channel: this.channel.toJSON(format),
inviter: this.inviter.toJSON(format),
uses: this.uses,
expires_at: this.expires
? new Date(this.expires * 1000).toISOString()
: undefined,
max_uses: this.maxUses,
};
}
}
}
}
export default Invite;