discord.js-selfbot-v13/src/structures/Invite.js

349 lines
9.8 KiB
JavaScript
Raw Normal View History

2022-03-19 10:37:45 +00:00
'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 Permissions = require('../util/Permissions');
// TODO: Convert `inviter` and `channel` in this class to a getter.
2022-03-19 10:37:45 +00:00
/**
* 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.resolve(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);
2022-03-19 10:37:45 +00:00
} else {
this.inviterId ??= null;
}
if ('inviter' in data) {
/**
* The user who created this invite
* @type {?User}
*/
this.inviter ??= this.client.users._add(data.inviter);
2022-03-19 10:37:45 +00:00
this.inviterId = data.inviter.id;
} else {
this.inviter ??= null;
2022-03-19 10:37:45 +00:00
}
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
* @typedef {number} TargetType
* @see {@link https://discord.com/developers/docs/resources/invite#invite-object-invite-target-types}
*/
2022-03-19 10:37:45 +00:00
if ('target_type' in data) {
/**
* The target type
* @type {?TargetType}
2022-03-19 10:37:45 +00:00
*/
this.targetType = data.target_type;
} else {
this.targetType ??= null;
}
if ('channel_id' in data) {
/**
* The channel's id this invite is for
* @type {Snowflake}
2022-03-19 10:37:45 +00:00
*/
this.channelId = data.channel_id;
this.channel = this.client.channels.cache.get(data.channel_id);
2022-03-19 10:37:45 +00:00
}
if ('channel' in data) {
/**
* The channel this invite is for
* @type {Channel}
2022-03-19 10:37:45 +00:00
*/
this.channel ??= this.client.channels._add(data.channel, this.guild, { cache: false });
2022-03-19 10:37:45 +00:00
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();
2022-03-19 10:37:45 +00:00
} else {
this.createdTimestamp ??= null;
}
if ('expires_at' in data) this._expiresTimestamp = new Date(data.expires_at).getTime();
2022-03-19 10:37:45 +00:00
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;
}
}
/**
* The time the invite was created at
* @type {?Date}
* @readonly
*/
get createdAt() {
return this.createdTimestamp ? new Date(this.createdTimestamp) : null;
2022-03-19 10:37:45 +00:00
}
/**
* 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.me) throw new Error('GUILD_UNCACHED_ME');
return (
this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) ||
guild.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD)
2022-03-19 10:37:45 +00:00
);
}
/**
* 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;
2022-03-19 10:37:45 +00:00
}
/**
* The URL to the invite
* @type {string}
* @readonly
*/
get url() {
return Endpoints.invite(this.client.options.http.invite, this.code);
2022-03-19 10:37:45 +00:00
}
/**
* 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;
}
/**
* Join this Guild using this invite.
* @param {Boolean} autoVerify Whether to automatically verify member
* @returns {Promise<void>}
* @example
* await client.fetchInvite('code').then(async invite => {
* await invite.acceptInvite();
* });
*/
async acceptInvite(autoVerify = true) {
await this.client.api.invites(this.code).post({});
if (autoVerify) {
const getForm = await this.client.api
.guilds(this.guild.id)['member-verification']
.get({ query: { with_guild: false, invite_code: this.code } });
const form = Object.assign(getForm.form_fields[0], { response: true });
// Respond to the form
// https://discord.com/api/v9/guilds/:id/requests/@me
await this.client.api.guilds(this.guild.id).requests['@me'].put({ data: { form_fields: [form] } });
}
return void 0;
}
2022-03-19 10:37:45 +00:00
}
/**
* 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;