From f361bed628539094b59ed0714e81f9c0ef5274ee Mon Sep 17 00:00:00 2001 From: March 7th <71698422+aiko-chan-ai@users.noreply.github.com> Date: Fri, 8 Apr 2022 19:00:31 +0700 Subject: [PATCH] Selfbot update added headers to discord hard to detect selfbot 'x-fingerprint' cookies 'x-super-properties' --- DOCUMENT.md | 1 + package.json | 2 +- src/client/Client.js | 40 ++++++++++ src/util/Options.js | 172 ++++++++++++++++++++++--------------------- typings/index.d.ts | 162 ++++++++++++++++++++-------------------- 5 files changed, 212 insertions(+), 165 deletions(-) diff --git a/DOCUMENT.md b/DOCUMENT.md index 72a4ed4..14b5b9a 100644 --- a/DOCUMENT.md +++ b/DOCUMENT.md @@ -34,6 +34,7 @@ const client = new Client({ new Client({ checkUpdate: true, // Check Package Update (Bot Ready) [Enable Default] readyStatus: false, // Set Custom Status sync from Account (Bot Ready) [Disable Default] + autoCookie: true, // Auto added Cookie and Fingerprint [Enable Default](https://github.com/aiko-chan-ai/discord.js-selfbot-v13/blob/main/DOCUMENT.md#http-options) }) ``` diff --git a/package.json b/package.json index 2db673b..d209468 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discord.js-selfbot-v13", - "version": "1.2.8", + "version": "1.3.0", "description": "A unofficial discord.js fork for creating selfbots [Based on discord.js v13]", "main": "./src/index.js", "types": "./typings/index.d.ts", diff --git a/src/client/Client.js b/src/client/Client.js index 3cbccdf..d34a3ee 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -260,6 +260,46 @@ class Client extends BaseClient { .join('.')}`, ); + if (this.options.autoCookie) { + /* Auto find fingerprint and add Cookie */ + let cookie = ''; + await require('axios')({ + method: 'get', + url: 'https://discord.com/api/v9/experiments', + headers: this.options.http.headers, + }) + .then((res) => { + if (!'set-cookie' in res.headers) return; + res.headers['set-cookie'].map((line) => { + line.split('; ').map((arr) => { + if ( + arr.startsWith('Expires') || + arr.startsWith('Path') || + arr.startsWith('Domain') || + arr.startsWith('HttpOnly') || + arr.startsWith('Secure') || + arr.startsWith('Max-Age') || + arr.startsWith('SameSite') + ) { + return; + } else { + cookie += `${arr}; `; + } + }); + }); + this.options.http.headers['Cookie'] = `${cookie}locale=en`; + this.options.http.headers['x-fingerprint'] = res.data.fingerprint; + this.emit(Events.DEBUG, `Added Cookie: ${cookie}`); + this.emit(Events.DEBUG, `Added Fingerprint: ${res.data.fingerprint}`); + }) + .catch((err) => { + this.emit( + Events.DEBUG, + `Finding Cookie and Fingerprint failed: ${err.message}`, + ); + }); + } + if (this.options.presence) { this.options.ws.presence = this.presence._parse(this.options.presence); } diff --git a/src/util/Options.js b/src/util/Options.js index 2b24a03..19554e4 100644 --- a/src/util/Options.js +++ b/src/util/Options.js @@ -132,91 +132,93 @@ class Options extends null { */ static createDefault() { return { - jsonTransformer: (object) => JSONBig.stringify(object), - checkUpdate: true, - readyStatus: false, - waitGuildTimeout: 15_000, - shardCount: 1, - makeCache: this.cacheWithLimits(this.defaultMakeCacheSettings), - messageCacheLifetime: 0, - messageSweepInterval: 0, - invalidRequestWarningInterval: 0, - intents: 65535, - partials: [ - 'USER', - 'CHANNEL', - 'GUILD_MEMBER', - 'MESSAGE', - 'REACTION', - 'GUILD_SCHEDULED_EVENT', - ], // Enable the partials - restWsBridgeTimeout: 5_000, - restRequestTimeout: 15_000, - restGlobalRateLimit: 0, - retryLimit: 1, - restTimeOffset: 500, - restSweepInterval: 60, - failIfNotExists: false, - userAgentSuffix: [], - presence: {}, - sweepers: {}, - ws: { - large_threshold: 50, - compress: false, - properties: { - //$os: 'iPhone14,5', - //$browser: 'Discord iOS', - //$device: 'iPhone14,5 OS 15.2', - $os: 'Windows', - $browser: 'Discord Client', - $device: 'ASUS ROG Phone 5', - }, - version: 9, - }, - http: { - headers: { - Accept: '*/*', - 'Accept-Encoding': 'gzip, deflate, br', - 'Accept-Language': 'en-US,en;q=0.9', - 'Cache-Control': 'no-cache', - Pragma: 'no-cache', - Referer: 'https://discord.com/channels/@me', - 'Sec-Ch-Ua': '" Not A;Brand";v="99" "', - 'Sec-Ch-Ua-Mobile': '?0', - 'Sec-Ch-Ua-Platform': '"iOS"', - 'Sec-Fetch-Dest': 'empty', - 'Sec-Fetch-Mode': 'cors', - 'Sec-Fetch-Site': 'same-origin', - 'X-Debug-Options': 'bugReporterEnabled', - // https://github.com/Merubokkusu/Discord-S.C.U.M/issues/66#issuecomment-1009171667 - 'x-super-properties': `${Buffer.from( - JSONBig.stringify({ - os: 'Windows', - browser: 'Discord Client', - release_channel: 'stable', - client_version: '1.0.9004', - os_version: '10.0.22000', - os_arch: 'x64', - system_locale: 'en-US', - client_build_number: 122087, - client_event_source: null, - }), - 'ascii', - ).toString('base64')}`, - 'X-Discord-Locale': 'en-US', - Origin: 'https://discord.com', - 'user-agent': - 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) discord/1.0.9004 Chrome/91.0.4472.164 Electron/13.6.6 Safari/537.36', - }, - agent: {}, - version: 9, - api: 'https://discord.com/api', - cdn: 'https://cdn.discordapp.com', - invite: 'https://discord.gg', - template: 'https://discord.new', - scheduledEvent: 'https://discord.com/events', - }, - }; + jsonTransformer: (object) => JSONBig.stringify(object), + checkUpdate: true, + readyStatus: false, + autoCookie: true, + waitGuildTimeout: 15_000, + shardCount: 1, + makeCache: this.cacheWithLimits(this.defaultMakeCacheSettings), + messageCacheLifetime: 0, + messageSweepInterval: 0, + invalidRequestWarningInterval: 0, + intents: 65535, + partials: [ + 'USER', + 'CHANNEL', + 'GUILD_MEMBER', + 'MESSAGE', + 'REACTION', + 'GUILD_SCHEDULED_EVENT', + ], // Enable the partials + restWsBridgeTimeout: 5_000, + restRequestTimeout: 15_000, + restGlobalRateLimit: 0, + retryLimit: 1, + restTimeOffset: 500, + restSweepInterval: 60, + failIfNotExists: false, + userAgentSuffix: [], + presence: {}, + sweepers: {}, + ws: { + large_threshold: 50, + compress: false, + properties: { + //$os: 'iPhone14,5', + //$browser: 'Discord iOS', + //$device: 'iPhone14,5 OS 15.2', + $os: 'Windows', + $browser: 'Discord Client', + $device: 'ASUS ROG Phone 5', + }, + version: 9, + }, + http: { + headers: { + Accept: '*/*', + // 'Accept-Encoding': 'gzip, deflate, br', => cause axios bug + 'Accept-Language': 'en-US,en;q=0.9', + 'Cache-Control': 'no-cache', + Pragma: 'no-cache', + Referer: 'https://discord.com/channels/@me', + 'Sec-Ch-Ua': + '"Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100', + 'Sec-Ch-Ua-Mobile': '?0', + 'Sec-Ch-Ua-Platform': '"Windows"', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'X-Debug-Options': 'bugReporterEnabled', + // https://github.com/Merubokkusu/Discord-S.C.U.M/issues/66#issuecomment-1009171667 + 'x-super-properties': `${Buffer.from( + JSONBig.stringify({ + os: 'Windows', + browser: 'Discord Client', + release_channel: 'stable', + client_version: '1.0.9004', + os_version: '10.0.22000', + os_arch: 'x64', + system_locale: 'en-US', + client_build_number: 122087, + client_event_source: null, + }), + 'ascii', + ).toString('base64')}`, + 'X-Discord-Locale': 'en-US', + Origin: 'https://discord.com', + 'user-agent': + 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) discord/1.0.9004 Chrome/91.0.4472.164 Electron/13.6.6 Safari/537.36', + }, + agent: {}, + version: 9, + api: 'https://discord.com/api', + cdn: 'https://cdn.discordapp.com', + invite: 'https://discord.gg', + template: 'https://discord.new', + scheduledEvent: 'https://discord.com/events', + }, + }; } /** diff --git a/typings/index.d.ts b/typings/index.d.ts index 54ad343..3e0d974 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -641,7 +641,7 @@ export class ClientUser extends User { public setPresence(data: PresenceData): ClientPresence; public setStatus(status: PresenceStatusData, shardId?: number | number[]): ClientPresence; public setUsername(username: string, password: string): Promise; - public setHypeSquad(type: HypeSquadOptions): Promise; + public setHypeSquad(type: HypeSquadOptions): Promise; public setAccentColor(color: ColorResolvable): Promise; public setDiscriminator(discriminator: string, password: string): Promise; public setAboutMe(bio: string): Promise; @@ -652,15 +652,15 @@ export class ClientUser extends User { public deleteAccount(password: string): Promise; // Selfbot public readonly nitro: boolean; - /** - * Nitro Status - * `0`: None - * `1`: Classic - * `2`: Boost - * @external - * https://discord.com/developers/docs/resources/user#user-object-premium-types - * @type {Number} - */ + /** + * Nitro Status + * `0`: None + * `1`: Classic + * `2`: Boost + * @external + * https://discord.com/developers/docs/resources/user#user-object-premium-types + * @type {Number} + */ public readonly nitroType: NitroType; public readonly phoneNumber: String; public readonly nsfwAllowed: boolean; @@ -1036,17 +1036,17 @@ export class GuildAuditLogs { export class GuildAuditLogsEntry< TActionRaw extends GuildAuditLogsResolvable = 'ALL', TAction = TActionRaw extends keyof GuildAuditLogsIds - ? GuildAuditLogsIds[TActionRaw] - : TActionRaw extends null - ? 'ALL' - : TActionRaw, + ? GuildAuditLogsIds[TActionRaw] + : TActionRaw extends null + ? 'ALL' + : TActionRaw, TActionType extends GuildAuditLogsActionType = TAction extends keyof GuildAuditLogsTypes - ? GuildAuditLogsTypes[TAction][1] - : 'ALL', + ? GuildAuditLogsTypes[TAction][1] + : 'ALL', TTargetType extends GuildAuditLogsTarget = TAction extends keyof GuildAuditLogsTypes - ? GuildAuditLogsTypes[TAction][0] - : 'UNKNOWN', -> { + ? GuildAuditLogsTypes[TAction][0] + : 'UNKNOWN', + > { private constructor(logs: GuildAuditLogs, guild: Guild, data: RawGuildAuditLogEntryData); public action: TAction; public actionType: TActionType; @@ -1284,7 +1284,7 @@ export class HTTPError extends Error { } // tslint:disable-next-line:no-empty-interface - Merge RateLimitData into RateLimitError to not have to type it again -export interface RateLimitError extends RateLimitData {} +export interface RateLimitError extends RateLimitData { } export class RateLimitError extends Error { private constructor(data: RateLimitData); public name: 'RateLimitError'; @@ -1337,7 +1337,7 @@ export type CacheTypeReducer< RawType = CachedType, PresentType = CachedType | RawType, Fallback = PresentType | null, -> = [State] extends ['cached'] + > = [State] extends ['cached'] ? CachedType : [State] extends ['raw'] ? RawType @@ -1483,25 +1483,25 @@ export class LimitedCollection extends Collection { export type MessageCollectorOptionsParams = | { - componentType?: T; - } & MessageComponentCollectorOptions[T]>; + componentType?: T; + } & MessageComponentCollectorOptions[T]>; export type MessageChannelCollectorOptionsParams< T extends MessageComponentTypeResolvable, Cached extends boolean = boolean, -> = + > = | { - componentType?: T; - } & MessageChannelComponentCollectorOptions[T]>; + componentType?: T; + } & MessageChannelComponentCollectorOptions[T]>; export type AwaitMessageCollectorOptionsParams< T extends MessageComponentTypeResolvable, Cached extends boolean = boolean, -> = + > = | { componentType?: T } & Pick< - InteractionCollectorOptions[T]>, - keyof AwaitMessageComponentOptions - >; + InteractionCollectorOptions[T]>, + keyof AwaitMessageComponentOptions + >; export interface StringMappedInteractionTypes { BUTTON: ButtonInteraction; @@ -1710,7 +1710,7 @@ export class MessageComponentInteraction e export class MessageContextMenuInteraction< Cached extends CacheType = CacheType, -> extends ContextMenuInteraction { + > extends ContextMenuInteraction { public readonly targetMessage: NonNullable['message']>; public inGuild(): this is MessageContextMenuInteraction<'present'>; public inCachedGuild(): this is MessageContextMenuInteraction<'cached'>; @@ -2965,7 +2965,7 @@ export class ApplicationCommandManager< ApplicationCommandScope = ApplicationCommand<{ guild: GuildResolvable }>, PermissionsOptionsExtras = { guild: GuildResolvable }, PermissionsGuildType = null, -> extends CachedManager { + > extends CachedManager { protected constructor(client: Client, iterable?: Iterable, user: User); public permissions: ApplicationCommandPermissionsManager< { command?: ApplicationCommandResolvable } & PermissionsOptionsExtras, @@ -3012,7 +3012,7 @@ export class ApplicationCommandPermissionsManager< FullPermissionsOptions, GuildType, CommandIdType, -> extends BaseManager { + > extends BaseManager { private constructor(manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand, user: User); private manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand; @@ -3029,13 +3029,13 @@ export class ApplicationCommandPermissionsManager< public remove( options: | (FetchSingleOptions & { - users: UserResolvable | UserResolvable[]; - roles?: RoleResolvable | RoleResolvable[]; - }) + users: UserResolvable | UserResolvable[]; + roles?: RoleResolvable | RoleResolvable[]; + }) | (FetchSingleOptions & { - users?: UserResolvable | UserResolvable[]; - roles: RoleResolvable | RoleResolvable[]; - }), + users?: UserResolvable | UserResolvable[]; + roles: RoleResolvable | RoleResolvable[]; + }), ): Promise; public set( options: FetchSingleOptions & { permissions: ApplicationCommandPermissionData[] }, @@ -3197,7 +3197,7 @@ export class GuildScheduledEventManager extends CachedManager< public fetch(): Promise>; public fetch< T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, - >(options?: T): Promise>; + >(options?: T): Promise>; public edit>( guildScheduledEvent: GuildScheduledEventResolvable, options: GuildScheduledEventEditOptions, @@ -3734,12 +3734,12 @@ export interface ApplicationCommandChannelOption extends BaseApplicationCommandO export interface ApplicationCommandAutocompleteOption extends Omit { type: - | 'STRING' - | 'NUMBER' - | 'INTEGER' - | ApplicationCommandOptionTypes.STRING - | ApplicationCommandOptionTypes.NUMBER - | ApplicationCommandOptionTypes.INTEGER; + | 'STRING' + | 'NUMBER' + | 'INTEGER' + | ApplicationCommandOptionTypes.STRING + | ApplicationCommandOptionTypes.NUMBER + | ApplicationCommandOptionTypes.INTEGER; autocomplete: true; } @@ -3939,8 +3939,8 @@ export type CacheFactory = ( export type CacheWithLimitsOptions = { [K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager - ? LimitedCollectionOptions | number - : never; + ? LimitedCollectionOptions | number + : never; }; export interface CategoryCreateChannelOptions { @@ -4140,6 +4140,10 @@ export interface ClientOptions { ws?: WebSocketOptions; http?: HTTPOptions; rejectOnRateLimit?: string[] | ((data: RateLimitData) => boolean | Promise); + // add + checkUpdate?: boolean; + readyStatus?: boolean; + autoCookie?: boolean; } export type ClientPresenceStatus = 'online' | 'idle' | 'dnd'; @@ -4688,20 +4692,20 @@ export interface GuildAuditLogsEntryExtraField { MESSAGE_UNPIN: { channel: GuildTextBasedChannel | { id: Snowflake }; messageId: Snowflake }; MEMBER_DISCONNECT: { count: number }; CHANNEL_OVERWRITE_CREATE: - | Role - | GuildMember - | { id: Snowflake; name: string; type: OverwriteTypes.role } - | { id: Snowflake; type: OverwriteTypes.member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: OverwriteTypes.role } + | { id: Snowflake; type: OverwriteTypes.member }; CHANNEL_OVERWRITE_UPDATE: - | Role - | GuildMember - | { id: Snowflake; name: string; type: OverwriteTypes.role } - | { id: Snowflake; type: OverwriteTypes.member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: OverwriteTypes.role } + | { id: Snowflake; type: OverwriteTypes.member }; CHANNEL_OVERWRITE_DELETE: - | Role - | GuildMember - | { id: Snowflake; name: string; type: OverwriteTypes.role } - | { id: Snowflake; type: OverwriteTypes.member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: OverwriteTypes.role } + | { id: Snowflake; type: OverwriteTypes.member }; STAGE_INSTANCE_CREATE: StageChannel | { id: Snowflake }; STAGE_INSTANCE_DELETE: StageChannel | { id: Snowflake }; STAGE_INSTANCE_UPDATE: StageChannel | { id: Snowflake }; @@ -4714,8 +4718,8 @@ export interface GuildAuditLogsEntryTargetField, -> extends Omit, 'channel'> { + > extends Omit, 'channel'> { channel?: GuildVoiceChannelResolvable | null; status?: T | number; } @@ -4918,14 +4922,14 @@ export type GuildScheduledEventEntityType = keyof typeof GuildScheduledEventEnti export type GuildScheduledEventManagerFetchResult< T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, -> = T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions + > = T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions ? GuildScheduledEvent : Collection; export type GuildScheduledEventManagerFetchSubscribersResult = T extends { withMember: true } - ? Collection> - : Collection>; + ? Collection> + : Collection>; export type GuildScheduledEventPrivacyLevel = keyof typeof GuildScheduledEventPrivacyLevels; @@ -5475,24 +5479,24 @@ export type Partialize< N extends keyof T | null = null, M extends keyof T | null = null, E extends keyof T | '' = '', -> = { - readonly client: Client; - id: Snowflake; - partial: true; -} & { - [K in keyof Omit]: K extends N ? null : K extends M ? T[K] | null : T[K]; -}; + > = { + readonly client: Client; + id: Snowflake; + partial: true; + } & { + [K in keyof Omit]: K extends N ? null : K extends M ? T[K] | null : T[K]; + }; export interface PartialDMChannel extends Partialize { lastMessageId: undefined; } -export interface PartialGuildMember extends Partialize {} +export interface PartialGuildMember extends Partialize { } export interface PartialMessage - extends Partialize {} + extends Partialize { } -export interface PartialMessageReaction extends Partialize {} +export interface PartialMessageReaction extends Partialize { } export interface PartialOverwriteData { id: Snowflake | number; @@ -5507,7 +5511,7 @@ export interface PartialRoleData extends RoleData { export type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION' | 'GUILD_SCHEDULED_EVENT'; -export interface PartialUser extends Partialize {} +export interface PartialUser extends Partialize { } export type PresenceStatusData = ClientPresenceStatus | 'invisible'; @@ -5691,8 +5695,8 @@ export interface SweeperDefinitions { export type SweeperOptions = { [K in keyof SweeperDefinitions]?: SweeperDefinitions[K][2] extends true - ? SweepOptions | LifetimeSweepOptions - : SweepOptions; + ? SweepOptions | LifetimeSweepOptions + : SweepOptions; }; export interface LimitedCollectionOptions {