diff --git a/esm.mjs b/esm.mjs index 934fe954c..7619931c0 100644 --- a/esm.mjs +++ b/esm.mjs @@ -9,7 +9,6 @@ export const { AutocompleteInteraction, Base, Bucket, - Call, CategoryChannel, Channel, Client, @@ -45,7 +44,6 @@ export const { PrivateChannel, PrivateThreadChannel, PublicThreadChannel, - Relationship, RequestHandler, Role, SequentialBucket, diff --git a/index.d.ts b/index.d.ts index 911cb8d33..c35e9c26c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -165,17 +165,13 @@ declare namespace Eris { // Permission type PermissionType = Constants["PermissionOverwriteTypes"][keyof Constants["PermissionOverwriteTypes"]]; - // Presence/Relationship + // Presence type ActivityFlags = Constants["ActivityFlags"][keyof Constants["ActivityFlags"]]; type ActivityType = Constants["ActivityTypes"][keyof Constants["ActivityTypes"]]; - type FriendSuggestionReasons = { name: string; platform_type: string; type: number }[]; type SelfStatus = Status | "invisible"; type Status = "online" | "idle" | "dnd"; type UserStatus = Status | "offline"; - // Selfbot - type ConnectionVisibilityTypes = Constants["ConnectionVisibilityTypes"][keyof Constants["ConnectionVisibilityTypes"]]; - // Sticker type StickerFormats = Constants["StickerFormats"][keyof Constants["StickerFormats"]]; type StickerTypes = Constants["StickerTypes"][keyof Constants["StickerTypes"]]; @@ -874,23 +870,15 @@ declare namespace Eris { autoModerationRuleCreate: [guild: Guild, rule: AutoModerationRule]; autoModerationRuleDelete: [guild: Guild, rule: AutoModerationRule]; autoModerationRuleUpdate: [guild: Guild, rule: AutoModerationRule | null, newRule: AutoModerationRule]; - callCreate: [call: Call]; - callDelete: [call: Call]; - callRing: [call: Call]; - callUpdate: [call: Call, oldCall: OldCall]; channelCreate: [channel: AnyGuildChannel]; - channelDelete: [channel: AnyChannel]; + channelDelete: [channel: Exclude]; channelPinUpdate: [channel: TextableChannel, timestamp: number, oldTimestamp: number]; - channelRecipientAdd: [channel: GroupChannel, user: User]; - channelRecipientRemove: [channel: GroupChannel, user: User]; channelUpdate: [channel: AnyGuildChannel, oldChannel: OldGuildChannel | OldForumChannel | OldGuildTextChannel | OldVoiceChannel] | [channel: GroupChannel, oldChannel: OldGroupChannel]; connect: [id: number]; debug: [message: string, id?: number]; disconnect: []; error: [err: Error, id?: number]; - friendSuggestionCreate: [user: User, reasons: FriendSuggestionReasons]; - friendSuggestionDelete: [user: User]; guildAuditLogEntryCreate: [guildAuditLogEntry: GuildAuditLogEntry]; guildAvailable: [guild: Guild]; guildBanAdd: [guild: Guild, user: User]; @@ -898,6 +886,7 @@ declare namespace Eris { guildCreate: [guild: Guild]; guildDelete: [guild: PossiblyUncachedGuild]; guildEmojisUpdate: [guild: PossiblyUncachedGuild, emojis: Emoji[], oldEmojis: Emoji[] | null]; + guildIntegrationsUpdate: [guild: PossiblyUncachedGuild]; guildMemberAdd: [guild: Guild, member: Member]; guildMemberChunk: [guild: Guild, member: Member[]]; guildMemberRemove: [guild: Guild, member: Member | MemberPartial]; @@ -927,13 +916,10 @@ declare namespace Eris { messageReactionRemoveAll: [message: PossiblyUncachedMessage]; messageReactionRemoveEmoji: [message: PossiblyUncachedMessage, emoji: PartialEmoji]; messageUpdate: [message: Message, oldMessage: OldMessage | null]; - presenceUpdate: [other: Member | Relationship, oldPresence: Presence | null]; + presenceUpdate: [other: Member, oldPresence: Presence | null]; rawREST: [request: RawRESTRequest]; rawWS: [packet: RawPacket, id: number]; ready: []; - relationshipAdd: [relationship: Relationship]; - relationshipRemove: [relationship: Relationship]; - relationshipUpdate: [relationship: Relationship, oldRelationship: { type: number }]; shardPreReady: [id: number]; stageInstanceCreate: [stageInstance: StageInstance]; stageInstanceDelete: [stageInstance: StageInstance]; @@ -2080,10 +2066,6 @@ declare namespace Eris { SELECT_MENU: 3; TEXT_INPUT: 4; }; - ConnectionVisibilityTypes: { - NONE: 0; - EVERYONE: 1; - }; ForumLayoutTypes: { NOT_SET: 0; LIST_VIEW: 1; @@ -2121,8 +2103,6 @@ declare namespace Eris { INVALID_SESSION: 9; HELLO: 10; HEARTBEAT_ACK: 11; - SYNC_GUILD: 12; - SYNC_CALL: 13; }; GuildFeatures: [ "ANIMATED_BANNER", @@ -2639,80 +2619,6 @@ declare namespace Eris { user: PartialUser; } - // Selfbot - interface Connection { - friend_sync: boolean; - id: string; - integrations: unknown[]; // TODO ???? - name: string; - revoked: boolean; - type: string; - verified: boolean; - visibility: ConnectionVisibilityTypes; - } - interface GuildSettings { - channel_override: { - channel_id: string; - message_notifications: number; - muted: boolean; - }[]; - guild_id: string; - message_notifications: number; - mobile_push: boolean; - muted: boolean; - suppress_everyone: boolean; - } - interface SearchOptions { - attachmentExtensions?: string; - attachmentFilename?: string; - authorID?: string; - channelIDs?: string[]; - content?: string; - contextSize?: number; - embedProviders?: string; - embedTypes?: string; - has?: string; - limit?: number; - maxID?: string; - minID?: string; - offset?: number; - sortBy?: string; - sortOrder?: string; - } - interface SearchResults { - results: (Message & { hit?: boolean })[][]; - totalResults: number; - } - interface UserProfile { - connected_accounts: { id: string; name: string; type: string; verified: boolean }[]; - mutual_guilds: { id: string; nick?: string }[]; - premium_since?: number; - user: PartialUser & { flags: number }; - } - interface UserSettings { - afk_timeout: number; - convert_emojis: boolean; - default_guilds_restricted: boolean; - detect_platform_accounts: boolean; - developer_mode: boolean; - enable_tts_command: boolean; - explicit_content_filter: number; - friend_source_flags: { - all: boolean; // not sure about other keys, abal heeeelp - }; - inline_attachment_media: boolean; - inline_embed_media: boolean; - guild_positions: string[]; - locale: LocaleStrings; - message_display_compact: boolean; - render_embeds: boolean; - render_reactions: boolean; - restricted_guilds: string[]; - show_current_game: boolean; - status: string; - theme: string; - } - // Classes /** Generic T is `true` if a Guild scoped command, and `false` if not */ export class ApplicationCommand extends Base { @@ -2777,19 +2683,6 @@ declare namespace Eris { queue(func: () => void, priority?: boolean): void; } - export class Call extends Base { - channel: GroupChannel; - createdAt: number; - endedTimestamp: number | null; - id: string; - participants: string[]; - region: string | null; - ringing: string[]; - unavailable: boolean; - voiceStates: Collection; - constructor(data: BaseData, channel: GroupChannel); - } - export class CategoryChannel extends GuildChannel implements Permissionable { channels: Collection>; permissionOverwrites: Collection; @@ -2814,19 +2707,16 @@ declare namespace Eris { dmChannelMap: { [s: string]: string }; dmChannels: Collection; gatewayURL?: string; - groupChannels: Collection; guilds: Collection; guildShardMap: { [s: string]: number }; lastConnect: number; lastReconnectDelay: number; - notes: { [s: string]: string }; options: ClientOptions; presence: ClientPresence; privateChannelMap: { [s: string]: string }; privateChannels: Collection; ready: boolean; reconnectAttempts: number; - relationships: Collection; requestHandler: RequestHandler; shards: ShardManager; startTime: number; @@ -2834,21 +2724,14 @@ declare namespace Eris { unavailableGuilds: Collection; uptime: number; user: ExtendedUser; - userGuildSettings: { [s: string]: GuildSettings }; users: Collection; - userSettings: UserSettings; voiceConnections: VoiceConnectionManager; constructor(token: string, options?: ClientOptions); - acceptInvite(inviteID: string): Promise>; addGroupRecipient(groupID: string, userID: string): Promise; addGuildDiscoverySubcategory(guildID: string, categoryID: string, reason?: string): Promise; addGuildMember(guildID: string, userID: string, accessToken: string, options?: AddGuildMemberOptions): Promise; addGuildMemberRole(guildID: string, memberID: string, roleID: string, reason?: string): Promise; addMessageReaction(channelID: string, messageID: string, reaction: string): Promise; - /** @deprecated */ - addMessageReaction(channelID: string, messageID: string, reaction: string, userID: string): Promise; - addRelationship(userID: string, block?: boolean): Promise; - addSelfPremiumSubscription(token: string, plan: string): Promise; banGuildMember(guildID: string, userID: string, options?: BanMemberOptions): Promise; /** @deprecated */ banGuildMember(guildID: string, userID: string, deleteMessageDays?: number, reason?: string): Promise; @@ -2906,13 +2789,9 @@ declare namespace Eris { deleteMessage(channelID: string, messageID: string, reason?: string): Promise; deleteMessages(channelID: string, messageIDs: string[], reason?: string): Promise; deleteRole(guildID: string, roleID: string, reason?: string): Promise; - deleteSelfConnection(platform: string, id: string): Promise; - deleteSelfPremiumSubscription(): Promise; deleteStageInstance(channelID: string): Promise; - deleteUserNote(userID: string): Promise; deleteWebhook(webhookID: string, token?: string, reason?: string): Promise; deleteWebhookMessage(webhookID: string, token: string, messageID: string): Promise; - disableSelfMFATOTP(code: string): Promise<{ token: string }>; disconnect(options: { reconnect?: boolean | "auto" }): void; editAFK(afk: boolean): void; editAutoModerationRule(guildID: string, ruleID: string, options: EditAutoModerationRuleOptions): Promise; @@ -2942,7 +2821,6 @@ declare namespace Eris { options: { name?: string; roles?: string[] }, reason?: string ): Promise; - editGuildIntegration(guildID: string, integrationID: string, options: IntegrationOptions): Promise; editGuildMember(guildID: string, memberID: string, options: MemberOptions, reason?: string): Promise; editGuildMFALevel(guildID: string, level: MFALevel, reason?: string): Promise; editGuildOnboarding(guildID: string, options: GuildOnboardingOptions, reason?: string): Promise; @@ -2960,16 +2838,9 @@ declare namespace Eris { editRoleConnectionMetadataRecords(data: ApplicationRoleConnectionMetadata[]): Promise; editRolePosition(guildID: string, roleID: string, position: number): Promise; editSelf(options: { avatar?: string; username?: string }): Promise; - editSelfConnection( - platform: string, - id: string, - data: { friendSync: boolean; visibility: number } - ): Promise; - editSelfSettings(data: UserSettings): Promise; editStageInstance(channelID: string, options: StageInstanceOptions): Promise; editStatus(status: SelfStatus, activities?: ActivityPartial[] | ActivityPartial): void; editStatus(activities?: ActivityPartial[] | ActivityPartial): void; - editUserNote(userID: string, note: string): Promise; editWebhook( webhookID: string, options: WebhookEditOptions, @@ -2984,10 +2855,6 @@ declare namespace Eris { ): Promise>; emit(event: K, ...args: ClientEvents[K]): boolean; emit(event: string, ...args: any[]): boolean; - enableSelfMFATOTP( - secret: string, - code: string - ): Promise<{ backup_codes: { code: string; consumed: boolean }[]; token: string }>; endPoll(channelID: string, messageID: string): Promise>; executeSlackWebhook(webhookID: string, token: string, options: Record & { auth?: boolean; threadID?: string }): Promise; executeSlackWebhook(webhookID: string, token: string, options: Record & { auth?: boolean; threadID?: string; wait: true }): Promise>; @@ -3000,7 +2867,7 @@ declare namespace Eris { getAutoModerationRule(guildID: string, ruleID: string): Promise; getAutoModerationRules(guildID: string): Promise; getBotGateway(): Promise<{ session_start_limit: { max_concurrency: number; remaining: number; reset_after: number; total: number }; shards: number; url: string }>; - getChannel(channelID: string): AnyChannel; + getChannel(channelID: string): Exclude; getChannelInvites(channelID: string): Promise; getChannelWebhooks(channelID: string): Promise; getCommand(commandID: string): Promise>; @@ -3046,7 +2913,7 @@ declare namespace Eris { /** @deprecated */ getMessages(channelID: string, limit?: number, before?: string, after?: string, around?: string): Promise; getNitroStickerPacks(): Promise<{ sticker_packs: StickerPack[] }>; - getOAuthApplication(appID?: string): Promise; + getOAuthApplication(): Promise; getPins(channelID: string): Promise; getPollAnswerVoters(channelID: string, messageID: string, answerID: string, options?: GetPollAnswerVotersOptions): Promise; getPruneCount(guildID: string, options?: GetPruneOptions): Promise; @@ -3070,44 +2937,9 @@ declare namespace Eris { getRESTUser(userID: string): Promise; getRoleConnectionMetadataRecords(): Promise; getSelf(): Promise; - getSelfBilling(): Promise<{ - payment_gateway?: string; - payment_source?: { - brand: string; - expires_month: number; - expires_year: number; - invalid: boolean; - last_4: number; - type: string; - }; - premium_subscription?: { - canceled_at?: string; - created_at: string; - current_period_end?: string; - current_period_start?: string; - ended_at?: string; - plan: string; - status: number; - }; - }>; - getSelfConnections(): Promise; - getSelfMFACodes( - password: string, - regenerate?: boolean - ): Promise<{ backup_codes: { code: string; consumed: boolean }[] }>; - getSelfPayments(): Promise<{ - amount: number; - amount_refunded: number; - created_at: string; // date - currency: string; - description: string; - status: number; - }[]>; - getSelfSettings(): Promise; getStageInstance(channelID: string): Promise; getThreadMember(channelID: string, userID: string, withMember?: boolean): Promise; getThreadMembers(channelID: string, options?: GetThreadMembersOptions): Promise; - getUserProfile(userID: string): Promise; getVoiceRegions(guildID?: string): Promise; getWebhook(webhookID: string, token?: string): Promise; getWebhookMessage(webhookID: string, token: string, messageID: string): Promise>; @@ -3138,10 +2970,7 @@ declare namespace Eris { removeMessageReaction(channelID: string, messageID: string, reaction: string, userID?: string): Promise; removeMessageReactionEmoji(channelID: string, messageID: string, reaction: string): Promise; removeMessageReactions(channelID: string, messageID: string): Promise; - removeRelationship(userID: string): Promise; - searchChannelMessages(channelID: string, query: SearchOptions): Promise; searchGuildMembers(guildID: string, query: string, limit?: number): Promise; - searchGuildMessages(guildID: string, query: SearchOptions): Promise; sendChannelTyping(channelID: string): Promise; setVoiceChannelStatus(channelID: string, status: string, reason?: string): Promise; syncGuildIntegration(guildID: string, integrationID: string): Promise; @@ -3261,7 +3090,7 @@ declare namespace Eris { recipients: Collection; type: Constants["ChannelTypes"]["DM"]; constructor(data: BaseData, client: Client); - addMessageReaction(messageID: string, reaction: string, userID?: string): Promise; + addMessageReaction(messageID: string, reaction: string): Promise; createMessage(content: MessageContent, file?: FileContent | FileContent[]): Promise>; delete(): Promise; deleteMessage(messageID: string): Promise; @@ -3415,7 +3244,6 @@ declare namespace Eris { editCommandPermissions(permissions: ApplicationCommandPermissions[], reason?: string): Promise; editDiscovery(options?: DiscoveryOptions): Promise; editEmoji(emojiID: string, options: { name: string; roles?: string[] }, reason?: string): Promise; - editIntegration(integrationID: string, options: IntegrationOptions): Promise; editMember(memberID: string, options: MemberOptions, reason?: string): Promise; editMFALevel(level: MFALevel, reason?: string): Promise; /** @deprecated */ @@ -3477,7 +3305,6 @@ declare namespace Eris { pruneMembers(options?: PruneMemberOptions): Promise; removeMemberRole(memberID: string, roleID: string, reason?: string): Promise; searchMembers(query: string, limit?: number): Promise; - syncIntegration(integrationID: string): Promise; syncTemplate(code: string): Promise; unbanMember(userID: string, reason?: string): Promise; } @@ -3533,8 +3360,6 @@ declare namespace Eris { user?: User; constructor(data: BaseData, guild: Guild); delete(): Promise; - edit(options: IntegrationOptions): Promise; - sync(): Promise; } export class GuildPreview extends Base { @@ -3601,11 +3426,9 @@ declare namespace Eris { lastMessageID: string | null; messages: Collection>; rateLimitPerUser: number; - types: GuildTextChannelTypes | GuildVoiceChannelTypes | GuildThreadChannelTypes; + type: GuildTextChannelTypes | GuildVoiceChannelTypes | GuildThreadChannelTypes; constructor(data: BaseData, client: Client, messageLimit?: number); addMessageReaction(messageID: string, reaction: string): Promise; - /** @deprecated */ - addMessageReaction(messageID: string, reaction: string, userID?: string): Promise; createMessage(content: MessageContent, file?: FileContent | FileContent[]): Promise>; deleteMessage(messageID: string, reason?: string): Promise; deleteMessages(messageIDs: string[], reason?: string): Promise; @@ -3865,8 +3688,6 @@ declare namespace Eris { webhookID: T extends GuildTextableWithThreads ? string | undefined : undefined; constructor(data: BaseData, client: Client); addReaction(reaction: string): Promise; - /** @deprecated */ - addReaction(reaction: string, userID: string): Promise; createThreadWithMessage(options: CreateThreadOptions): Promise; crosspost(): Promise : never>; delete(reason?: string): Promise; @@ -3959,16 +3780,6 @@ declare namespace Eris { type: GuildPublicThreadChannelTypes; } - export class Relationship extends Base implements Omit { - activities: Activity[] | null; - clientStatus?: ClientStatus; - id: string; - status: Status; - type: number; - user: User; - constructor(data: BaseData, client: Client); - } - export class RequestHandler implements SimpleJSON { globalBlock: boolean; latencyRef: LatencyRef; @@ -4032,8 +3843,6 @@ declare namespace Eris { getAllUsersQueue: string; globalBucket: Bucket; guildCreateTimeout: NodeJS.Timeout | null; - guildSyncQueue: string[]; - guildSyncQueueLength: number; heartbeatInterval: NodeJS.Timeout | null; id: number; lastHeartbeatAck: boolean; @@ -4050,7 +3859,6 @@ declare namespace Eris { seq: number; sessionID: string | null; status: "connecting" | "disconnected" | "handshaking" | "identifying" | "ready" | "resuming"; - unsyncedGuilds: number; ws: WebSocket | BrowserWebSocket | null; constructor(id: number, client: Client); checkReady(): void; @@ -4075,13 +3883,11 @@ declare namespace Eris { once(event: string, listener: (...args: any[]) => void): this; onPacket(packet: RawPacket): void; requestGuildMembers(guildID: string, options?: RequestGuildMembersOptions): Promise; - requestGuildSync(guildID: string): void; reset(): void; restartGuildCreateTimeout(): void; resume(): void; sendStatusUpdate(): void; sendWS(op: number, _data: Record, priority?: boolean): void; - syncGuild(guildID: string): void; wsEvent(packet: Required): void; on(event: K, listener: (...args: ShardEvents[K]) => void): this; on(event: string, listener: (...args: any[]) => void): this; @@ -4236,55 +4042,31 @@ declare namespace Eris { system: boolean; username: string; constructor(data: BaseData, client: Client); - addRelationship(block?: boolean): Promise; - deleteNote(): Promise; dynamicAvatarURL(format?: ImageFormat, size?: number): string; dynamicBannerURL(format?: ImageFormat, size?: number): string | null; - editNote(note: string): Promise; getDMChannel(): Promise; - getProfile(): Promise; - removeRelationship(): Promise; } export class VoiceChannel extends GuildTextableChannel implements Invitable, Permissionable { bitrate: number; - lastMessageID: string | null; - messages: Collection>; nsfw: boolean; permissionOverwrites: Collection; position: number; - rateLimitPerUser: number; rtcRegion: string | null; status?: string; type: GuildVoiceChannelTypes; userLimit: number; videoQualityMode: VideoQualityMode; voiceMembers: Collection; - addMessageReaction(messageID: string, reaction: string): Promise; - addMessageReaction(messageID: string, reaction: string, userID: string): Promise; createInvite(options?: CreateInviteOptions, reason?: string): Promise>; - createMessage(content: MessageContent, file?: FileContent | FileContent[] | undefined): Promise>; createWebhook(options: WebhookCreateOptions, reason?: string | undefined): Promise; - deleteMessage(messageID: string, reason?: string | undefined): Promise; deletePermission(overwriteID: string, reason?: string): Promise; - edit(options: EditVoiceChannelOptions, reason?: string): Promise; - editMessage(messageID: string, content: MessageContentEdit): Promise>; editPermission(overwriteID: string, allow: PermissionValueTypes, deny: PermissionValueTypes, type: PermissionType, reason?: string): Promise; getInvites(): Promise[]>; - getMessage(messageID: string): Promise>; - getMessageReaction(messageID: string, reaction: string, options?: GetMessageReactionOptions | undefined): Promise; - getMessageReaction(messageID: string, reaction: string, limit?: number | undefined, before?: string | undefined, after?: string | undefined): Promise; - getMessages(options?: GetMessagesOptions | undefined): Promise[]>; - getMessages(limit?: number | undefined, before?: string | undefined, after?: string | undefined, around?: string | undefined): Promise[]>; getWebhooks(): Promise; join(options?: JoinVoiceChannelOptions): Promise; leave(): void; - removeMessageReaction(messageID: string, reaction: string, userID?: string | undefined): Promise; - removeMessageReactionEmoji(messageID: string, reaction: string): Promise; - removeMessageReactions(messageID: string): Promise; - sendTyping(): Promise; setStatus(status: string, reason?: string): Promise; - unsendMessage(messageID: string): Promise; } export class VoiceConnection extends EventEmitter implements SimpleJSON { diff --git a/index.js b/index.js index 0e1407987..273d88acd 100644 --- a/index.js +++ b/index.js @@ -10,7 +10,6 @@ Eris.ApplicationCommand = require("./lib/structures/ApplicationCommand"); Eris.AutocompleteInteraction = require("./lib/structures/AutocompleteInteraction"); Eris.Base = require("./lib/structures/Base"); Eris.Bucket = require("./lib/util/Bucket"); -Eris.Call = require("./lib/structures/Call"); Eris.CategoryChannel = require("./lib/structures/CategoryChannel"); Eris.Channel = require("./lib/structures/Channel"); Eris.Client = Client; @@ -46,7 +45,6 @@ Eris.PingInteraction = require("./lib/structures/PingInteraction"); Eris.PrivateChannel = require("./lib/structures/PrivateChannel"); Eris.PrivateThreadChannel = require("./lib/structures/PrivateThreadChannel"); Eris.PublicThreadChannel = require("./lib/structures/PublicThreadChannel"); -Eris.Relationship = require("./lib/structures/Relationship"); Eris.RequestHandler = require("./lib/rest/RequestHandler"); Eris.Role = require("./lib/structures/Role"); Eris.SequentialBucket = require("./lib/util/SequentialBucket"); diff --git a/lib/Client.js b/lib/Client.js index 99aba6d65..acc29ecf2 100644 --- a/lib/Client.js +++ b/lib/Client.js @@ -20,7 +20,6 @@ const Member = require("./structures/Member"); const Message = require("./structures/Message"); const Permission = require("./structures/Permission"); const DMChannel = require("./structures/DMChannel"); -const Relationship = require("./structures/Relationship"); const RequestHandler = require("./rest/RequestHandler"); const Role = require("./structures/Role"); const ShardManager = require("./gateway/ShardManager"); @@ -61,12 +60,9 @@ const sleep = (ms) => new Promise((res) => setTimeout(res, ms)); * @prop {Object} dmChannelMap Object mapping user IDs to private channel IDs * @prop {Collection} dmChannels Collection of private channels the bot is in * @prop {String} gatewayURL The URL for the discord gateway - * @prop {Collection} groupChannels Collection of group channels the bot is in (user accounts only) * @prop {Collection} guilds Collection of guilds the bot is in * @prop {Object} guildShardMap Object mapping guild IDs to shard IDs - * @prop {Object} notes Object mapping user IDs to user notes (user accounts only) * @prop {Object} options Eris options - * @prop {Collection} relationships Collection of relationships the bot user has (user accounts only) * @prop {RequestHandler} requestHandler The request handler the client will use * @prop {Collection} shards Collection of shards Eris is using * @prop {Number} startTime Timestamp of bot ready event @@ -74,9 +70,7 @@ const sleep = (ms) => new Promise((res) => setTimeout(res, ms)); * @prop {Collection} unavailableGuilds Collection of unavailable guilds the bot is in * @prop {Number} uptime How long in milliseconds the bot has been up for * @prop {ExtendedUser} user The bot user - * @prop {Object} userGuildSettings Object mapping guild IDs to individual guild settings for the bot user (user accounts only) * @prop {Collection} users Collection of users the bot sees - * @prop {Object} userSettings Object containing the user account settings (user accounts only) * @prop {Collection} voiceConnections Extended collection of active VoiceConnections the bot has */ class Client extends EventEmitter { @@ -221,13 +215,11 @@ class Client extends EventEmitter { this.lastConnect = 0; this.channelGuildMap = {}; this.threadGuildMap = {}; - this.groupChannels = new Collection(GroupChannel); this.guilds = new Collection(Guild); this.dmChannelMap = {}; this.dmChannels = new Collection(DMChannel); this.guildShardMap = {}; this.unavailableGuilds = new Collection(UnavailableGuild); - this.relationships = new Collection(Relationship); this.users = new Collection(User); this.presence = { activities: null, @@ -235,9 +227,6 @@ class Client extends EventEmitter { since: null, status: "offline" }; - this.userGuildSettings = []; - this.userSettings = {}; - this.notes = {}; this.voiceConnections = new VoiceConnectionManager(); this.connect = this.connect.bind(this); @@ -259,15 +248,6 @@ class Client extends EventEmitter { return this.startTime ? Date.now() - this.startTime : 0; } - /** - * [USER ACCOUNT] Accept an invite - * @arg {String} inviteID The ID of the invite - * @returns {Promise} - */ - acceptInvite(inviteID) { - return this.requestHandler.request("POST", Endpoints.INVITE(inviteID), true).then((invite) => new Invite(invite, this)); - } - /** * Add a user to a group channel * @arg {String} groupID The ID of the target group @@ -334,45 +314,13 @@ class Client extends EventEmitter { * @arg {String} channelID The ID of the channel * @arg {String} messageID The ID of the message * @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji) - * @arg {String} [userID="@me"] The ID of the user to react as. Passing this parameter is deprecated and will not be supported in future versions. * @returns {Promise} */ - addMessageReaction(channelID, messageID, reaction, userID) { - if(userID !== undefined) { - emitDeprecation("REACTION_USER"); - this.emit("warn", "[DEPRECATED] addMessageReaction() was called without an \"@me\" `userID` argument"); - } + addMessageReaction(channelID, messageID, reaction) { if(reaction === decodeURI(reaction)) { reaction = encodeURIComponent(reaction); } - return this.requestHandler.request("PUT", Endpoints.CHANNEL_MESSAGE_REACTION_USER(channelID, messageID, reaction, userID || "@me"), true); - } - - /** - * [USER ACCOUNT] Create a relationship with a user - * @arg {String} userID The ID of the target user - * @arg {Boolean} [block=false] If true, block the user. Otherwise, add the user as a friend - * @returns {Promise} - */ - addRelationship(userID, block) { - return this.requestHandler.request("PUT", Endpoints.USER_RELATIONSHIP("@me", userID), true, { - type: block ? 2 : undefined - }); - } - - /** - * [USER ACCOUNT] Purchase a premium subscription (Nitro) for the current user - * You must get a Stripe card token from the Stripe API for this to work - * @arg {String} token The Stripe credit card token - * @arg {String} plan The plan to purchase, either "premium_month" or "premium_year" - * @returns {Promise} - */ - addSelfPremiumSubscription(token, plan) { - return this.requestHandler.request("PUT", Endpoints.USER_BILLING_PREMIUM_SUBSCRIPTION("@me"), true, { - token: token, - payment_gateway: "stripe", - plan: plan - }); + return this.requestHandler.request("PUT", Endpoints.CHANNEL_MESSAGE_REACTION_USER(channelID, messageID, reaction, "@me"), true); } /** @@ -493,7 +441,7 @@ class Client extends EventEmitter { self_mute: false, self_deaf: false }); - this.voiceConnections.leave(guildID || "call"); + this.voiceConnections.leave(guildID); } /** @@ -1206,7 +1154,7 @@ class Client extends EventEmitter { } /** - * Delete a guild channel, or leave a private or group channel + * Delete a guild channel, or leave a DM channel * @arg {String} channelID The ID of the channel * @arg {String} [reason] The reason to be displayed in audit logs * @returns {Promise} @@ -1405,24 +1353,6 @@ class Client extends EventEmitter { }); } - /** - * [USER ACCOUNT] Delete a connection for the current user - * @arg {String} platform The connection platform (e.g. "twitch", "reddit") - * @arg {String} id The connection ID - * @returns {Promise} - */ - deleteSelfConnection(platform, id) { - return this.requestHandler.request("DELETE", Endpoints.USER_CONNECTION_PLATFORM("@me", platform, id), true); - } - - /** - * [USER ACCOUNT] Cancel the premium subscription (Nitro) for the current user - * @returns {Promise} - */ - deleteSelfPremiumSubscription() { - return this.requestHandler.request("DELETE", Endpoints.USER_BILLING_PREMIUM_SUBSCRIPTION("@me"), true); - } - /** * Delete a stage instance * @arg {String} channelID The stage channel associated with the instance @@ -1432,14 +1362,6 @@ class Client extends EventEmitter { return this.requestHandler.request("DELETE", Endpoints.STAGE_INSTANCE(channelID), true); } - /** - * [USER ACCOUNT] Delete the current user's note for another user - * @returns {Promise} - */ - deleteUserNote(userID) { - return this.requestHandler.request("DELETE", Endpoints.USER_NOTE("@me", userID), true); - } - /** * Delete a webhook * @arg {String} webhookID The ID of the webhook @@ -1464,21 +1386,6 @@ class Client extends EventEmitter { return this.requestHandler.request("DELETE", Endpoints.WEBHOOK_MESSAGE(webhookID, token, messageID), false); } - /** - * [USER ACCOUNT] Disable TOTP authentication for the current user - * @arg {String} code The timed auth code for the current user - * @returns {Promise} An object containing the user's new authorization token - */ - disableSelfMFATOTP(code) { - return this.requestHandler.request("POST", Endpoints.USER_MFA_TOTP_DISABLE("@me"), true, { - code - }).then((data) => { - if(data.token) { - this._token = data.token; - } - }); - } - /** * Disconnects all shards * @arg {Object?} [options] Shard disconnect options @@ -1553,7 +1460,6 @@ class Client extends EventEmitter { * @arg {Boolean} [options.locked] The lock status of the channel (thread channels only) * @arg {String} [options.name] The name of the channel * @arg {Boolean} [options.nsfw] The nsfw status of the channel (guild channels only) - * @arg {String} [options.ownerID] The ID of the channel owner (group channels only) * @arg {String?} [options.parentID] The ID of the parent channel category for this channel (guild text/voice channels only) * @arg {Array} [options.permissionOverwrites] An array containing permission overwrite objects * @arg {Number} [options.position] The sorting position of the channel (guild channels only) @@ -1583,7 +1489,6 @@ class Client extends EventEmitter { locked: options.locked, name: options.name, nsfw: options.nsfw, - owner_id: options.ownerID, parent_id: options.parentID, position: options.position, rate_limit_per_user: options.rateLimitPerUser, @@ -1859,24 +1764,6 @@ class Client extends EventEmitter { return this.requestHandler.request("PATCH", Endpoints.GUILD_EMOJI(guildID, emojiID), true, options); } - /** - * Edit a guild integration - * @arg {String} guildID The ID of the guild - * @arg {String} integrationID The ID of the integration - * @arg {Object} options The properties to edit - * @arg {String} [options.enableEmoticons] Whether to enable integration emoticons or not - * @arg {String} [options.expireBehavior] What to do when a user's subscription runs out - * @arg {String} [options.expireGracePeriod] How long before the integration's role is removed from an unsubscribed user - * @returns {Promise} - */ - editGuildIntegration(guildID, integrationID, options) { - return this.requestHandler.request("PATCH", Endpoints.GUILD_INTEGRATION(guildID, integrationID), true, { - expire_behavior: options.expireBehavior, - expire_grace_period: options.expireGracePeriod, - enable_emoticons: options.enableEmoticons - }); - } - /** * Edit a guild member * @arg {String} guildID The ID of the guild @@ -2233,80 +2120,6 @@ class Client extends EventEmitter { return this.requestHandler.request("PATCH", Endpoints.USER("@me"), true, options).then((data) => new ExtendedUser(data, this)); } - /** - * [USER ACCOUNT] Edit a connection for the current user - * @arg {String} platform The connection platform (e.g. "twitch", "reddit") - * @arg {String} id The connection ID - * @arg {Object} data The connection data - * @arg {Boolean} [data.friendSync] Whether to sync friends from the connection or not - * @arg {Number} [data.visibility] The visibility level for the connection. 0 = hidden, 1 = shown on profile - * @returns {Promise} The updated connection data - */ - editSelfConnection(platform, id, data) { - return this.requestHandler.request("PATCH", Endpoints.USER_CONNECTION_PLATFORM("@me", platform, id), true, { - visibility: data.visibility, - friend_sync: data.friendSync - }); - } - - /** - * [USER ACCOUNT] Edit settings for the current user - * @arg {Object} data The user settings data - * @arg {Boolean} [data.convertEmoticons] Whether to convert emoticons or not (e.g. :D => 😄) - * @arg {Boolean} [data.detectPlatformAccounts] Whether to automatically detect accounts from other platforms or not (Blizzard, Skype, etc.) - * @arg {Boolean} [data.developerMode] Whether to enable developer mode or not - * @arg {Boolean} [data.enableTTSCommand] Whether to respect usage of the TTS command or not - * @arg {Object} [data.friendSourceFlags] An object representing allowed friend request sources - * @arg {Boolean} [data.friendSourceFlags.all] Whether to allow friends requests from anywhere or not - * @arg {Boolean} [data.friendSourceFlags.mutualFriends] Whether to allow friend requests from people with mutual friends or not - * @arg {Boolean} [data.friendSourceFlags.mutualGuilds] Whether to allow friend requests from people in mutual guilds or not - * @arg {Array} [data.guildPositions] An ordered array of guild IDs representing the guild list order in the Discord client - * @arg {Boolean} [data.inlineAttachmentMedia] Whether to show attachment previews or not - * @arg {Boolean} [data.inlineEmbedMedia] Whether to show embed images or not - * @arg {String} [data.locale] The locale to use for the Discord UI - * @arg {Boolean} [data.messageDisplayCompact] Whether to use compact mode or not - * @arg {Boolean} [data.renderEmbeds] Whether to show embeds or not - * @arg {Boolean} [data.renderReactions] Whether to show reactions or not - * @arg {Array} [data.restrictedGuilds] An array of guild IDs where direct messages from guild members are disallowed - * @arg {Boolean} [data.showCurrentGame] Whether to set the user's status to the current game or not - * @arg {String} [data.status] The status of the user, either "invisible", "dnd", "away", or "online" - * @arg {String} [data.theme] The theme to use for the Discord UI, either "dark" or "light" - * @returns {Promise} The user's settings data. - */ - editSelfSettings(data) { - let friendSourceFlags = undefined; - if(data.friendSourceFlags) { - friendSourceFlags = {}; - if(data.friendSourceFlags.all) { - friendSourceFlags.all = true; - } - if(data.friendSourceFlags.mutualFriends) { - friendSourceFlags.mutual_friends = true; - } - if(data.friendSourceFlags.mutualGuilds) { - friendSourceFlags.mutual_guilds = true; - } - } - return this.requestHandler.request("PATCH", Endpoints.USER_SETTINGS("@me"), true, { - convert_emoticons: data.convertEmoticons, - detect_platform_accounts: data.detectPlatformAccounts, - developer_mode: data.developerMode, - enable_tts_command: data.enableTTSCommand, - friend_source_flags: friendSourceFlags, - guild_positions: data.guildPositions, - inline_attachment_media: data.inlineAttachmentMedia, - inline_embed_media: data.inlineEmbedMedia, - locale: data.locale, - message_display_compact: data.messageDisplayCompact, - render_embeds: data.renderEmbeds, - render_reactions: data.renderReactions, - restricted_guilds: data.restrictedGuilds, - show_current_game: data.showCurrentGame, - status: data.status, - theme: data.theme - }); - } - /** * Update a stage instance * @arg {String} channelID The ID of the stage channel associated with the instance @@ -2350,18 +2163,6 @@ class Client extends EventEmitter { }); } - /** - * [USER ACCOUNT] Edit the current user's note for another user - * @arg {String} userID The ID of the target user - * @arg {String} note The note - * @returns {Promise} - */ - editUserNote(userID, note) { - return this.requestHandler.request("PUT", Endpoints.USER_NOTE("@me", userID), true, { - note - }); - } - /** * Edit a webhook * @arg {String} webhookID The ID of the webhook @@ -2439,23 +2240,6 @@ class Client extends EventEmitter { return this.requestHandler.request("PATCH", Endpoints.WEBHOOK_MESSAGE(webhookID, token, messageID), false, file ? {payload_json: options} : options, file).then((response) => new Message(response, this)); } - /** - * [USER ACCOUNT] Enable TOTP authentication for the current user - * @arg {String} secret The TOTP secret used to generate the auth code - * @arg {String} code The timed auth code for the current user - * @returns {Promise} An object containing the user's new authorization token and backup codes - */ - enableSelfMFATOTP(secret, code) { - return this.requestHandler.request("POST", Endpoints.USER_MFA_TOTP_ENABLE("@me"), true, { - secret, - code - }).then((data) => { - if(data.token) { - this._token = data.token; - } - }); - } - /** * Immediately end a poll. Note: You cannot end polls created by another user. * @arg {String} channelID The ID of the channel @@ -2639,7 +2423,7 @@ class Client extends EventEmitter { /** * Get a Channel object from a channel ID * @arg {String} channelID The ID of the channel - * @returns {CategoryChannel | DMChannel | ForumChannel | GroupChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel | TextChannel | VoiceChannel} + * @returns {CategoryChannel | DMChannel | ForumChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel | TextChannel | VoiceChannel} */ getChannel(channelID) { if(!channelID) { @@ -2652,7 +2436,7 @@ class Client extends EventEmitter { if(this.threadGuildMap[channelID] && this.guilds.get(this.threadGuildMap[channelID])) { return this.guilds.get(this.threadGuildMap[channelID]).threads.get(channelID); } - return this.dmChannels.get(channelID) || this.groupChannels.get(channelID); + return this.dmChannels.get(channelID); } /** @@ -3206,12 +2990,11 @@ class Client extends EventEmitter { } /** - * Get data on an OAuth2 application - * @arg {String} [appID="@me"] The client ID of the application to get data for (user accounts only). "@me" refers to the logged in user's own application + * Get data on the bot's OAuth2 application * @returns {Promise} The bot's application data. Refer to [the official Discord API documentation entry](https://discord.com/developers/docs/topics/oauth2#get-current-application-information) for object structure */ - getOAuthApplication(appID) { - return this.requestHandler.request("GET", Endpoints.OAUTH2_APPLICATION(appID || "@me"), true); + getOAuthApplication() { + return this.requestHandler.request("GET", Endpoints.OAUTH2_APPLICATION, true); } /** @@ -3483,51 +3266,6 @@ class Client extends EventEmitter { return this.requestHandler.request("GET", Endpoints.USER("@me"), true).then((data) => new ExtendedUser(data, this)); } - /** - * [USER ACCOUNT] Get the billing info for the current user - * @returns {Promise} The user's billing info - */ - getSelfBilling() { - return this.requestHandler.request("GET", Endpoints.USER_BILLING("@me"), true); - } - - /** - * [USER ACCOUNT] Get the connections for the current user - * @returns {Promise} The user's connections - */ - getSelfConnections() { - return this.requestHandler.request("GET", Endpoints.USER_CONNECTIONS("@me"), true); - } - - /** - * [USER ACCOUNT] Get the MFA backup codes for the current user - * @arg {String} password The password for the current user - * @arg {Boolean} [regenerate] Whether to regenerate the MFA backup codes or not - * @returns {Promise} The user's MFA codes - */ - getSelfMFACodes(password, regenerate) { - return this.requestHandler.request("POST", Endpoints.USER_MFA_CODES("@me"), true, { - password: password, - regenerate: !!regenerate - }); - } - - /** - * [USER ACCOUNT] Get the payment history for the current user - * @returns {Promise} The user's payment history - */ - getSelfPayments() { - return this.requestHandler.request("GET", Endpoints.USER_BILLING_PAYMENTS("@me"), true); - } - - /** - * [USER ACCOUNT] Get settings for the current user - * @returns {Promise} The user's settings data. - */ - getSelfSettings() { - return this.requestHandler.request("GET", Endpoints.USER_SETTINGS("@me"), true); - } - /** * Get the stage instance associated with a stage channel * @arg {String} channelID The stage channel ID @@ -3567,15 +3305,6 @@ class Client extends EventEmitter { }).then((members) => members.map((member) => new ThreadMember(member, this))); } - /** - * [USER ACCOUNT] Get profile data for a user - * @arg {String} userID The ID of the target user - * @returns {Promise} The user's profile data. - */ - getUserProfile(userID) { - return this.requestHandler.request("GET", Endpoints.USER_PROFILE(userID), true); - } - /** * Get a list of general/guild-specific voice regions * @arg {String} [guildID] The ID of the guild @@ -3617,7 +3346,7 @@ class Client extends EventEmitter { } /** - * Join a voice channel. If joining a group call, the voice connection ID will be stored in voiceConnections as "call". Otherwise, it will be the guild ID + * Join a voice channel * @arg {String} channelID The ID of the voice channel * @arg {Object} [options] VoiceConnection constructor options * @arg {Object} [options.opusOnly] Skip opus encoder initialization. You should not enable this unless you know what you are doing @@ -3643,7 +3372,7 @@ class Client extends EventEmitter { if(options.opusOnly === undefined) { options.opusOnly = this.options.opusOnly; } - return this.voiceConnections.join(this.channelGuildMap[channelID] || "call", channelID, options); + return this.voiceConnections.join(this.channelGuildMap[channelID], channelID, options); } /** @@ -3880,69 +3609,6 @@ class Client extends EventEmitter { return this.requestHandler.request("DELETE", Endpoints.CHANNEL_MESSAGE_REACTIONS(channelID, messageID), true); } - /** - * [USER ACCOUNT] Remove a relationship with a user - * @arg {String} userID The ID of the target user - * @returns {Promise} - */ - removeRelationship(userID) { - return this.requestHandler.request("DELETE", Endpoints.USER_RELATIONSHIP("@me", userID), true); - } - - /** - * [USER ACCOUNT] Search a channel's messages - * @arg {String} channelID The ID of the channel - * @arg {Object} query Search parameters - * @arg {String} [query.attachmentExtensions] Filter results by attachment extension - * @arg {String} [query.attachmentFilename] Filter results by attachment filename - * @arg {String} [query.authorID] Filter results by an author ID - * @arg {String} [query.content] Filter results by a content string - * @arg {Number} [query.contextSize=2] How many context messages around each result to return. - * @arg {String} [query.embedProviders] Filter results by embed provider - * @arg {String} [query.embedTypes] Filter results by embed type - * @arg {String} [query.has] Only return messages with an "attachment", "embed", or "link" - * @arg {Number} [query.limit=25] How many messages to return, 1 <= limit <= 25 - * @arg {String} [query.maxID] The maximum message ID to return results for - * @arg {String} [query.minID] The minimum message ID to return results for - * @arg {Number} [query.offset=0] The query index of the first message to be returned, 0 <= offset <= 5000 - * @arg {String} [query.sortBy="timestamp"] What to sort by, either "timestamp" or "relevance" - * @arg {String} [query.sortOrder="desc"] What order to sort by, either "asc" or "desc" - * For example, if you searched for `6` and contextSize was 2, `[4, 5, 6, 7, 8]` would be returned - * @returns {Promise} A search result object. The object will have a `totalResults` key and `results` key. - * Each entry in the result array is an array of Message objects. - * In each array, the message where `Message.hit === true` is the matched message, while the other messages are context messages. - * Sample return: ``` - * { - * totalResults: 2, - * results: [ - * [Message, Message, Message (Message.hit = true), Message], - * [Message, Message, Message (Message.hit = true), Message, Message] - * ] - * } - * ``` - */ - searchChannelMessages(channelID, query) { - return this.requestHandler.request("GET", Endpoints.CHANNEL_MESSAGES_SEARCH(channelID), true, { - sort_by: query.sortBy, - sort_order: query.sortOrder, - content: query.content, - author_id: query.authorID, - min_id: query.minID, - max_id: query.maxID, - limit: query.limit, - offset: query.offset, - context_size: query.contextSize, - has: query.has, - embed_providers: query.embedProviders, - embed_types: query.embedTypes, - attachment_extensions: query.attachmentExtensions, - attachment_filename: query.attachmentFilename - }).then((results) => ({ - totalResults: results.total_results, - results: results.messages && results.messages.map((result) => result.map((message) => new Message(message, this))) - })); - } - /** * Search for guild members by partial nickname/username * @arg {String} guildID The ID of the guild @@ -3960,62 +3626,6 @@ class Client extends EventEmitter { }); } - /** - * [USER ACCOUNT] Search a guild's messages - * @arg {String} guildID The ID of the guild - * @arg {Object} query Search parameters - * @arg {String} [query.attachmentExtensions] Filter results by attachment extension - * @arg {String} [query.attachmentFilename] Filter results by attachment filename - * @arg {String} [query.authorID] Filter results by an author ID - * @arg {Array} [query.channelIDs] Filter results by channel ID - * @arg {String} [query.content] Filter results by a content string - * @arg {Number} [query.contextSize=2] How many context messages around each result to return. - * @arg {String} [query.embedProviders] Filter results by embed provider - * @arg {String} [query.embedTypes] Filter results by embed type - * @arg {String} [query.has] Only return messages with an "attachment", "embed", or "link" - * @arg {Number} [query.limit=25] How many messages to return, 1 <= limit <= 25 - * @arg {String} [query.minID] The minimum message ID to return results for - * @arg {String} [query.maxID] The maximum message ID to return results for - * @arg {Number} [query.offset=0] The query index of the first message to be returned, 0 <= offset <= 5000 - * @arg {String} [query.sortBy="timestamp"] What to sort by, either "timestamp" or "relevance" - * @arg {String} [query.sortOrder="desc"] What order to sort by, either "asc" or "desc" - * For example, if you searched for `6` and contextSize was 2, `[4, 5, 6, 7, 8]` would be returned - * @returns {Promise} A search result object. The object will have a `totalResults` key and `results` key. - * Each entry in the result array is an array of Message objects. - * In each array, the message where `Message.hit === true` is the matched message, while the other messages are context messages. - * Sample return: ``` - * { - * totalResults: 2, - * results: [ - * [Message, Message, Message (Message.hit = true), Message], - * [Message, Message, Message (Message.hit = true), Message, Message] - * ] - * } - * ``` - */ - searchGuildMessages(guildID, query) { - return this.requestHandler.request("GET", Endpoints.GUILD_MESSAGES_SEARCH(guildID), true, { - sort_by: query.sortBy, - sort_order: query.sortOrder, - content: query.content, - author_id: query.authorID, - min_id: query.minID, - max_id: query.maxID, - limit: query.limit, - offset: query.offset, - context_size: query.contextSize, - has: query.has, - embed_providers: query.embedProviders, - embed_types: query.embedTypes, - attachment_extensions: query.attachmentExtensions, - attachment_filename: query.attachmentFilename, - channel_id: query.channelIDs - }).then((results) => ({ - totalResults: results.total_results, - results: results.messages && results.messages.map((result) => result.map((message) => new Message(message, this))) - })); - } - /** * Send typing status in a channel * @arg {String} channelID The ID of the channel @@ -4155,7 +3765,6 @@ class Client extends EventEmitter { "dmChannels", "ready", "reconnectAttempts", - "relationships", "requestHandler", "shards", "startTime", diff --git a/lib/Constants.js b/lib/Constants.js index be5aa6412..4b308ad55 100644 --- a/lib/Constants.js +++ b/lib/Constants.js @@ -236,9 +236,7 @@ module.exports.GatewayOPCodes = { REQUEST_GUILD_MEMBERS: 8, GET_GUILD_MEMBERS: 8, // [DEPRECATED] INVALID_SESSION: 9, HELLO: 10, - HEARTBEAT_ACK: 11, - SYNC_GUILD: 12, - SYNC_CALL: 13 + HEARTBEAT_ACK: 11 }; module.exports.GuildFeatures = [ diff --git a/lib/command/Command.js b/lib/command/Command.js index e40b44434..bae8ab160 100644 --- a/lib/command/Command.js +++ b/lib/command/Command.js @@ -514,34 +514,34 @@ class Command { toJSON(props = []) { return Base.prototype.toJSON.call(this, [ - "parentCommand", - "label", - "description", - "fullDescription", - "usage", "aliases", - "caseInsensitive", - "hooks", - "requirements", - "deleteCommand", "argsRequired", - "guildOnly", - "dmOnly", + "caseInsensitive", "cooldown", "cooldownExclusions", - "restartCooldown", - "cooldownReturns", "cooldownMessage", + "cooldownReturns", + "defaultSubcommandOptions", + "deleteCommand", + "description", + "dmOnly", + "errorMessage", + "execute", + "fullDescription", + "guildOnly", + "hidden", + "hooks", "invalidUsageMessage", + "label", + "parentCommand", "permissionMessage", - "errorMessage", "reactionButtons", "reactionButtonTimeout", - "execute", - "defaultSubcommandOptions", + "requirements", + "restartCooldown", "subcommands", "subcommandAliases", - "hidden", + "usage", ...props ]); } diff --git a/lib/command/CommandClient.js b/lib/command/CommandClient.js index 96c5d7dc2..572040bd5 100644 --- a/lib/command/CommandClient.js +++ b/lib/command/CommandClient.js @@ -442,11 +442,11 @@ class CommandClient extends Client { toJSON(props = []) { return super.toJSON([ + "activeMessages", + "commandAliases", "commandOptions", - "guildPrefixes", "commands", - "commandAliases", - "activeMessages", + "guildPrefixes", ...props ]); } diff --git a/lib/gateway/Shard.js b/lib/gateway/Shard.js index 3af694769..9a5e15a7b 100644 --- a/lib/gateway/Shard.js +++ b/lib/gateway/Shard.js @@ -3,10 +3,8 @@ const util = require("util"); const Base = require("../structures/Base"); const Bucket = require("../util/Bucket"); -const Call = require("../structures/Call"); const Channel = require("../structures/Channel"); const ForumChannel = require("../structures/ForumChannel"); -const GroupChannel = require("../structures/GroupChannel"); const GuildChannel = require("../structures/GuildChannel"); const Message = require("../structures/Message"); const DMChannel = require("../structures/DMChannel"); @@ -74,15 +72,6 @@ class Shard extends EventEmitter { checkReady() { if(!this.ready) { - if(this.guildSyncQueue.length > 0) { - this.requestGuildSync(this.guildSyncQueue); - this.guildSyncQueue = []; - this.guildSyncQueueLength = 1; - return; - } - if(this.unsyncedGuilds > 0) { - return; - } if(this.getAllUsersQueue.length > 0) { this.requestGuildMembers(this.getAllUsersQueue); this.getAllUsersQueue = []; @@ -116,10 +105,6 @@ class Shard extends EventEmitter { createGuild(_guild) { this.client.guildShardMap[_guild.id] = this.id; const guild = this.client.guilds.add(_guild, this.client, true); - if(this.client.bot === false) { - ++this.unsyncedGuilds; - this.syncGuild(guild.id); - } if(this.client.options.getAllUsers && guild.members.size < guild.memberCount) { this.getGuildMembers(guild.id, { presences: this.client.options.intents && this.client.options.intents & Constants.Intents.guildPresences @@ -512,10 +497,6 @@ class Shard extends EventEmitter { }); } - requestGuildSync(guildID) { - this.sendWS(GatewayOPCodes.SYNC_GUILD, guildID); - } - reset() { this.connecting = false; this.ready = false; @@ -533,9 +514,6 @@ class Shard extends EventEmitter { this.getAllUsersCount = {}; this.getAllUsersQueue = []; this.getAllUsersLength = 1; - this.guildSyncQueue = []; - this.guildSyncQueueLength = 1; - this.unsyncedGuilds = 0; this.latency = Infinity; this.lastHeartbeatAck = true; this.lastHeartbeatReceived = null; @@ -553,7 +531,7 @@ class Shard extends EventEmitter { this.guildCreateTimeout = null; } if(!this.ready) { - if(this.client.unavailableGuilds.size === 0 && this.unsyncedGuilds === 0) { + if(this.client.unavailableGuilds.size === 0) { return this.checkReady(); } this.guildCreateTimeout = setTimeout(() => { @@ -574,8 +552,8 @@ class Shard extends EventEmitter { sendStatusUpdate() { this.sendWS(GatewayOPCodes.PRESENCE_UPDATE, { activities: this.presence.activities, - afk: !!this.presence.afk, // For push notifications - since: this.presence.status === "idle" ? Date.now() : 0, + afk: !!this.presence.afk, + since: this.presence.status === "idle" ? Date.now() : null, status: this.presence.status }); } @@ -602,19 +580,6 @@ class Shard extends EventEmitter { } } - syncGuild(guildID) { - if(this.guildSyncQueueLength + 3 + guildID.length > 4081) { // 4096 - "{\"op\":12,\"d\":[]}".length + 1 for lazy comma offset - this.requestGuildSync(this.guildSyncQueue); - this.guildSyncQueue = [guildID]; - this.guildSyncQueueLength = 1 + guildID.length + 3; - } else if(this.ready) { - this.requestGuildSync([guildID]); - } else { - this.guildSyncQueue.push(guildID); - this.guildSyncQueueLength += guildID.length + 3; - } - } - wsEvent(packet) { switch(packet.t) { case "AUTO_MODERATION_ACTION_EXECUTION": { @@ -778,31 +743,6 @@ class Shard extends EventEmitter { this.emit("userUpdate", user, oldUser); } } - if(!packet.d.guild_id) { - packet.d.id = packet.d.user.id; - const relationship = this.client.relationships.get(packet.d.id); - if(!relationship) { // Removing relationships - break; - } - const oldPresence = { - activities: relationship.activities, - status: relationship.status - }; - /** - * Fired when a guild member or relationship's status or game changes - * @event Client#presenceUpdate - * @prop {Member | Relationship} other The updated member or relationship - * @prop {Object?} oldPresence The old presence data. If the user was offline when the bot started and the client option getAllUsers is not true, this will be null - * @prop {Array?} oldPresence.activities The member's current activities - * @prop {Object?} oldPresence.clientStatus The member's per-client status - * @prop {String} oldPresence.clientStatus.desktop The member's status on desktop. Either "online", "idle", "dnd", or "offline". Will be "offline" for bots - * @prop {String} oldPresence.clientStatus.mobile The member's status on mobile. Either "online", "idle", "dnd", or "offline". Will be "offline" for bots - * @prop {String} oldPresence.clientStatus.web The member's status on web. Either "online", "idle", "dnd", or "offline". Will be "online" for bots - * @prop {String} oldPresence.status The other user's old status. Either "online", "idle", or "offline" - */ - this.emit("presenceUpdate", this.client.relationships.update(packet.d), oldPresence); - break; - } const guild = this.client.guilds.get(packet.d.guild_id); if(!guild) { this.emit("debug", "Rogue presence update: " + JSON.stringify(packet), this.id); @@ -819,6 +759,18 @@ class Shard extends EventEmitter { } if((!member && packet.d.user.username) || oldPresence) { member = guild.members.update(packet.d, guild); + /** + * Fired when a guild member's status or game changes + * @event Client#presenceUpdate + * @prop {Member} other The updated member + * @prop {Object?} oldPresence The old presence data. If the user was offline when the bot started and the client option getAllUsers is not true, this will be null + * @prop {Array?} oldPresence.activities The member's current activities + * @prop {Object?} oldPresence.clientStatus The member's per-client status + * @prop {String} oldPresence.clientStatus.desktop The member's status on desktop. Either "online", "idle", "dnd", or "offline". Will be "offline" for bots + * @prop {String} oldPresence.clientStatus.mobile The member's status on mobile. Either "online", "idle", "dnd", or "offline". Will be "offline" for bots + * @prop {String} oldPresence.clientStatus.web The member's status on web. Either "online", "idle", "dnd", or "offline". Will be "online" for bots + * @prop {String} oldPresence.status The other user's old status. Either "online", "idle", or "offline" + */ this.emit("presenceUpdate", member, oldPresence); } break; @@ -837,48 +789,10 @@ class Shard extends EventEmitter { if(packet.d.self_stream === undefined) { packet.d.self_stream = false; } - if(packet.d.guild_id === undefined) { - packet.d.id = packet.d.user_id; - if(packet.d.channel_id === null) { - let flag = false; - for(const groupChannel of this.client.groupChannels) { - const call = (groupChannel[1].call || groupChannel[1].lastCall); - if(call && call.voiceStates.remove(packet.d)) { - flag = true; - break; - } - } - if(!flag) { - for(const dmChannel of this.client.dmChannels) { - const call = (dmChannel[1].call || dmChannel[1].lastCall); - if(call && call.voiceStates.remove(packet.d)) { - flag = true; - break; - } - } - if(!flag) { - this.emit("debug", new Error("VOICE_STATE_UPDATE for user leaving call not found")); - break; - } - } - } else { - const channel = this.client.getChannel(packet.d.channel_id); - if(!channel.call && !channel.lastCall) { - this.emit("debug", new Error("VOICE_STATE_UPDATE for untracked call")); - break; - } - (channel.call || channel.lastCall).voiceStates.update(packet.d); - } - break; - } const guild = this.client.guilds.get(packet.d.guild_id); if(!guild) { break; } - if(guild.pendingVoiceStates) { - guild.pendingVoiceStates.push(packet.d); - break; - } let member = guild.members.get(packet.d.id = packet.d.user_id); if(!member) { if(!packet.d.member) { @@ -1825,13 +1739,7 @@ class Shard extends EventEmitter { break; } let oldChannel; - if(channel instanceof GroupChannel) { - oldChannel = { - name: channel.name, - ownerID: channel.ownerID, - icon: channel.icon - }; - } else if(channel instanceof GuildChannel) { + if(channel instanceof GuildChannel) { oldChannel = { availableTags: channel.availableTags, bitrate: channel.bitrate, @@ -1871,13 +1779,8 @@ class Shard extends EventEmitter { guild.channels.remove(channel); guild.channels.add(newChannel, this.client); } else if(channel instanceof DMChannel) { - if(channel instanceof GroupChannel) { - this.client.groupChannels.remove(channel); - this.client.groupChannels.add(newChannel, this.client); - } else { - this.client.dmChannels.remove(channel); - this.client.dmChannels.add(newChannel, this.client); - } + this.client.dmChannels.remove(channel); + this.client.dmChannels.add(newChannel, this.client); } else { this.emit("warn", new Error("Unhandled CHANNEL_UPDATE type: " + JSON.stringify(packet, null, 2))); break; @@ -1945,138 +1848,11 @@ class Shard extends EventEmitter { }); } this.emit("channelDelete", channel); - } else if(packet.d.type === ChannelTypes.GROUP_DM) { - if(this.id === 0) { - this.emit("channelDelete", this.client.groupChannels.remove(packet.d)); - } } else { this.emit("warn", new Error("Unhandled CHANNEL_DELETE type: " + JSON.stringify(packet, null, 2))); } break; } - case "CALL_CREATE": { - packet.d.id = packet.d.message_id; - const channel = this.client.getChannel(packet.d.channel_id); - if(channel.call) { - channel.call.update(packet.d); - } else { - channel.call = new Call(packet.d, channel); - let incrementedID = ""; - let overflow = true; - const chunks = packet.d.id.match(/\d{1,9}/g).map((chunk) => parseInt(chunk)); - for(let i = chunks.length - 1; i >= 0; --i) { - if(overflow) { - ++chunks[i]; - overflow = false; - } - if(chunks[i] > 999999999) { - overflow = true; - incrementedID = "000000000" + incrementedID; - } else { - incrementedID = chunks[i] + incrementedID; - } - } - if(overflow) { - incrementedID = overflow + incrementedID; - } - this.client.getMessages(channel.id, { - limit: 1, - before: incrementedID - }).catch((err) => this.emit("error", err)); - } - /** - * Fired when a call is created - * @event Client#callCreate - * @prop {Call} call The call - */ - this.emit("callCreate", channel.call); - break; - } - case "CALL_UPDATE": { - const channel = this.client.getChannel(packet.d.channel_id); - if(!channel.call) { - throw new Error("CALL_UPDATE but channel has no call"); - } - const oldCall = { - endedTimestamp: channel.call.endedTimestamp, - participants: channel.call.participants, - region: channel.call.region, - ringing: channel.call.ringing, - unavailable: channel.call.unavailable - }; - /** - * Fired when a call is updated - * @event Client#callUpdate - * @prop {Call} call The updated call - * @prop {Object} oldCall The old call data - * @prop {Number?} oldCall.endedTimestamp The timestamp of the call end - * @prop {Array} oldCall.participants The IDs of the call participants - * @prop {String?} oldCall.region The region of the call server - * @prop {Array?} oldCall.ringing The IDs of people that were being rung - * @prop {Boolean} oldCall.unavailable Whether the call was unavailable or not - */ - this.emit("callUpdate", channel.call.update(packet.d), oldCall); - break; - } - case "CALL_DELETE": { - const channel = this.client.getChannel(packet.d.channel_id); - if(!channel.call) { - throw new Error("CALL_DELETE but channel has no call"); - } - channel.lastCall = channel.call; - channel.call = null; - /** - * Fired when a call is deleted - * @event Client#callDelete - * @prop {Call} call The call - */ - this.emit("callDelete", channel.lastCall); - break; - } - case "CHANNEL_RECIPIENT_ADD": { - const channel = this.client.groupChannels.get(packet.d.channel_id); - /** - * Fired when a user joins a group channel - * @event Client#channelRecipientAdd - * @prop {GroupChannel} channel The channel - * @prop {User} user The user - */ - this.emit("channelRecipientAdd", channel, channel.recipients.add(this.client.users.update(packet.d.user, this.client))); - break; - } - case "CHANNEL_RECIPIENT_REMOVE": { - const channel = this.client.groupChannels.get(packet.d.channel_id); - /** - * Fired when a user leaves a group channel - * @event Client#channelRecipientRemove - * @prop {GroupChannel} channel The channel - * @prop {User} user The user - */ - this.emit("channelRecipientRemove", channel, channel.recipients.remove(packet.d.user)); - break; - } - case "FRIEND_SUGGESTION_CREATE": { - /** - * Fired when a client receives a friend suggestion - * @event Client#friendSuggestionCreate - * @prop {User} user The suggested user - * @prop {Array} reasons Array of reasons why this suggestion was made - * @prop {String} reasons.name Username of suggested user on that platform - * @prop {String} reasons.platform_type Platform you share with the user - * @prop {Number} reasons.type Type of reason? - */ - this.emit("friendSuggestionCreate", new User(packet.d.suggested_user, this.client), packet.d.reasons); - break; - } - case "FRIEND_SUGGESTION_DELETE": { - /** - * Fired when a client's friend suggestion is removed for any reason - * @event Client#friendSuggestionDelete - * @prop {User} user The suggested user - */ - this.emit("friendSuggestionDelete", this.client.users.get(packet.d.suggested_user_id)); - break; - } case "GUILD_MEMBERS_CHUNK": { const guild = this.client.guilds.get(packet.d.guild_id); if(!guild) { @@ -2126,46 +1902,6 @@ class Shard extends EventEmitter { break; } - case "GUILD_SYNC": {// (╯°□°)╯︵ ┻━┻ thx Discord devs - const guild = this.client.guilds.get(packet.d.id); - for(const member of packet.d.members) { - member.id = member.user.id; - guild.members.add(member, guild); - } - for(const presence of packet.d.presences) { - if(!guild.members.get(presence.user.id)) { - let userData = this.client.users.get(presence.user.id); - if(userData) { - userData = `{username: ${userData.username}, id: ${userData.id}, discriminator: ${userData.discriminator}}`; - } - this.emit("debug", `Presence without member. ${presence.user.id}. In global user cache: ${userData}. ` + JSON.stringify(presence), this.id); - continue; - } - presence.id = presence.user.id; - guild.members.update(presence); - } - if(guild.pendingVoiceStates && guild.pendingVoiceStates.length > 0) { - for(const voiceState of guild.pendingVoiceStates) { - if(!guild.members.get(voiceState.user_id)) { - continue; - } - voiceState.id = voiceState.user_id; - const channel = guild.channels.get(voiceState.channel_id); - if(channel) { - channel.voiceMembers.add(guild.members.update(voiceState)); - if(this.client.options.seedVoiceConnections && voiceState.id === this.client.user.id && !this.client.voiceConnections.get(channel.guild ? channel.guild.id : "call")) { - this.client.joinVoiceChannel(channel.id); - } - } else { // Phantom voice states from connected users in deleted channels (╯°□°)╯︵ ┻━┻ - this.client.emit("debug", "Phantom voice state received but channel not found | Guild: " + guild.id + " | Channel: " + voiceState.channel_id); - } - } - } - guild.pendingVoiceStates = null; - --this.unsyncedGuilds; - this.checkReady(); - break; - } case "RESUMED": case "READY": { this.connectAttempts = 0; @@ -2208,14 +1944,7 @@ class Shard extends EventEmitter { this.client._token = "Bot " + this.client._token; } } else { - this.client.bot = false; - this.client.userGuildSettings = {}; - if(packet.d.user_guild_settings) { - packet.d.user_guild_settings.forEach((guildSettings) => { - this.client.userGuildSettings[guildSettings.guild_id] = guildSettings; - }); - } - this.client.userSettings = packet.d.user_settings; + this.emit("warn", new Error("User accounts are against Discord Terms of Service and not supported")); } if(packet.d._trace) { @@ -2237,32 +1966,11 @@ class Shard extends EventEmitter { if(channel.type === undefined || channel.type === ChannelTypes.DM) { this.client.dmChannelMap[channel.recipients[0].id] = channel.id; this.client.dmChannels.add(channel, this.client, true); - } else if(channel.type === ChannelTypes.GROUP_DM) { - this.client.groupChannels.add(channel, this.client, true); } else { this.emit("warn", new Error("Unhandled READY private_channel type: " + JSON.stringify(channel, null, 2))); } }); - if(packet.d.relationships) { - packet.d.relationships.forEach((relationship) => { - this.client.relationships.add(relationship, this.client, true); - }); - } - - if(packet.d.presences) { - packet.d.presences.forEach((presence) => { - if(this.client.relationships.get(presence.user.id)) { // Avoid DM channel presences which are also in here - presence.id = presence.user.id; - this.client.relationships.update(presence, null, true); - } - }); - } - - if(packet.d.notes) { - this.client.notes = packet.d.notes; - } - this.client.application = packet.d.application; this.preReady = true; @@ -2303,45 +2011,6 @@ class Shard extends EventEmitter { this.emit("userUpdate", user, oldUser); break; } - case "RELATIONSHIP_ADD": { - if(this.client.bot) { - break; - } - const relationship = this.client.relationships.get(packet.d.id); - if(relationship) { - const oldRelationship = { - type: relationship.type - }; - /** - * Fired when a relationship is updated - * @event Client#relationshipUpdate - * @prop {Relationship} relationship The relationship - * @prop {Object} oldRelationship The old relationship data - * @prop {Number} oldRelationship.type The old type of the relationship - */ - this.emit("relationshipUpdate", this.client.relationships.update(packet.d), oldRelationship); - } else { - /** - * Fired when a relationship is added - * @event Client#relationshipAdd - * @prop {Relationship} relationship The relationship - */ - this.emit("relationshipAdd", this.client.relationships.add(packet.d, this.client)); - } - break; - } - case "RELATIONSHIP_REMOVE": { - if(this.client.bot) { - break; - } - /** - * Fired when a relationship is removed - * @event Client#relationshipRemove - * @prop {Relationship} relationship The relationship - */ - this.emit("relationshipRemove", this.client.relationships.remove(packet.d)); - break; - } case "GUILD_EMOJIS_UPDATE": { const guild = this.client.guilds.get(packet.d.guild_id); let oldEmojis = null; @@ -2412,33 +2081,6 @@ class Shard extends EventEmitter { }); break; } - case "PRESENCES_REPLACE": { - for(const presence of packet.d) { - const guild = this.client.guilds.get(presence.guild_id); - if(!guild) { - this.emit("debug", "Rogue presences replace: " + JSON.stringify(presence), this.id); - continue; - } - const member = guild.members.get(presence.user.id); - if(!member && presence.user.username) { - presence.id = presence.user.id; - member.update(presence); - } - } - break; - } - case "USER_NOTE_UPDATE": { - if(packet.d.note) { - this.client.notes[packet.d.id] = packet.d.note; - } else { - delete this.client.notes[packet.d.id]; - } - break; - } - case "USER_GUILD_SETTINGS_UPDATE": { - this.client.userGuildSettings[packet.d.guild_id] = packet.d; - break; - } case "THREAD_CREATE": { const channel = Channel.from(packet.d, this.client); if(!channel.guild) { @@ -2791,12 +2433,6 @@ class Shard extends EventEmitter { this.emit("guildScheduledEventUserRemove", event || {id: packet.d.guild_scheduled_event_id, guild: guild}, user); break; } - case "MESSAGE_ACK": // Ignore these - case "GUILD_INTEGRATIONS_UPDATE": - case "USER_SETTINGS_UPDATE": - case "CHANNEL_PINS_ACK": { - break; - } case "INTERACTION_CREATE": { /** * Fired when an interaction is created @@ -2815,6 +2451,15 @@ class Shard extends EventEmitter { this.emit("applicationCommandPermissionsUpdate", packet.d); break; } + case "GUILD_INTEGRATIONS_UPDATE": { + /** + * Fired when a guild integration is updated + * @event Client#guildIntegrationsUpdate + * @prop {Guild} guild The guild where the integration was updated. If the guild isn't cached, this will be an object with an `id` key. No other properties are guaranteed + */ + this.emit("guildIntegrationsUpdate", this.client.guilds.get(packet.d.guild_id) || {id: packet.d.guild_id}); + break; + } default: { /** * Fired when the shard encounters an unknown packet @@ -2961,25 +2606,22 @@ class Shard extends EventEmitter { toJSON(props = []) { return Base.prototype.toJSON.call(this, [ + "connectAttempts", "connecting", - "ready", "discordServerTrace", - "status", + "getAllUsersCount", + "getAllUsersLength", + "getAllUsersQueue", + "lastHeartbeatAck", "lastHeartbeatReceived", "lastHeartbeatSent", "latency", "preReady", - "getAllUsersCount", - "getAllUsersQueue", - "getAllUsersLength", - "guildSyncQueue", - "guildSyncQueueLength", - "unsyncedGuilds", - "lastHeartbeatAck", + "ready", + "reconnectInterval", "seq", "sessionID", - "reconnectInterval", - "connectAttempts", + "status", ...props ]); } diff --git a/lib/rest/Endpoints.js b/lib/rest/Endpoints.js index dff9d7567..795912dd3 100644 --- a/lib/rest/Endpoints.js +++ b/lib/rest/Endpoints.js @@ -13,7 +13,6 @@ module.exports.COMMAND_PERMISSIONS = (applicationID, guildID, commandID) module.exports.COMMANDS = (applicationID) => `/applications/${applicationID}/commands`; module.exports.CHANNEL = (chanID) => `/channels/${chanID}`; module.exports.CHANNEL_BULK_DELETE = (chanID) => `/channels/${chanID}/messages/bulk-delete`; -module.exports.CHANNEL_CALL_RING = (chanID) => `/channels/${chanID}/call/ring`; module.exports.CHANNEL_CROSSPOST = (chanID, msgID) => `/channels/${chanID}/messages/${msgID}/crosspost`; module.exports.CHANNEL_FOLLOW = (chanID) => `/channels/${chanID}/followers`; module.exports.CHANNEL_INVITES = (chanID) => `/channels/${chanID}/invites`; @@ -22,7 +21,6 @@ module.exports.CHANNEL_MESSAGE_REACTION_USER = (chanID, msgID, reaction, userID) module.exports.CHANNEL_MESSAGE_REACTIONS = (chanID, msgID) => `/channels/${chanID}/messages/${msgID}/reactions`; module.exports.CHANNEL_MESSAGE = (chanID, msgID) => `/channels/${chanID}/messages/${msgID}`; module.exports.CHANNEL_MESSAGES = (chanID) => `/channels/${chanID}/messages`; -module.exports.CHANNEL_MESSAGES_SEARCH = (chanID) => `/channels/${chanID}/messages/search`; module.exports.CHANNEL_PERMISSION = (chanID, overID) => `/channels/${chanID}/permissions/${overID}`; module.exports.CHANNEL_PERMISSIONS = (chanID) => `/channels/${chanID}/permissions`; module.exports.CHANNEL_PIN = (chanID, msgID) => `/channels/${chanID}/pins/${msgID}`; @@ -58,7 +56,6 @@ module.exports.GUILD_MEMBER_NICK = (guildID, memberID) module.exports.GUILD_MEMBER_ROLE = (guildID, memberID, roleID) => `/guilds/${guildID}/members/${memberID}/roles/${roleID}`; module.exports.GUILD_MEMBERS = (guildID) => `/guilds/${guildID}/members`; module.exports.GUILD_MEMBERS_SEARCH = (guildID) => `/guilds/${guildID}/members/search`; -module.exports.GUILD_MESSAGES_SEARCH = (guildID) => `/guilds/${guildID}/messages/search`; module.exports.GUILD_MFA_LEVEL = (guildID) => `/guilds/${guildID}/mfa`; module.exports.GUILD_ONBOARDING = (guildID) => `/guilds/${guildID}/onboarding`; module.exports.GUILD_PREVIEW = (guildID) => `/guilds/${guildID}/preview`; @@ -84,7 +81,7 @@ module.exports.GUILD_VOICE_STATE = (guildID, user) module.exports.GUILDS = "/guilds"; module.exports.INTERACTION_RESPOND = (interactID, interactToken) => `/interactions/${interactID}/${interactToken}/callback`; module.exports.INVITE = (inviteID) => `/invites/${inviteID}`; -module.exports.OAUTH2_APPLICATION = (appID) => `/oauth2/applications/${appID}`; +module.exports.OAUTH2_APPLICATION = "/oauth2/applications/@me"; module.exports.ORIGINAL_INTERACTION_RESPONSE = (appID, interactToken) => `/webhooks/${appID}/${interactToken}`; module.exports.POLL_ANSWER_VOTERS = (channelID, msgID, answerID) => `/channels/${channelID}/polls/${msgID}/answers/${answerID}`; module.exports.POLL_END = (channelID, msgID) => `/channels/${channelID}/polls/${msgID}/expire`; @@ -101,22 +98,9 @@ module.exports.THREADS_ARCHIVED = (channelID, type) module.exports.THREADS_ARCHIVED_JOINED = (channelID) => `/channels/${channelID}/users/@me/threads/archived/private`; module.exports.THREADS_GUILD_ACTIVE = (guildID) => `/guilds/${guildID}/threads/active`; module.exports.USER = (userID) => `/users/${userID}`; -module.exports.USER_BILLING = (userID) => `/users/${userID}/billing`; -module.exports.USER_BILLING_PAYMENTS = (userID) => `/users/${userID}/billing/payments`; -module.exports.USER_BILLING_PREMIUM_SUBSCRIPTION = (userID) => `/users/${userID}/billing/premium-subscription`; module.exports.USER_CHANNELS = (userID) => `/users/${userID}/channels`; -module.exports.USER_CONNECTION_PLATFORM = (userID, platform, id) => `/users/${userID}/connections/${platform}/${id}`; -module.exports.USER_CONNECTIONS = (userID) => `/users/${userID}/connections`; module.exports.USER_GUILD = (userID, guildID) => `/users/${userID}/guilds/${guildID}`; module.exports.USER_GUILDS = (userID) => `/users/${userID}/guilds`; -module.exports.USER_MFA_CODES = (userID) => `/users/${userID}/mfa/codes`; -module.exports.USER_MFA_TOTP_DISABLE = (userID) => `/users/${userID}/mfa/totp/disable`; -module.exports.USER_MFA_TOTP_ENABLE = (userID) => `/users/${userID}/mfa/totp/enable`; -module.exports.USER_NOTE = (userID, targetID) => `/users/${userID}/note/${targetID}`; -module.exports.USER_PROFILE = (userID) => `/users/${userID}/profile`; -module.exports.USER_RELATIONSHIP = (userID, relID) => `/users/${userID}/relationships/${relID}`; -module.exports.USER_SETTINGS = (userID) => `/users/${userID}/settings`; -module.exports.USERS = "/users"; module.exports.VOICE_REGIONS = "/voice/regions"; module.exports.WEBHOOK = (hookID) => `/webhooks/${hookID}`; module.exports.WEBHOOK_MESSAGE = (hookID, token, msgID) => `/webhooks/${hookID}/${token}/messages/${msgID}`; diff --git a/lib/structures/Call.js b/lib/structures/Call.js deleted file mode 100644 index 59653b1f8..000000000 --- a/lib/structures/Call.js +++ /dev/null @@ -1,76 +0,0 @@ -"use strict"; - -const Base = require("./Base"); -const Collection = require("../util/Collection"); -const VoiceState = require("./VoiceState"); - -/** - * Represents a call - * @prop {GroupChannel} channel The call channel - * @prop {Number} createdAt Timestamp of the call's creation - * @prop {Number?} endedTimestamp The timestamp of the call end - * @prop {String} id The ID of the call - * @prop {Array} participants The IDs of the call participants - * @prop {String?} region The region of the call server - * @prop {Array?} ringing The IDs of people that still have not responded to the call request - * @prop {Boolean} unavailable Whether the call is unavailable or not - * @prop {Collection} voiceStates The voice states of the call participants - */ -class Call extends Base { - constructor(data, channel) { - super(data.id); - this.channel = channel; - this.voiceStates = new Collection(VoiceState); - this.ringing = []; - this.participants = []; - this.region = null; - this.endedTimestamp = null; - this.unavailable = true; - this.update(data); - } - - update(data) { - if(data.participants !== undefined) { - this.participants = data.participants; - } - if(data.ringing !== undefined) { - if(!this.ringing.includes(this.channel._client.user.id) && (this.ringing = data.ringing).includes(this.channel._client.user.id)) { - /** - * Fired when the bot user is rung in a call - * @event Client#callRing - * @prop {Call} call The call - */ - this.channel._client.emit("callRing", this); - } - } - if(data.region !== undefined) { - this.region = data.region; - } - if(data.ended_timestamp !== undefined) { - this.endedTimestamp = Date.parse(data.ended_timestamp); - } - if(data.unavailable !== undefined) { - this.unavailable = data.unavailable; - } - if(data.voice_states) { - data.voice_states.forEach((voiceState) => { - voiceState.id = voiceState.user_id; - this.voiceStates.add(voiceState); - }); - } - } - - toJSON(props = []) { - return super.toJSON([ - "endedTimestamp", - "participants", - "region", - "ringing", - "unavailable", - "voiceStates", - ...props - ]); - } -} - -module.exports = Call; diff --git a/lib/structures/DMChannel.js b/lib/structures/DMChannel.js index 23cbe47e4..522763b0f 100644 --- a/lib/structures/DMChannel.js +++ b/lib/structures/DMChannel.js @@ -37,11 +37,10 @@ class DMChannel extends Channel { * Add a reaction to a message * @arg {String} messageID The ID of the message * @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji) - * @arg {String} [userID="@me"] The ID of the user to react as. Passing this parameter is deprecated and will not be supported in future versions. * @returns {Promise} */ - addMessageReaction(messageID, reaction, userID) { - return this._client.addMessageReaction.call(this._client, this.id, messageID, reaction, userID); + addMessageReaction(messageID, reaction) { + return this._client.addMessageReaction.call(this._client, this.id, messageID, reaction); } /** diff --git a/lib/structures/Guild.js b/lib/structures/Guild.js index 152ef5c08..e13af5f61 100644 --- a/lib/structures/Guild.js +++ b/lib/structures/Guild.js @@ -186,27 +186,23 @@ class Guild extends Base { } if(data.voice_states) { - if(!client.bot) { - this.pendingVoiceStates = data.voice_states; - } else { - for(const voiceState of data.voice_states) { - if(!this.members.get(voiceState.user_id)) { - continue; - } - voiceState.id = voiceState.user_id; - try { - const channel = this.channels.get(voiceState.channel_id); - const member = this.members.update(voiceState); - if(channel && channel.voiceMembers) { - channel.voiceMembers.add(member); - } - } catch(err) { - client.emit("error", err, this.shard.id); - continue; - } - if(client.options.seedVoiceConnections && voiceState.id === client.user.id && !client.voiceConnections.get(this.id)) { - process.nextTick(() => this._client.joinVoiceChannel(voiceState.channel_id)); + for(const voiceState of data.voice_states) { + if(!this.members.get(voiceState.user_id)) { + continue; + } + voiceState.id = voiceState.user_id; + try { + const channel = this.channels.get(voiceState.channel_id); + const member = this.members.update(voiceState); + if(channel && channel.voiceMembers) { + channel.voiceMembers.add(member); } + } catch(err) { + client.emit("error", err, this.shard.id); + continue; + } + if(client.options.seedVoiceConnections && voiceState.id === client.user.id && !client.voiceConnections.get(this.id)) { + process.nextTick(() => this._client.joinVoiceChannel(voiceState.channel_id)); } } } @@ -803,19 +799,6 @@ class Guild extends Base { return this._client.editGuildEmoji.call(this._client, this.id, emojiID, options, reason); } - /** - * Edit a guild integration - * @arg {String} integrationID The ID of the integration - * @arg {Object} options The properties to edit - * @arg {String} [options.enableEmoticons] Whether to enable integration emoticons or not - * @arg {String} [options.expireBehavior] What to do when a user's subscription runs out - * @arg {String} [options.expireGracePeriod] How long before the integration's role is removed from an unsubscribed user - * @returns {Promise} - */ - editIntegration(integrationID, options) { - return this._client.editGuildIntegration.call(this._client, this.id, integrationID, options); - } - /** * Edit a guild member * @arg {String} memberID The ID of the member (use "@me" to edit the current bot user) @@ -1420,15 +1403,6 @@ class Guild extends Base { return this._client.searchGuildMembers.call(this._client, this.id, query, limit); } - /** - * Force a guild integration to sync - * @arg {String} integrationID The ID of the integration - * @returns {Promise} - */ - syncIntegration(integrationID) { - return this._client.syncGuildIntegration.call(this._client, this.id, integrationID); - } - /** * Force a guild template to sync * @arg {String} code The template code @@ -1478,7 +1452,6 @@ class Guild extends Base { "mfaLevel", "name", "ownerID", - "pendingVoiceStates", "preferredLocale", "premiumProgressBarEnabled", "premiumSubscriptionCount", diff --git a/lib/structures/GuildIntegration.js b/lib/structures/GuildIntegration.js index f34163e5c..0d164901e 100644 --- a/lib/structures/GuildIntegration.js +++ b/lib/structures/GuildIntegration.js @@ -75,26 +75,6 @@ class GuildIntegration extends Base { return this.guild.shard.client.deleteGuildIntegration.call(this.guild.shard.client, this.guild.id, this.id); } - /** - * Edit the guild integration - * @arg {Object} options The properties to edit - * @arg {String} [options.enableEmoticons] Whether to enable integration emoticons or not - * @arg {String} [options.expireBehavior] What to do when a user's subscription runs out - * @arg {String} [options.expireGracePeriod] How long before the integration's role is removed from an unsubscribed user - * @returns {Promise} - */ - edit(options) { - return this.guild.shard.client.editGuildIntegration.call(this.guild.shard.client, this.guild.id, this.id, options); - } - - /** - * Force the guild integration to sync - * @returns {Promise} - */ - sync() { - return this.guild.shard.client.syncGuildIntegration.call(this.guild.shard.client, this.guild.id, this.id); - } - toJSON(props = []) { return super.toJSON([ "account", diff --git a/lib/structures/GuildTextableChannel.js b/lib/structures/GuildTextableChannel.js index b192f5b95..53716a664 100644 --- a/lib/structures/GuildTextableChannel.js +++ b/lib/structures/GuildTextableChannel.js @@ -29,11 +29,10 @@ class GuildTextableChannel extends GuildChannel { * Add a reaction to a message * @arg {String} messageID The ID of the message * @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji) - * @arg {String} [userID="@me"] The ID of the user to react as. Passing this parameter is deprecated and will not be supported in future versions. * @returns {Promise} */ - addMessageReaction(messageID, reaction, userID) { - return this._client.addMessageReaction.call(this._client, this.id, messageID, reaction, userID); + addMessageReaction(messageID, reaction) { + return this._client.addMessageReaction.call(this._client, this.id, messageID, reaction); } /** diff --git a/lib/structures/Message.js b/lib/structures/Message.js index c3d25ce69..300d78c03 100644 --- a/lib/structures/Message.js +++ b/lib/structures/Message.js @@ -2,8 +2,7 @@ const Base = require("./Base"); const Endpoints = require("../rest/Endpoints"); -const Call = require("./Call"); -const {MessageTypes, MessageFlags} = require("../Constants"); +const {MessageFlags} = require("../Constants"); const User = require("./User"); /** @@ -23,7 +22,7 @@ const User = require("./User"); * @prop {Number?} editedTimestamp Timestamp of latest message edit * @prop {Array} embeds Array of embeds * @prop {Number} flags Message flags (see constants) - * @prop {String} [guildID] The ID of the guild this message is in (undefined if in DMs) + * @prop {String?} guildID The ID of the guild this message is in (undefined if in DMs) * @prop {String} id The ID of the message * @prop {Object?} interaction An object containing info about the interaction the message is responding to, if applicable * @prop {String} interaction.id The ID of the interaction @@ -63,7 +62,6 @@ class Message extends Base { id: data.channel_id }; this.content = ""; - this.hit = !!data.hit; this.reactions = {}; this.guildID = data.guild_id; this.webhookID = data.webhook_id; @@ -142,27 +140,10 @@ class Message extends Base { this.member = null; } - if(this.type === MessageTypes.CALL) { - if(data.call.ended_timestamp) { - if((!this.channel.lastCall || this.channel.lastCall.endedTimestamp < Date.parse(data.call.ended_timestamp))) { - data.call.id = this.id; - this.channel.lastCall = new Call(data.call, this.channel); - } - } else { - if(!this.channel.call) { - data.call.id = this.id; - this.channel.call = new Call(data.call, this.channel); - } - } - } - this.update(data, client); } update(data, client) { - if(this.type === 3) { // (╯°□°)╯︵ ┻━┻ - (this.channel.call || this.channel.lastCall).update(data.call); - } if(data.content !== undefined) { this.content = data.content || ""; this.mentionEveryone = !!data.mention_everyone; @@ -236,6 +217,12 @@ class Message extends Base { if(data.components !== undefined) { this.components = data.components; } + if(data.call !== undefined) { + this.call = { + endedTimestamp: Date.parse(data.call.ended_timestamp) || null, + participants: data.call.participants + }; + } } get channelMentions() { @@ -295,14 +282,13 @@ class Message extends Base { /** * Add a reaction to a message * @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji) - * @arg {String} [userID="@me"] The ID of the user to react as. Passing this parameter is deprecated and will not be supported in future versions. * @returns {Promise} */ - addReaction(reaction, userID) { + addReaction(reaction) { if(this.flags & MessageFlags.EPHEMERAL) { throw new Error("Ephemeral messages cannot have reactions"); } - return this._client.addMessageReaction.call(this._client, this.channel.id, this.id, reaction, userID); + return this._client.addMessageReaction.call(this._client, this.channel.id, this.id, reaction); } /** @@ -477,7 +463,7 @@ class Message extends Base { /** * Remove a reaction from a message * @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji) - * @arg {String} [userID="@me"] The ID of the user to remove the reaction for. + * @arg {String} [userID="@me"] The ID of the user to remove the reaction for * @returns {Promise} */ removeReaction(reaction, userID) { @@ -532,7 +518,6 @@ class Message extends Base { "embeds", "flags", "guildID", - "hit", "member", "mentionEveryone", "mentions", diff --git a/lib/structures/Relationship.js b/lib/structures/Relationship.js deleted file mode 100644 index 3ba575a32..000000000 --- a/lib/structures/Relationship.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; - -const Base = require("./Base"); - -/** - * [USER ACCOUNT] Represents a Relationship - * @prop {Object?} game The active game the other user is playing - * @prop {String} game.name The name of the active game - * @prop {Number} game.type The type of the active game (0 is default, 1 is Twitch, 2 is YouTube) - * @prop {String?} game.url The url of the active game - * @prop {String} status The other user's status. Either "online", "idle", or "offline" - * @prop {Number} type The type of relationship. 1 is friend, 2 is block, 3 is incoming request, 4 is outgoing request - * @prop {User} user The other user in the relationship - */ -class Relationship extends Base { - constructor(data, client) { - super(data.id); - this.user = client.users.add(data.user, client); - this.type = 0; - this.status = "offline"; - this.activities = null; - this.update(data); - } - - update(data) { - if(data.type !== undefined) { - this.type = data.type; - } - if(data.status !== undefined) { - this.status = data.status; - } - if(data.activities !== undefined) { - this.activities = data.activities; - } - } - - toJSON(props = []) { - return super.toJSON([ - "activities", - "status", - "type", - "user", - ...props - ]); - } -} - -module.exports = Relationship; diff --git a/lib/structures/User.js b/lib/structures/User.js index 373296154..ffaa69be7 100644 --- a/lib/structures/User.js +++ b/lib/structures/User.js @@ -110,22 +110,6 @@ class User extends Base { return this.avatar ? this._client._formatImage(Endpoints.USER_AVATAR(this.id, this.avatar), "jpg") : this.defaultAvatarURL; } - /** - * [USER ACCOUNT] Create a relationship with the user - * @arg {Boolean} [block=false] If true, block the user. Otherwise, add the user as a friend - * @returns {Promise} - */ - addRelationship(block) { - return this._client.addRelationship.call(this._client, this.id, block); - } - - /** - * [USER ACCOUNT] Delete the current user's note for another user - */ - deleteNote() { - return this._client.deleteUserNote.call(this._client, this.id); - } - /** * Get the user's avatar with the given format and size * @arg {String} [format] The filetype of the avatar ("jpg", "jpeg", "png", "gif", or "webp") @@ -158,15 +142,6 @@ class User extends Base { return this._client._formatImage(Endpoints.BANNER(this.id, this.banner), format, size); } - /** - * [USER ACCOUNT] Edit the current user's note for the user - * @arg {String} note The note - * @returns {Promise} - */ - editNote(note) { - return this._client.editUserNote.call(this._client, this.id, note); - } - /** * Get a DM channel with the user, or create one if it does not exist * @returns {Promise} @@ -175,22 +150,6 @@ class User extends Base { return this._client.getDMChannel.call(this._client, this.id); } - /** - * [USER ACCOUNT] Get profile data for the user - * @returns {Promise} The user's profile data. - */ - getProfile() { - return this._client.getUserProfile.call(this._client, this.id); - } - - /** - * [USER ACCOUNT] Remove a relationship with the user - * @returns {Promise} - */ - removeRelationship() { - return this._client.removeRelationship.call(this._client, this.id); - } - toJSON(props = []) { return super.toJSON([ "accentColor", diff --git a/lib/structures/VoiceState.js b/lib/structures/VoiceState.js index 5f8957e65..d28fbfadb 100644 --- a/lib/structures/VoiceState.js +++ b/lib/structures/VoiceState.js @@ -3,7 +3,7 @@ const Base = require("./Base"); /** - * Represents a member's voice state in a call/guild + * Represents a member's voice state in a guild * @prop {String?} channelID The ID of the member's current voice channel * @prop {Boolean} deaf Whether the member is server deafened or not * @prop {String} id The ID of the member diff --git a/lib/voice/VoiceConnection.js b/lib/voice/VoiceConnection.js index 056430b8e..a6eb5f473 100644 --- a/lib/voice/VoiceConnection.js +++ b/lib/voice/VoiceConnection.js @@ -203,13 +203,13 @@ class VoiceConnection extends EventEmitter { } if(this.resuming) { this.sendWS(VoiceOPCodes.RESUME, { - server_id: this.id === "call" ? data.channel_id : this.id, + server_id: this.id, session_id: data.session_id, token: data.token }); } else { this.sendWS(VoiceOPCodes.IDENTIFY, { - server_id: this.id === "call" ? data.channel_id : this.id, + server_id: this.id, user_id: data.user_id, session_id: data.session_id, token: data.token