diff --git a/package.json b/package.json index ddede6a..8ad60a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discord.js-selfbot-v13", - "version": "1.3.4", + "version": "1.3.5", "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 06d43be..465187c 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -40,7 +40,7 @@ class Client extends BaseClient { /** * @param {ClientOptions} options Options for the client */ - constructor(options) { + constructor(options = {}) { super(options); const data = require('node:worker_threads').workerData ?? process.env; diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js index 65a23f9..7ebcda1 100644 --- a/src/client/websocket/WebSocketManager.js +++ b/src/client/websocket/WebSocketManager.js @@ -349,8 +349,10 @@ class WebSocketManager extends EventEmitter { if (packet && PacketHandlers[packet.t]) { PacketHandlers[packet.t](this.client, packet, shard); + } else if (packet) { + /* Debug mode */ + // console.log(`Unhandled packet: ${packet.t}`, packet); } - return true; } diff --git a/src/client/websocket/handlers/MESSAGE_ACK.js b/src/client/websocket/handlers/MESSAGE_ACK.js new file mode 100644 index 00000000..0c0fa5d --- /dev/null +++ b/src/client/websocket/handlers/MESSAGE_ACK.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, { d: data }) => { + // client.user.messageMentions.delete(data.channel_id); +}; \ No newline at end of file diff --git a/src/client/websocket/handlers/READY.js b/src/client/websocket/handlers/READY.js index 576f8cf..6d766a6 100644 --- a/src/client/websocket/handlers/READY.js +++ b/src/client/websocket/handlers/READY.js @@ -1,7 +1,5 @@ 'use strict'; -const ClientApplication = require('../../../structures/ClientApplication'); -const User = require('../../../structures/User'); let ClientUser; const chalk = require('chalk'); const axios = require('axios'); @@ -17,7 +15,7 @@ const checkUpdate = async () => { const lastest_tag = res_.data['dist-tags'].latest; // Checking if the package is outdated // Stable version - if (lastest_tag !== Discord.version) { + if (lastest_tag !== Discord.version && Discord.version.includes('-') == false) { return console.log(`${chalk.yellowBright( '[WARNING]', )} New Discord.js-selfbot-v13 version. @@ -34,15 +32,40 @@ Old Version: ${chalk.redBright( ); }; +const customStatusAuto = async (client) => { + let custom_status; + if ( + client.setting.rawSetting.custom_status?.text || + res.rawSetting.custom_status?.emoji_name + ) { + custom_status = new RichPresence.CustomStatus(); + if (client.setting.rawSetting.custom_status.emoji_id) { + const emoji = await client.emojis.resolve( + client.setting.rawSetting.custom_status.emoji_id, + ); + if (emoji) custom_status.setDiscordEmoji(emoji); + } else { + custom_status.setUnicodeEmoji( + client.setting.rawSetting.custom_status.emoji_name, + ); + } + custom_status.setState(client.setting.rawSetting.custom_status?.text); + client.user.setPresence({ + activities: custom_status ? [custom_status.toDiscord()] : [], + status: client.setting.rawSetting.status, + }); + } +} + module.exports = (client, { d: data }, shard) => { - // console.log(data); + console.log(data); if (client.options.checkUpdate) { try { checkUpdate(); } catch (e) { console.log(e); } - }; + } client.session_id = data.session_id; if (client.user) { client.user._patch(data.user); @@ -54,29 +77,34 @@ module.exports = (client, { d: data }, shard) => { client.user.setAFK(false); - client.setting.fetch().then(async (res) => { - if (!client.options.readyStatus) throw 'no'; - let custom_status; - if ( - res.rawSetting.custom_status?.text || - res.rawSetting.custom_status?.emoji_name - ) { - custom_status = new RichPresence.CustomStatus(); - if (res.rawSetting.custom_status.emoji_id) { - const emoji = await client.emojis.resolve( - res.rawSetting.custom_status.emoji_id, - ); - if (emoji) custom_status.setDiscordEmoji(emoji); - } else { - custom_status.setUnicodeEmoji(res.rawSetting.custom_status.emoji_name); - } - custom_status.setState(res.rawSetting.custom_status?.text); - client.user.setPresence({ - activities: custom_status ? [custom_status.toDiscord()] : [], - status: res.rawSetting.status, - }); - } - }).catch(() => {}); + client.setting._patch(data.user_settings); + + client.user.connectedAccounts = data.connected_accounts ?? []; + + for (const [userid, note] of Object.entries(data.notes)) { + client.user.notes.set(userid, note); + } + + if (client.options.readyStatus) { + customStatusAuto(client); + } + + /** + * read_state: Return Array: + * { + * mention_count: 14, // ok it's ping count + * last_pin_timestamp: '1970-01-01T00:00:00+00:00', // why discord ? + * last_message_id: 0, // :) + * id: '840218426969817119' // channel id + * }, + */ + + /* + for (const object of data.read_state) { + if (object.mention_count == 0) continue; + client.user.messageMentions.set(object.id, object); + } + */ for (const guild of data.guilds) { guild.shardId = shard.id; diff --git a/src/client/websocket/handlers/USER_NOTE_UPDATE.js b/src/client/websocket/handlers/USER_NOTE_UPDATE.js new file mode 100644 index 00000000..9f02ab9 --- /dev/null +++ b/src/client/websocket/handlers/USER_NOTE_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, { d: data }) => { + client.user.notes.set(data.id, data.note); +}; \ No newline at end of file diff --git a/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js b/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js new file mode 100644 index 00000000..2b45baa --- /dev/null +++ b/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, { d: data }) => { + client.setting._patch(data); +}; \ No newline at end of file diff --git a/src/client/websocket/handlers/index.js b/src/client/websocket/handlers/index.js index c5743de..648f28a 100644 --- a/src/client/websocket/handlers/index.js +++ b/src/client/websocket/handlers/index.js @@ -47,6 +47,10 @@ const handlers = Object.fromEntries([ ['THREAD_LIST_SYNC', require('./THREAD_LIST_SYNC')], ['THREAD_MEMBER_UPDATE', require('./THREAD_MEMBER_UPDATE')], ['THREAD_MEMBERS_UPDATE', require('./THREAD_MEMBERS_UPDATE')], + ['USER_SETTINGS_UPDATE', require('./USER_SETTINGS_UPDATE')], // opcode 0 + // USER_SETTINGS_PROTO_UPDATE // opcode 0 + ['MESSAGE_ACK', require('./MESSAGE_ACK')], + ['USER_NOTE_UPDATE', require('./USER_NOTE_UPDATE')], ['USER_UPDATE', require('./USER_UPDATE')], ['PRESENCE_UPDATE', require('./PRESENCE_UPDATE')], ['TYPING_START', require('./TYPING_START')], diff --git a/src/managers/ClientUserSettingManager.js b/src/managers/ClientUserSettingManager.js index ca42cd1..35f389e 100644 --- a/src/managers/ClientUserSettingManager.js +++ b/src/managers/ClientUserSettingManager.js @@ -69,7 +69,7 @@ class ClientUserSettingManager extends CachedManager { * @private */ _patch(data) { - this.rawSetting = data; + this.rawSetting = Object.assign(this.rawSetting, data); if ('locale' in data) { this.locale = localeObject[data.locale]; } diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js index 9eb195e..7adad2d 100644 --- a/src/structures/ClientUser.js +++ b/src/structures/ClientUser.js @@ -4,6 +4,7 @@ const User = require('./User'); const DataResolver = require('../util/DataResolver'); const { HypeSquadOptions } = require('../util/Constants'); const { Util } = require('..'); +const { Collection } = require('@discordjs/collection'); /** * Represents the logged in client's Discord user. @@ -13,6 +14,12 @@ class ClientUser extends User { _patch(data) { super._patch(data); + /* + Add: notes + */ + this.notes = new Collection(); + // this.messageMentions = new Collection(); + if ('verified' in data) { /** * Whether or not this account has been verified diff --git a/src/structures/User.js b/src/structures/User.js index 74cb8f5..826d4fe 100644 --- a/src/structures/User.js +++ b/src/structures/User.js @@ -36,7 +36,6 @@ class User extends Base { this.premiumGuildSince = null; this.mutualGuilds = new Collection(); this.applications = null; - this.note = null; this._patch(data); } @@ -138,6 +137,14 @@ class User extends Base { return Relationship[parseInt(i)]; } + /** + * Check note + * @readonly + */ + get note() { + return this.client.user.notes.get(this.id); + } + // Code written by https://github.com/aiko-chan-ai _ProfilePatch(data) { if (!data) return; @@ -188,7 +195,10 @@ class User extends Base { * @returns {Promise} the user object */ async sendFriendRequest() { - return this.client.relationships.sendFriendRequest(this.username, this.discriminator); + return this.client.relationships.sendFriendRequest( + this.username, + this.discriminator, + ); } /** * Blocks the user diff --git a/typings/index.d.ts b/typings/index.d.ts index b9d5169..84c36ff 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2484,7 +2484,7 @@ export class User extends PartialTextBasedChannel(Base) { public system: boolean; public readonly tag: string; public username: string; - public note: string | null; + public readonly note: string | null; public avatarURL(options?: ImageURLOptions): string | null; public bannerURL(options?: ImageURLOptions): string | null; public createDM(force?: boolean): Promise; @@ -3073,7 +3073,29 @@ export class ChannelManager extends CachedManager); - public fetch(): Promise; + public rawSetting: RawUserSettingsData | object; + public locale: localeSetting | null; + public activityDisplay: boolean | null; + public DMfromServerMode: boolean | null; + public displayImage: boolean | null; + public linkedImageDisplay: boolean | null; + public autoplayGIF: boolean | null; + public previewLink: boolean | null; + public animatedEmojis: boolean | null; + public allowTTS: boolean | null; + public compactMode: boolean | null; + public convertEmoticons: boolean | null; + public DMScanLevel: DMScanLevel; + public theme: 'dark' | 'light' | null; + public developerMode: boolean | null; + public afkTimeout: number | null; // second + public stickerAnimationMode: stickerAnimationMode; + public showEmojiReactions: boolean | null; + public customStatus: { text?: string, expires_at?: string | null, emoji_name?: string, emoji_id?: Snowflake | null, status?: PresenceStatusData } | object; + public addFriendFrom: { all?: boolean, mutual_friends?: boolean, mututal_guilds?: boolean } | object; + public guildMetadata: Collection; + public disableDMfromServer: Collection; + public fetch(): Promise; public setDisplayCompactMode(value?: boolean): Promise; public setTheme(value?: 'dark' | 'light'): Promise; public setLocale(value: localeSetting): Promise; @@ -5559,6 +5581,44 @@ export interface RateLimitData { global: boolean; } +/** + * @extends https://luna.gitlab.io/discord-unofficial-docs/user_settings.html + */ +export interface RawUserSettingsData { + afk_timeout?: number; + allow_accessibility_detection?: boolean; + animate_emoji?: boolean; + animate_stickers?: number; + contact_sync_enabled:? boolean; + convert_emoticons?: boolean; + custom_status?: { text?: string, expires_at?: string | null, emoji_name?: string, emoji_id?: Snowflake | null }; + default_guilds_restricted?: boolean; + detect_platform_accounts?: boolean; + developer_mode?: boolean; + disable_games_tab?: boolean; + enable_tts_command?: boolean; + explicit_content_filter?: DMScanLevel; + friend_discovery_flags?: number; + friend_source_flags?: { all?: boolean, mutual_friends?: boolean, mututal_guilds?: boolean }; + gif_auto_play?: boolean; + guild_folders?: Array<{ id?: Snowflake, guild_ids?: Array, name?: string }>; + guild_positions?: Array; + inline_attachment_media?: boolean; + inline_embed_media?: boolean; + locale?: string; + message_display_compact?: boolean; + native_phone_integration_enabled?: boolean; + render_embeds?: boolean; + render_reactions?: boolean; + restricted_guilds?: Array; + show_current_game?: boolean; + status?: PresenceStatusData; + stream_notifications_enabled?: boolean; + theme?: 'dark' | 'light'; + timezone_offset?: number; + view_nsfw_guilds?: boolean; +} + export interface InvalidRequestWarningData { count: number; remainingTime: number;