UNPKG

discord.js-selfbot-v13

Version:

A unofficial discord.js fork for creating selfbots [Based on discord.js v13]

359 lines (322 loc) 9.97 kB
'use strict'; const Base = require('./Base'); const { GuildScheduledEvent } = require('./GuildScheduledEvent'); const IntegrationApplication = require('./IntegrationApplication'); const InviteStageInstance = require('./InviteStageInstance'); const { Error } = require('../errors'); const { Endpoints } = require('../util/Constants'); const InviteFlags = require('../util/InviteFlags'); const Permissions = require('../util/Permissions'); // TODO: Convert `inviter` and `channel` in this class to a getter. /** * Represents an invitation to a guild channel. * @extends {Base} */ class Invite extends Base { constructor(client, data) { super(client); this._patch(data); } _patch(data) { const InviteGuild = require('./InviteGuild'); /** * The guild the invite is for including welcome screen data if present * @type {?(Guild|InviteGuild)} */ this.guild ??= null; if (data.guild) { this.guild = this.client.guilds.cache.get(data.guild.id) ?? new InviteGuild(this.client, data.guild); } if ('code' in data) { /** * The code for this invite * @type {string} */ this.code = data.code; } if ('approximate_presence_count' in data) { /** * The approximate number of online members of the guild this invite is for * <info>This is only available when the invite was fetched through {@link Client#fetchInvite}.</info> * @type {?number} */ this.presenceCount = data.approximate_presence_count; } else { this.presenceCount ??= null; } if ('approximate_member_count' in data) { /** * The approximate total number of members of the guild this invite is for * <info>This is only available when the invite was fetched through {@link Client#fetchInvite}.</info> * @type {?number} */ this.memberCount = data.approximate_member_count; } else { this.memberCount ??= null; } if ('temporary' in data) { /** * Whether or not this invite only grants temporary membership * <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch} * or created through {@link GuildInviteManager#create}.</info> * @type {?boolean} */ this.temporary = data.temporary ?? null; } else { this.temporary ??= null; } if ('max_age' in data) { /** * The maximum age of the invite, in seconds, 0 if never expires * <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch} * or created through {@link GuildInviteManager#create}.</info> * @type {?number} */ this.maxAge = data.max_age; } else { this.maxAge ??= null; } if ('uses' in data) { /** * How many times this invite has been used * <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch} * or created through {@link GuildInviteManager#create}.</info> * @type {?number} */ this.uses = data.uses; } else { this.uses ??= null; } if ('max_uses' in data) { /** * The maximum uses of this invite * <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch} * or created through {@link GuildInviteManager#create}.</info> * @type {?number} */ this.maxUses = data.max_uses; } else { this.maxUses ??= null; } if ('inviter_id' in data) { /** * The user's id who created this invite * @type {?Snowflake} */ this.inviterId = data.inviter_id; this.inviter = this.client.users.resolve(data.inviter_id); } else { this.inviterId ??= null; } if ('inviter' in data) { /** * The user who created this invite * @type {?User} */ this.inviter ??= this.client.users._add(data.inviter); this.inviterId = data.inviter.id; } else { this.inviter ??= null; } if ('target_user' in data) { /** * The user whose stream to display for this voice channel stream invite * @type {?User} */ this.targetUser = this.client.users._add(data.target_user); } else { this.targetUser ??= null; } if ('target_application' in data) { /** * The embedded application to open for this voice channel embedded application invite * @type {?IntegrationApplication} */ this.targetApplication = new IntegrationApplication(this.client, data.target_application); } else { this.targetApplication ??= null; } /** * The type of the invite target: * * 1: STREAM * * 2: EMBEDDED_APPLICATION * * 3: ROLE_SUBSCRIPTIONS * * 4: CREATOR_PAGE * @typedef {number} TargetType * @see {@link https://discord.com/developers/docs/resources/invite#invite-object-invite-target-types} */ if ('target_type' in data) { /** * The target type * @type {?TargetType} */ this.targetType = data.target_type; } else { this.targetType ??= null; } /** * The type of the invite: * * 0: GUILD * * 1: GROUP_DM * * 2: FRIEND * @typedef {number} InviteType * @see {@link https://docs.discord.food/resources/invite#invite-type} */ if ('type' in data) { /** * The type of invite * @type {?InviteType} */ this.type = data.type; } else { this.type ??= null; } if ('channel_id' in data) { /** * The channel's id this invite is for * @type {?Snowflake} */ this.channelId = data.channel_id; this.channel = this.client.channels.cache.get(data.channel_id); } if ('channel' in data && data.channel !== null) { /** * The channel this invite is for * @type {?Channel} */ this.channel ??= this.client.channels._add(data.channel, this.guild, { cache: false }); this.channelId ??= data.channel.id; } if ('created_at' in data) { /** * The timestamp this invite was created at * @type {?number} */ this.createdTimestamp = new Date(data.created_at).getTime(); } else { this.createdTimestamp ??= null; } if ('expires_at' in data) { this._expiresTimestamp = data.expires_at && Date.parse(data.expires_at); } else { this._expiresTimestamp ??= null; } if ('stage_instance' in data) { /** * The stage instance data if there is a public {@link StageInstance} in the stage channel this invite is for * @type {?InviteStageInstance} */ this.stageInstance = new InviteStageInstance(this.client, data.stage_instance, this.channel.id, this.guild.id); } else { this.stageInstance ??= null; } if ('guild_scheduled_event' in data) { /** * The guild scheduled event data if there is a {@link GuildScheduledEvent} in the channel this invite is for * @type {?GuildScheduledEvent} */ this.guildScheduledEvent = new GuildScheduledEvent(this.client, data.guild_scheduled_event); } else { this.guildScheduledEvent ??= null; } if ('flags' in data) { /** * The flags that are applied to the invite. * @type {?Readonly<InviteFlags>} */ this.flags = new InviteFlags(data.flags).freeze(); } else { this.flags ??= new InviteFlags().freeze(); } } /** * The time the invite was created at * @type {?Date} * @readonly */ get createdAt() { return this.createdTimestamp ? new Date(this.createdTimestamp) : null; } /** * Whether the invite is deletable by the client user * @type {boolean} * @readonly */ get deletable() { const guild = this.guild; if (!guild || !this.client.guilds.cache.has(guild.id)) return false; if (!guild.members.me) throw new Error('GUILD_UNCACHED_ME'); return ( this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) || guild.members.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD) ); } /** * The timestamp the invite will expire at * @type {?number} * @readonly */ get expiresTimestamp() { return ( this._expiresTimestamp ?? (this.createdTimestamp && this.maxAge ? this.createdTimestamp + this.maxAge * 1_000 : null) ); } /** * The time the invite will expire at * @type {?Date} * @readonly */ get expiresAt() { const { expiresTimestamp } = this; return expiresTimestamp ? new Date(expiresTimestamp) : null; } /** * The URL to the invite * @type {string} * @readonly */ get url() { return Endpoints.invite(this.client.options.http.invite, this.code); } /** * Deletes this invite. * @param {string} [reason] Reason for deleting this invite * @returns {Promise<Invite>} */ async delete(reason) { await this.client.api.invites[this.code].delete({ reason }); return this; } /** * When concatenated with a string, this automatically concatenates the invite's URL instead of the object. * @returns {string} * @example * // Logs: Invite: https://discord.gg/A1b2C3 * console.log(`Invite: ${invite}`); */ toString() { return this.url; } toJSON() { return super.toJSON({ url: true, expiresTimestamp: true, presenceCount: false, memberCount: false, uses: false, channel: 'channelId', inviter: 'inviterId', guild: 'guildId', }); } valueOf() { return this.code; } } /** * Regular expression that globally matches Discord invite links * @type {RegExp} */ Invite.INVITES_PATTERN = /discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/gi; module.exports = Invite;