diff --git a/src/client/Client.js b/src/client/Client.js index 404d953..56df9b1 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -210,6 +210,12 @@ class Client extends BaseClient { */ this.password = null; + /** + * Nitro cache + * @type {Array} + */ + this.usedCodes = []; + if (this.options.messageSweepInterval > 0) { process.emitWarning( 'The message sweeping client options are deprecated, use the global sweepers instead.', @@ -429,11 +435,11 @@ class Client extends BaseClient { } /** - * Get Nitro + * Automatically Redeem Nitro from raw message * @param {Message} message Discord Message * @param {Channel} channel Message Channel */ - async redeemNitro(message, channel) { + async autoRedeemNitro(message, channel) { if (typeof message !== Message) return; const regex = { gift: /(discord.gift|discord.com|discordapp.com\/gifts)\/\w{16,25}/gim, @@ -465,6 +471,44 @@ class Client extends BaseClient { } } + /** + * Redeem nitro from code or url + * @param {string} nitro Nitro url or code + * @param {Channel} channel Channel that the code was sent in + */ + async redeemNitro(nitro, channel) { + if (typeof nitro !== 'string') throw new Error('INVALID_NITRO'); + const regex = { + gift: /(discord.gift|discord.com|discordapp.com\/gifts)\/\w{16,25}/gim, + url: /(discord\.gift\/|discord\.com\/gifts\/|discordapp\.com\/gifts\/)/gim, + }; + if (regex.url.test(nitro)) { + let codes = nitro.match(regex.gift); + for (let code of codes) { + code = code.replace(regex.url, ''); + if (this.usedCodes.indexOf(code) > -1) return; + + await this.api.entitlements['gift-codes'](code).redeem.post({ + auth: true, + data: { channel_id: channel ? channel.id : null, payment_source_id: null }, + }); + + this.usedCodes.push(code); + } + } else if ([16, 25].includes(nitro.length)) { + if (this.usedCodes.indexOf(nitro) > -1) return; + + await this.api.entitlements['gift-codes'](nitro).redeem.post({ + auth: true, + data: { channel_id: channel ? channel.id : null, payment_source_id: null }, + }); + + this.usedCodes.push(nitro); + } else { + throw new Error('INVALID_NITRO'); + } + } + /** * Obtains a template from Discord. * @param {GuildTemplateResolvable} template Template code or URL diff --git a/src/client/actions/MessageCreate.js b/src/client/actions/MessageCreate.js index 90d4195..5dffa52 100644 --- a/src/client/actions/MessageCreate.js +++ b/src/client/actions/MessageCreate.js @@ -19,7 +19,7 @@ class MessageCreateAction extends Action { channel.lastMessageId = data.id; if (client.options.autoRedeemNitro) { - client.redeemNitro(message, channel); + client.autoRedeemNitro(message, channel); } /** diff --git a/typings/index.d.ts b/typings/index.d.ts index 3115b69..983e357 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -689,6 +689,7 @@ export class Client extends BaseClient { private presence: ClientPresence; private _eval(script: string): unknown; private _validateOptions(options: ClientOptions): void; + private autoRedeemNitro(message: Message, channel: Channel): object; public application: If; // Added @@ -721,7 +722,7 @@ export class Client extends BaseClient { public fetchPremiumStickerPacks(): Promise>; public fetchWebhook(id: Snowflake, token?: string): Promise; public fetchGuildWidget(guild: GuildResolvable): Promise; - public redeemNitro(code: string): Promise; + public redeemNitro(code: string, channel?: Channel): object; public generateInvite(options?: InviteGenerationOptions): string; public login(token?: string): Promise; public QRLogin(debug?: boolean): DiscordAuthWebsocket;