From b492a539cbd58603edcc811cb42f4563c6f2f8b3 Mon Sep 17 00:00:00 2001 From: UserUNP <39243708+UserUNP@users.noreply.github.com> Date: Sun, 12 Mar 2023 08:00:42 +0100 Subject: [PATCH 1/5] typescript & bug fixes --- .editorconfig | 26 ++++ .gitignore | 3 +- dist/lib/constants.js | 180 ++++++++++++++++++++++++++ dist/lib/constants.js.map | 1 + dist/lib/index.js | 161 ++++++++++++++++++++++++ dist/lib/index.js.map | 1 + dist/lib/rpc/command.js | 55 ++++++++ dist/lib/rpc/command.js.map | 1 + dist/types/constants.d.ts | 24 ++++ dist/types/constants.d.ts.map | 1 + dist/types/index.d.ts | 36 ++++++ dist/types/index.d.ts.map | 1 + dist/types/rpc/command.d.ts | 21 ++++ dist/types/rpc/command.d.ts.map | 1 + package.json | 13 +- pnpm-lock.yaml | 42 +++++++ src/{constants.js => constants.ts} | 86 ++++++++++--- src/index.js | 172 ------------------------- src/index.ts | 194 +++++++++++++++++++++++++++++ src/rpc/command.js | 61 --------- src/rpc/command.ts | 147 ++++++++++++++++++++++ tsconfig.json | 43 +++++++ 22 files changed, 1018 insertions(+), 252 deletions(-) create mode 100644 .editorconfig create mode 100644 dist/lib/constants.js create mode 100644 dist/lib/constants.js.map create mode 100644 dist/lib/index.js create mode 100644 dist/lib/index.js.map create mode 100644 dist/lib/rpc/command.js create mode 100644 dist/lib/rpc/command.js.map create mode 100644 dist/types/constants.d.ts create mode 100644 dist/types/constants.d.ts.map create mode 100644 dist/types/index.d.ts create mode 100644 dist/types/index.d.ts.map create mode 100644 dist/types/rpc/command.d.ts create mode 100644 dist/types/rpc/command.d.ts.map create mode 100644 pnpm-lock.yaml rename src/{constants.js => constants.ts} (54%) delete mode 100644 src/index.js create mode 100644 src/index.ts delete mode 100644 src/rpc/command.js create mode 100644 src/rpc/command.ts create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c5c221a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +insert_final_newline = true + +[src/*] +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false + +[*.yml] +insert_final_newline = true +trim_trailing_whitespace = false + +[*.txt] +insert_final_newline = true +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 25c8fdb..15ac82e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -package-lock.json \ No newline at end of file +package-lock.json +.test diff --git a/dist/lib/constants.js b/dist/lib/constants.js new file mode 100644 index 0000000..8432415 --- /dev/null +++ b/dist/lib/constants.js @@ -0,0 +1,180 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isMessage = exports.isCommand = exports.isEvent = exports.isPlatform = exports.RPC_COMMANDS = exports.RPC_EVENTS = exports.PLATFORM_TYPES = exports.OPCODES = void 0; +var OPCODES; +(function (OPCODES) { + OPCODES[OPCODES["HANDSHAKE"] = 0] = "HANDSHAKE"; + OPCODES[OPCODES["FRAME"] = 1] = "FRAME"; + OPCODES[OPCODES["CLOSE"] = 2] = "CLOSE"; + OPCODES[OPCODES["HELLO"] = 3] = "HELLO"; +})(OPCODES = exports.OPCODES || (exports.OPCODES = {})); +; +exports.PLATFORM_TYPES = [ + "desktop", + "mobile" +]; +exports.RPC_EVENTS = [ + "CURRENT_USER_UPDATE", + "GUILD_STATUS", + "GUILD_CREATE", + "CHANNEL_CREATE", + "RELATIONSHIP_UPDATE", + "VOICE_CHANNEL_SELECT", + "VOICE_STATE_CREATE", + "VOICE_STATE_DELETE", + "VOICE_STATE_UPDATE", + "VOICE_SETTINGS_UPDATE", + "VOICE_SETTINGS_UPDATE_2", + "VOICE_CONNECTION_STATUS", + "SPEAKING_START", + "SPEAKING_STOP", + "GAME_JOIN", + "GAME_SPECTATE", + "ACTIVITY_JOIN", + "ACTIVITY_JOIN_REQUEST", + "ACTIVITY_SPECTATE", + "ACTIVITY_INVITE", + "ACTIVITY_PIP_MODE_UPDATE", + "THERMAL_STATE_UPDATE", + "ORIENTATION_UPDATE", + "NOTIFICATION_CREATE", + "MESSAGE_CREATE", + "MESSAGE_UPDATE", + "MESSAGE_DELETE", + "LOBBY_DELETE", + "LOBBY_UPDATE", + "LOBBY_MEMBER_CONNECT", + "LOBBY_MEMBER_DISCONNECT", + "LOBBY_MEMBER_UPDATE", + "LOBBY_MESSAGE", + "OVERLAY", + "OVERLAY_UPDATE", + "ENTITLEMENT_CREATE", + "ENTITLEMENT_DELETE", + "USER_ACHIEVEMENT_UPDATE", + "VOICE_CHANNEL_EFFECT_SEND", + "VOICE_CHANNEL_EFFECT_RECENT_EMOJI", + "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE", + "READY", + "ERROR" +]; +exports.RPC_COMMANDS = [ + "DISPATCH", + "SET_CONFIG", + "AUTHORIZE", + "AUTHENTICATE", + "GET_GUILD", + "GET_GUILDS", + "GET_CHANNEL", + "GET_CHANNELS", + "CREATE_CHANNEL_INVITE", + "GET_RELATIONSHIPS", + "GET_USER", + "SUBSCRIBE", + "UNSUBSCRIBE", + "SET_USER_VOICE_SETTINGS", + "SET_USER_VOICE_SETTINGS_2", + "SELECT_VOICE_CHANNEL", + "GET_SELECTED_VOICE_CHANNEL", + "SELECT_TEXT_CHANNEL", + "GET_VOICE_SETTINGS", + "SET_VOICE_SETTINGS_2", + "SET_VOICE_SETTINGS", + "SET_ACTIVITY", + "SEND_ACTIVITY_JOIN_INVITE", + "CLOSE_ACTIVITY_JOIN_REQUEST", + "ACTIVITY_INVITE_USER", + "ACCEPT_ACTIVITY_INVITE", + "OPEN_INVITE_DIALOG", + "INVITE_BROWSER", + "DEEP_LINK", + "CONNECTIONS_CALLBACK", + "BILLING_POPUP_BRIDGE_CALLBACK", + "BRAINTREE_POPUP_BRIDGE_CALLBACK", + "GIFT_CODE_BROWSER", + "GUILD_TEMPLATE_BROWSER", + "OVERLAY", + "BROWSER_HANDOFF", + "SET_CERTIFIED_DEVICES", + "GET_IMAGE", + "CREATE_LOBBY", + "UPDATE_LOBBY", + "DELETE_LOBBY", + "UPDATE_LOBBY_MEMBER", + "CONNECT_TO_LOBBY", + "DISCONNECT_FROM_LOBBY", + "SEND_TO_LOBBY", + "SEARCH_LOBBIES", + "CONNECT_TO_LOBBY_VOICE", + "DISCONNECT_FROM_LOBBY_VOICE", + "SET_OVERLAY_LOCKED", + "OPEN_OVERLAY_ACTIVITY_INVITE", + "OPEN_OVERLAY_GUILD_INVITE", + "OPEN_OVERLAY_VOICE_SETTINGS", + "VALIDATE_APPLICATION", + "GET_ENTITLEMENT_TICKET", + "GET_APPLICATION_TICKET", + "START_PURCHASE", + "START_PREMIUM_PURCHASE", + "GET_SKUS", + "GET_ENTITLEMENTS", + "GET_NETWORKING_CONFIG", + "NETWORKING_SYSTEM_METRICS", + "NETWORKING_PEER_METRICS", + "NETWORKING_CREATE_TOKEN", + "SET_USER_ACHIEVEMENT", + "GET_USER_ACHIEVEMENTS", + "USER_SETTINGS_GET_LOCALE", + "GET_ACTIVITY_JOIN_TICKET", + "SEND_GENERIC_EVENT", + "SEND_ANALYTICS_EVENT", + "OPEN_EXTERNAL_LINK", + "CAPTURE_LOG", + "ENCOURAGE_HW_ACCELERATION", + "SET_ORIENTATION_LOCK_STATE" +]; +function isPlatform(platform) { + if (!platform) + return false; + if (typeof platform !== "string") + return false; + if (!exports.PLATFORM_TYPES.join(" ").includes(platform)) + return false; + else + return true; +} +exports.isPlatform = isPlatform; +function isEvent(event) { + if (!event) + return false; + if (typeof event !== "string") + return false; + if (!exports.RPC_EVENTS.join(" ").includes(event)) + return false; + else + return true; +} +exports.isEvent = isEvent; +function isCommand(command) { + if (!command) + return false; + if (typeof command !== "string") + return false; + if (!exports.RPC_COMMANDS.join(" ").includes(command)) + return false; + else + return true; +} +exports.isCommand = isCommand; +function isMessage(message) { + if (!message) + return false; + if (typeof message !== "object") + return false; + if (!("cmd" in message && "nonce" in message && "data" in message)) + return false; + else + return true; +} +exports.isMessage = isMessage; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/lib/constants.js.map b/dist/lib/constants.js.map new file mode 100644 index 0000000..01c1c74 --- /dev/null +++ b/dist/lib/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/index.js b/dist/lib/index.js new file mode 100644 index 0000000..1eeda07 --- /dev/null +++ b/dist/lib/index.js @@ -0,0 +1,161 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = require("tslib"); +const eventemitter3_1 = tslib_1.__importDefault(require("eventemitter3")); +const uuid_1 = tslib_1.__importDefault(require("uuid")); +const constants_1 = require("./constants"); +const command_1 = tslib_1.__importDefault(require("./rpc/command")); +class ActivitySDK extends eventemitter3_1.default { + constructor(appId) { + super(); + this.appId = appId; + this.rpcTarget = window.parent.opener || window.parent; + this.rpcOrigin = document.referrer || "*"; + this.commands = new command_1.default(this.appId, this.sendCommand); + this.commandCache = new Map(); + window.addEventListener('message', this._handleMessage); + const params = new URLSearchParams(window.location.search); + const frameParam = params.get('frame_id'); + const instanceParam = params.get('instance_id'); + const platformParam = params.get('platform'); + if ((0, constants_1.isPlatform)(platformParam)) + this.platform = platformParam; + else + throw new Error("Unsupported or invalid platform."); + const channelParam = params.get('channel_id'); + const guildParam = params.get('guild_id'); + if (!frameParam) + throw new Error("Window missing frame_id"); + else + this.frameId = frameParam; + if (!instanceParam) + throw new Error("Window missing instance_id"); + else + this.instanceId = instanceParam; + if (!channelParam) + throw new Error("Window missing frame_id"); + else + this.channelId = channelParam; + if (!guildParam) + throw new Error("Window missing frame_id"); + else + this.guildId = guildParam; + this._init(); + } + _handleMessage(message) { + const opcode = message.data[0]; + const payload = message.data[1]; + if (!(opcode in constants_1.OPCODES)) + throw new Error("Invalid opcode recieved: " + opcode); + switch (constants_1.OPCODES[opcode]) { + case "HANDSHAKE": + return; + case "FRAME": + this._handleFrame(payload); + return; + case "CLOSE": + return; + case "HELLO": + return; + default: + throw "Unable to handle opcode: " + constants_1.OPCODES[opcode]; + } + } + _postRawPayload(opcode, payload) { + this.rpcTarget.postMessage([opcode, payload], this.rpcOrigin); + } + sendCommand(type, args) { + if (!(0, constants_1.isCommand)(type)) + throw new Error("Invalid RPC Command: " + type); + const nonce = uuid_1.default.v4(); + this._postRawPayload(constants_1.OPCODES.FRAME, { nonce, cmd: type, args }); + return new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); + } + postPayload(type, payload) { + if (!(0, constants_1.isCommand)(type)) + throw new Error("Invalid RPC Command: " + type); + const nonce = uuid_1.default.v4(); + this.rpcTarget.postMessage([ + constants_1.OPCODES.FRAME, + Object.assign({ nonce, cmd: type }, payload), + ], this.rpcOrigin); + return new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); + } + // Command Handling + _resolveCommand(nonce, data) { + const response = this.commandCache.get(nonce); + if (response) + response.resolve(data); + this.commandCache.delete(nonce); + } + _rejectCommand(nonce, data) { + const response = this.commandCache.get(nonce); + if (response) + response.reject(data); + this.commandCache.delete(nonce); + } + _handleFrame(resp) { + if (resp.cmd === "DISPATCH") { + this.emit(`${resp.evt}`, resp.data); + } + if (!resp.nonce) + throw new Error("Missing nonce"); + if (resp.evt === "ERROR") + this._rejectCommand(resp.nonce, resp.data); + else + this._resolveCommand(resp.nonce, resp.data); + } + ; + // Handling RPC Events + subscribe(type, reciever) { + return tslib_1.__awaiter(this, void 0, void 0, function* () { + if (!(0, constants_1.isEvent)(type)) + throw new Error("Invalid RPC Event: " + type); + yield this.postPayload("SUBSCRIBE", { + evt: type + }); + return this.on(type, reciever); + }); + } + unsubscribe(type, reciever) { + return tslib_1.__awaiter(this, void 0, void 0, function* () { + if (!(0, constants_1.isEvent)(type)) + throw new Error("Invalid RPC Event: " + type); + yield this.postPayload("UNSUBSCRIBE", { + evt: type + }); + return this.off(type, reciever); + }); + } + // Helpers + getPlatform() { + return this.platform; + } + getChannelId() { + return this.channelId; + } + getGuildId() { + return this.guildId; + } + // Internal startup logic + _kill() { + window.removeEventListener('message', this._handleMessage); + this.removeAllListeners(); + } + _handshake() { + this.rpcTarget.postMessage([ + constants_1.OPCODES.HANDSHAKE, + { + v: 1, + encoding: 'json', + client_id: this.appId, + frame_id: this.frameId, + }, + ], this.rpcOrigin); + } + _init() { + this._handshake(); + } +} +exports.default = ActivitySDK; +//# sourceMappingURL=index.js.map diff --git a/dist/lib/index.js.map b/dist/lib/index.js.map new file mode 100644 index 0000000..f075dab --- /dev/null +++ b/dist/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/rpc/command.js b/dist/lib/rpc/command.js new file mode 100644 index 0000000..6bbae2b --- /dev/null +++ b/dist/lib/rpc/command.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class ActivitySDKCommands { + constructor(appId, sendCommandHandler) { + this.appId = appId; + this.sendCommandHandler = sendCommandHandler; + } + authorize(scopes, rpcToken) { + return this.sendCommandHandler("AUTHORIZE", { + client_id: this.appId, rpc_token: rpcToken, scopes + }); + } + authenticate(accessToken) { + return this.sendCommandHandler("AUTHENTICATE", { + access_token: accessToken + }); + } + setConfig(data) { + return this.sendCommandHandler("SET_CONFIG", data); + } + getSelectedVoiceChannel() { + return this.sendCommandHandler("GET_SELECTED_VOICE_CHANNEL", { nonce: null }); + } + setActivity(pid, activity) { + return this.sendCommandHandler("SET_ACTIVITY", { + pid, activity + }); + } + getGuild() { + return this.sendCommandHandler("GET_GUILD", { nonce: null }); + } + getGuilds() { + return this.sendCommandHandler("GET_GUILDS", { nonce: null }); + } + getChannel() { + return this.sendCommandHandler("GET_CHANNEL", { nonce: null }); + } + getChannels() { + return this.sendCommandHandler("GET_CHANNELS", { nonce: null }); + } + createChannelInvite() { + return this.sendCommandHandler("CREATE_CHANNEL_INVITE", { nonce: null }); + } + openInviteDialog() { + return this.sendCommandHandler("OPEN_INVITE_DIALOG", { nonce: null }); + } + encourageHardwareAcceleration() { + return this.sendCommandHandler("ENCOURAGE_HW_ACCELERATION", { nonce: null }); + } + getUserLocale() { + return this.sendCommandHandler("USER_SETTINGS_GET_LOCALE", { nonce: null }); + } +} +exports.default = ActivitySDKCommands; +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/dist/lib/rpc/command.js.map b/dist/lib/rpc/command.js.map new file mode 100644 index 0000000..2e828f7 --- /dev/null +++ b/dist/lib/rpc/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/rpc/command.ts"],"names":[],"mappings":";;AAEA,MAAM,mBAAmB;IAEvB,YAAoB,KAAa,EAAS,kBAA4D;QAAlF,UAAK,GAAL,KAAK,CAAQ;QAAS,uBAAkB,GAAlB,kBAAkB,CAA0C;IAAG,CAAC;IAE1G,SAAS,CAAC,MAAgB,EAAE,QAAgB;QAC1C,OAAO,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE;YAC1C,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM;SACnD,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,WAAmB;QAC9B,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE;YAC7C,YAAY,EAAE,WAAW;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,IAAgB;QACxB,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,uBAAuB;QACrB,OAAO,IAAI,CAAC,kBAAkB,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,WAAW,CAAC,GAAW,EAAE,QAAgB;QACvC,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE;YAC7C,GAAG,EAAE,QAAQ;SACd,CAAC,CAAC;IACL,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,mBAAmB;QACjB,OAAO,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,kBAAkB,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,6BAA6B;QAC3B,OAAO,IAAI,CAAC,kBAAkB,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,kBAAkB,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,CAAC;CACF;AAED,kBAAe,mBAAmB,CAAC"} \ No newline at end of file diff --git a/dist/types/constants.d.ts b/dist/types/constants.d.ts new file mode 100644 index 0000000..d0c7771 --- /dev/null +++ b/dist/types/constants.d.ts @@ -0,0 +1,24 @@ +export declare enum OPCODES { + "HANDSHAKE" = 0, + "FRAME" = 1, + "CLOSE" = 2, + "HELLO" = 3 +} +export declare const PLATFORM_TYPES: readonly ["desktop", "mobile"]; +export declare const RPC_EVENTS: readonly ["CURRENT_USER_UPDATE", "GUILD_STATUS", "GUILD_CREATE", "CHANNEL_CREATE", "RELATIONSHIP_UPDATE", "VOICE_CHANNEL_SELECT", "VOICE_STATE_CREATE", "VOICE_STATE_DELETE", "VOICE_STATE_UPDATE", "VOICE_SETTINGS_UPDATE", "VOICE_SETTINGS_UPDATE_2", "VOICE_CONNECTION_STATUS", "SPEAKING_START", "SPEAKING_STOP", "GAME_JOIN", "GAME_SPECTATE", "ACTIVITY_JOIN", "ACTIVITY_JOIN_REQUEST", "ACTIVITY_SPECTATE", "ACTIVITY_INVITE", "ACTIVITY_PIP_MODE_UPDATE", "THERMAL_STATE_UPDATE", "ORIENTATION_UPDATE", "NOTIFICATION_CREATE", "MESSAGE_CREATE", "MESSAGE_UPDATE", "MESSAGE_DELETE", "LOBBY_DELETE", "LOBBY_UPDATE", "LOBBY_MEMBER_CONNECT", "LOBBY_MEMBER_DISCONNECT", "LOBBY_MEMBER_UPDATE", "LOBBY_MESSAGE", "OVERLAY", "OVERLAY_UPDATE", "ENTITLEMENT_CREATE", "ENTITLEMENT_DELETE", "USER_ACHIEVEMENT_UPDATE", "VOICE_CHANNEL_EFFECT_SEND", "VOICE_CHANNEL_EFFECT_RECENT_EMOJI", "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE", "READY", "ERROR"]; +export declare const RPC_COMMANDS: readonly ["DISPATCH", "SET_CONFIG", "AUTHORIZE", "AUTHENTICATE", "GET_GUILD", "GET_GUILDS", "GET_CHANNEL", "GET_CHANNELS", "CREATE_CHANNEL_INVITE", "GET_RELATIONSHIPS", "GET_USER", "SUBSCRIBE", "UNSUBSCRIBE", "SET_USER_VOICE_SETTINGS", "SET_USER_VOICE_SETTINGS_2", "SELECT_VOICE_CHANNEL", "GET_SELECTED_VOICE_CHANNEL", "SELECT_TEXT_CHANNEL", "GET_VOICE_SETTINGS", "SET_VOICE_SETTINGS_2", "SET_VOICE_SETTINGS", "SET_ACTIVITY", "SEND_ACTIVITY_JOIN_INVITE", "CLOSE_ACTIVITY_JOIN_REQUEST", "ACTIVITY_INVITE_USER", "ACCEPT_ACTIVITY_INVITE", "OPEN_INVITE_DIALOG", "INVITE_BROWSER", "DEEP_LINK", "CONNECTIONS_CALLBACK", "BILLING_POPUP_BRIDGE_CALLBACK", "BRAINTREE_POPUP_BRIDGE_CALLBACK", "GIFT_CODE_BROWSER", "GUILD_TEMPLATE_BROWSER", "OVERLAY", "BROWSER_HANDOFF", "SET_CERTIFIED_DEVICES", "GET_IMAGE", "CREATE_LOBBY", "UPDATE_LOBBY", "DELETE_LOBBY", "UPDATE_LOBBY_MEMBER", "CONNECT_TO_LOBBY", "DISCONNECT_FROM_LOBBY", "SEND_TO_LOBBY", "SEARCH_LOBBIES", "CONNECT_TO_LOBBY_VOICE", "DISCONNECT_FROM_LOBBY_VOICE", "SET_OVERLAY_LOCKED", "OPEN_OVERLAY_ACTIVITY_INVITE", "OPEN_OVERLAY_GUILD_INVITE", "OPEN_OVERLAY_VOICE_SETTINGS", "VALIDATE_APPLICATION", "GET_ENTITLEMENT_TICKET", "GET_APPLICATION_TICKET", "START_PURCHASE", "START_PREMIUM_PURCHASE", "GET_SKUS", "GET_ENTITLEMENTS", "GET_NETWORKING_CONFIG", "NETWORKING_SYSTEM_METRICS", "NETWORKING_PEER_METRICS", "NETWORKING_CREATE_TOKEN", "SET_USER_ACHIEVEMENT", "GET_USER_ACHIEVEMENTS", "USER_SETTINGS_GET_LOCALE", "GET_ACTIVITY_JOIN_TICKET", "SEND_GENERIC_EVENT", "SEND_ANALYTICS_EVENT", "OPEN_EXTERNAL_LINK", "CAPTURE_LOG", "ENCOURAGE_HW_ACCELERATION", "SET_ORIENTATION_LOCK_STATE"]; +export type PlatformType = (typeof PLATFORM_TYPES)[number]; +export type RPCEvent = (typeof RPC_EVENTS)[number]; +export type RPCCommand = (typeof RPC_COMMANDS)[number]; +export interface RPCPayload { + cmd: RPCCommand; + nonce: string | null; + data?: object; + args?: object; + evt?: string; +} +export declare function isPlatform(platform: unknown): platform is PlatformType; +export declare function isEvent(event: unknown): event is RPCEvent; +export declare function isCommand(command: unknown): command is RPCCommand; +export declare function isMessage(message: unknown): message is RPCPayload; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/types/constants.d.ts.map b/dist/types/constants.d.ts.map new file mode 100644 index 0000000..0def50f --- /dev/null +++ b/dist/types/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,oBAAY,OAAO;IACjB,WAAW,IAAA;IACX,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED,eAAO,MAAM,cAAc,gCAGjB,CAAC;AAEX,eAAO,MAAM,UAAU,+5BA4Cb,CAAC;AAEX,eAAO,MAAM,YAAY,0lDA0Ef,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC3D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,IAAI,YAAY,CAKtE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAKzD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,UAAU,CAKjE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,UAAU,CAKjE"} \ No newline at end of file diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts new file mode 100644 index 0000000..c03787d --- /dev/null +++ b/dist/types/index.d.ts @@ -0,0 +1,36 @@ +import EventEmitter from 'eventemitter3'; +import { OPCODES, PlatformType, RPCCommand, RPCEvent, RPCPayload } from './constants'; +import ActivitySDKCommands from './rpc/command'; +declare class ActivitySDK extends EventEmitter { + appId: string; + rpcTarget: Window; + rpcOrigin: string; + commands: ActivitySDKCommands; + commandCache: Map void; + reject: (reason?: any) => void; + }>; + frameId: string; + instanceId: string; + platform: PlatformType; + channelId: string; + guildId: string; + constructor(appId: string); + _handleMessage(message: MessageEvent): void; + _postRawPayload(opcode: OPCODES, payload: RPCPayload): void; + sendCommand(type: RPCCommand, args: Required): Promise; + postPayload(type: RPCCommand, payload: Omit): Promise; + _resolveCommand(nonce: string, data: Required): void; + _rejectCommand(nonce: string, data: Required): void; + _handleFrame(resp: RPCPayload): void; + subscribe(type: RPCEvent, reciever: () => void): Promise; + unsubscribe(type: RPCEvent, reciever: () => void): Promise; + getPlatform(): "desktop" | "mobile"; + getChannelId(): string; + getGuildId(): string; + _kill(): void; + _handshake(): void; + _init(): void; +} +export default ActivitySDK; +//# sourceMappingURL=index.d.ts.map diff --git a/dist/types/index.d.ts.map b/dist/types/index.d.ts.map new file mode 100644 index 0000000..8082517 --- /dev/null +++ b/dist/types/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAGzC,OAAO,EACL,OAAO,EACP,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,UAAU,EACX,MAAM,aAAa,CAAC;AACrB,OAAO,mBAAmB,MAAM,eAAe,CAAC;AAEhD,cAAM,WAAY,SAAQ,YAAY;IAejB,KAAK,EAAE,MAAM;IAbhC,SAAS,EAAE,MAAM,CAAyC;IAC1D,SAAS,EAAE,MAAM,CAA4B;IAE7C,QAAQ,sBAA0D;IAClE,YAAY;yBAAsC,OAAO,KAAK,IAAI;0BAAoB,GAAG,KAAK,IAAI;OAAM;IAExG,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;gBAGG,KAAK,EAAE,MAAM;IAuBhC,cAAc,CAAC,OAAO,EAAE,YAAY;IAmBpC,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU;IAIpD,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IASjE,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,KAAK,CAAC;IAaxE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAOjE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAOhE,YAAY,CAAC,IAAI,EAAE,UAAU;IAWvB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,IAAI;IAU9C,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,IAAI;IAWtD,WAAW;IAIX,YAAY;IAIZ,UAAU;IAKV,KAAK;IAKL,UAAU;IAYV,KAAK;CAIN;AAED,eAAe,WAAW,CAAC"} \ No newline at end of file diff --git a/dist/types/rpc/command.d.ts b/dist/types/rpc/command.d.ts new file mode 100644 index 0000000..d51cbd8 --- /dev/null +++ b/dist/types/rpc/command.d.ts @@ -0,0 +1,21 @@ +import { RPCCommand, RPCPayload } from "../constants"; +declare class ActivitySDKCommands { + private appId; + sendCommandHandler: (type: RPCCommand, args: object) => void; + constructor(appId: string, sendCommandHandler: (type: RPCCommand, args: object) => void); + authorize(scopes: string[], rpcToken: string): void; + authenticate(accessToken: string): void; + setConfig(data: RPCPayload): void; + getSelectedVoiceChannel(): void; + setActivity(pid: number, activity: object): void; + getGuild(): void; + getGuilds(): void; + getChannel(): void; + getChannels(): void; + createChannelInvite(): void; + openInviteDialog(): void; + encourageHardwareAcceleration(): void; + getUserLocale(): void; +} +export default ActivitySDKCommands; +//# sourceMappingURL=command.d.ts.map \ No newline at end of file diff --git a/dist/types/rpc/command.d.ts.map b/dist/types/rpc/command.d.ts.map new file mode 100644 index 0000000..cbcb17b --- /dev/null +++ b/dist/types/rpc/command.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/rpc/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,cAAM,mBAAmB;IAEX,OAAO,CAAC,KAAK;IAAiB,kBAAkB,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI;gBAAlF,KAAK,EAAE,MAAM,EAAS,kBAAkB,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI;IAEtG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM;IAM5C,YAAY,CAAC,WAAW,EAAE,MAAM;IAMhC,SAAS,CAAC,IAAI,EAAE,UAAU;IAI1B,uBAAuB;IAIvB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAMzC,QAAQ;IAIR,SAAS;IAIT,UAAU;IAIV,WAAW;IAIX,mBAAmB;IAInB,gBAAgB;IAIhB,6BAA6B;IAI7B,aAAa;CAGd;AAED,eAAe,mBAAmB,CAAC"} \ No newline at end of file diff --git a/package.json b/package.json index 545b2fd..ad613ad 100644 --- a/package.json +++ b/package.json @@ -2,16 +2,25 @@ "name": "activitysdk", "version": "0.1.1", "description": "Unofficial SDK to communicate between the discord client and an embedded activity.", - "main": "src/index.js", + "main": "./dist/lib/index.js", + "types": "./dist/types/index.d.ts", "dependencies": { "eventemitter3": "^5.0.0", + "tslib": "^2.5.0", "uuid": "^9.0.0" }, - "devDependencies": {}, + "devDependencies": { + "@types/uuid": "^9.0.1", + "typescript": "^4.9.5" + }, "repository": { "type": "git", "url": "git+https://github.com/justsomederpystuff/activitysdk.git" }, + "files": [ + "./dist", "./src", + "./README.md", "./LICENSE" + ], "author": "big nutty", "license": "MIT", "bugs": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..501a700 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,42 @@ +lockfileVersion: 5.4 + +specifiers: + '@types/uuid': ^9.0.1 + eventemitter3: ^5.0.0 + tslib: ^2.5.0 + typescript: ^4.9.5 + uuid: ^9.0.0 + +dependencies: + eventemitter3: 5.0.0 + tslib: 2.5.0 + uuid: 9.0.0 + +devDependencies: + '@types/uuid': 9.0.1 + typescript: 4.9.5 + +packages: + + /@types/uuid/9.0.1: + resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==} + dev: true + + /eventemitter3/5.0.0: + resolution: {integrity: sha512-riuVbElZZNXLeLEoprfNYoDSwTBRR44X3mnhdI1YcnENpWTCsTTVZ2zFuqQcpoyqPQIUXdiPEU0ECAq0KQRaHg==} + dev: false + + /tslib/2.5.0: + resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + dev: false + + /typescript/4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /uuid/9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + dev: false diff --git a/src/constants.js b/src/constants.ts similarity index 54% rename from src/constants.js rename to src/constants.ts index 355f004..138f27f 100644 --- a/src/constants.js +++ b/src/constants.ts @@ -1,20 +1,16 @@ -module.exports.OPCODES = Object.freeze({ - 0: "HANDSHAKE", - 1: "FRAME", - 2: "CLOSE", - 3: "HELLO", - "HANDSHAKE": 0, - "FRAME": 1, - "CLOSE": 2, - "HELLO": 3 -}) +export enum OPCODES { //* same as the object you had. + "HANDSHAKE", + "FRAME", + "CLOSE", + "HELLO", +}; -module.exports.PLATFORM_TYPES = Object.freeze([ +export const PLATFORM_TYPES = [ "desktop", "mobile" -]) +] as const; -module.exports.RPC_EVENTS = Object.freeze([ +export const RPC_EVENTS = [ "CURRENT_USER_UPDATE", "GUILD_STATUS", "GUILD_CREATE", @@ -58,9 +54,9 @@ module.exports.RPC_EVENTS = Object.freeze([ "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE", "READY", "ERROR" -]) +] as const; -module.exports.RPC_COMMANDS = Object.freeze([ +export const RPC_COMMANDS = [ "DISPATCH", "SET_CONFIG", "AUTHORIZE", @@ -134,4 +130,62 @@ module.exports.RPC_COMMANDS = Object.freeze([ "CAPTURE_LOG", "ENCOURAGE_HW_ACCELERATION", "SET_ORIENTATION_LOCK_STATE" -]) \ No newline at end of file +] as const; + +//* pov: ottelino hates typescript +//* (something) as const -> infers the type as the literal of this object -> makes it readonly. +//* type LiteralType = "yeepee" | 0 | false +//* type NormalType = string | number | boolean +//* +//? how 2 use: +//? indexing an array type with "number" tells typescript to get the union of all elements in the array. easy to use because autocompletion/intellisense. +//? interface -> object type but compiles faster. +//? you can have functions that work as a type guard + +export type PlatformType = (typeof PLATFORM_TYPES)[number]; +export type RPCEvent = (typeof RPC_EVENTS)[number]; +export type RPCCommand = (typeof RPC_COMMANDS)[number]; +export interface RPCPayload { + cmd: RPCCommand; + evt: RPCEvent | null; + nonce: string | null; + data?: DataObj; // sometimes its type of string for some reason. + args?: object; // object -> { [key: string]: any } +} + +export function malformedRequestError() { + new Error("Malformed request from client."); +} + +export function malformedResponseError() { + new Error("Malformed response from server."); +} + +export function isPlatform(platform: unknown): platform is PlatformType { + if (!platform) return false; + if (typeof platform !== "string") return false; + if (!PLATFORM_TYPES.join(" ").includes(platform)) return false; + else return true; +} + +export function isEvent(event: unknown): event is RPCEvent { + if (!event) return false; + if (typeof event !== "string") return false; + if (!RPC_EVENTS.join(" ").includes(event)) return false; + else return true; +} + +export function isCommand(command: unknown): command is RPCCommand { + if (!command) return false; + if (typeof command !== "string") return false; + if (!RPC_COMMANDS.join(" ").includes(command)) return false; + else return true; +} + +export function isMessage(message: unknown): message is RPCPayload { + if (!message) return false; + if (typeof message !== "object") return false; + if (!("cmd" in message && "nonce" in message && "data" in message)) return false; + else return true; +} + diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 86dbd9c..0000000 --- a/src/index.js +++ /dev/null @@ -1,172 +0,0 @@ -const EventEmitter = require('eventemitter3'); -const uuid = require('uuid') - -const { OPCODES, RPC_COMMANDS, RPC_EVENTS } = require('./constants'); -const ActivitySDKCommands = require('./rpc/command'); - -class ActivitySDK extends EventEmitter { - constructor(appId) { - super(); - this.appId = appId; - - this.rpcTarget = window.parent - if(!this.rpcTarget) this.rpcTarget = window.parent.opener - - this.rpcOrigin = document.referrer - if(!this.rpcOrigin) this.rpcOrigin = "*" - - this.commandCache = new Map(); - - this._handleMessage = (message) => { - let d = message.data; - const opcode = d[0]; - if(!OPCODES[opcode]) throw "Invalid opcode recieved: " + opcode - switch(OPCODES[opcode]){ - case "HANDSHAKE": - return; - case "FRAME": - this._handleFrame(d[1]); - return; - case "CLOSE": - return; - case "HELLO": - return; - default: - throw "Unable to handle opcode: " + OPCODES[opcode] - } - } - - this._sendCommand = (type, data) => { - if(!RPC_COMMANDS.includes(type)) throw "Invalid RPC Command: " + type - const nonce = uuid.v4(); - - this.rpcTarget.postMessage([ - OPCODES.FRAME, - Object.assign(Object.assign({ - cmd: type - }, { args: data }), { nonce }), - ], this.rpcOrigin); - - const response = new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); - return response; - } - - this._sendCommandRaw = (type, data) => { - if(!RPC_COMMANDS.includes(type)) throw "Invalid RPC Command: " + type - const nonce = uuid.v4(); - - this.rpcTarget.postMessage([ - OPCODES.FRAME, - Object.assign(Object.assign({ - cmd: type - }, data), { nonce }), - ], this.rpcOrigin); - - const response = new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); - return response; - } - - this.commands = new ActivitySDKCommands(this._sendCommand); - - window.addEventListener('message', this._handleMessage); - this._init(); - } - - // Command Handling - _resolveCommand(nonce, data){ - const response = this.commandCache.get(nonce) - if(response) response.resolve(data) - - this.commandCache.delete(nonce) - } - - _rejectCommand(nonce){ - const response = this.commandCache.get(nonce) - if(response) response.reject(data) - - this.commandCache.delete(nonce) - } - - _handleFrame(data){ - if(data.cmd == "DISPATCH") return this.emit(data.evt, data.data); - - if(!data.nonce) throw "Missing nonce" - if(data.cmd == "ERROR"){ - this._rejectCommand(data.nonce, data.data) - } - - this._resolveCommand(data.nonce, data.data) - }; - - // Handling RPC Events - async subscribe(event, reciever){ - if(!RPC_EVENTS.includes(event)) throw "Invalid RPC Event: " + type - - await this._sendCommandRaw("SUBSCRIBE", { - evt: event - }) - - return this.on(event, reciever) - } - - async unsubscribe(event, reciever){ - if(!RPC_EVENTS.includes(event)) throw "Invalid RPC Event: " + type - - await this._sendCommandRaw("UNSUBSCRIBE", { - evt: event - }) - - return this.off(event, reciever) - } - - // Helpers - getPlatform(){ - return this.platform - } - - getChannelId(){ - return this.channelId - } - - getGuildId(){ - return this.guildId - } - - // Internal startup logic - _kill() { - window.removeEventListener('message', this._handleMessage); - this.removeAllListeners(); - } - - _handshake(){ - this.rpcTarget.postMessage([ - OPCODES.HANDSHAKE, - { - v: 1, - encoding: 'json', - client_id: this.appId, - frame_id: this.frameId, - }, - ], this.rpcOrigin); - } - - _init(){ - const params = new URLSearchParams(window.location.search); - this.frameId = params.get('frame_id') - this.instanceId = params.get('instance_id') - this.platform = params.get('platform') - - this.channelId = params.get('channel_id') - this.guildId = params.get('guild_id') - - if(!this.frameId) throw "Window missing frame_id" - if(!this.instanceId) throw "Window missing instance_id" - if(!this.platform) throw "Window missing platform" - if(!["desktop", "mobile"].includes(this.platform)) throw "Invalid platform" - - this._handshake(); - } - -} - -module.exports = ActivitySDK; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..f0d7ac9 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,194 @@ +import EventEmitter from 'eventemitter3'; +import { v4 as uuid } from 'uuid'; + +import { + OPCODES, + PlatformType, isPlatform, + RPCCommand, isCommand, + RPCEvent, isEvent, + RPCPayload, +} from './constants'; +import ActivitySDKCommands from './rpc/command'; + +class ActivitySDK extends EventEmitter { + + isReady: boolean = false; + rpcTarget: Window = window.parent.opener || window.parent; + rpcOrigin: string = document.referrer || "*"; + + commands = new ActivitySDKCommands(this.appId, this.appSecret, this.sendCommand.bind(this)); + commandCache = new Map["data"]) => void; reject: (reason?: any) => void }>(); + + frameId: string; + instanceId: string; + platform: PlatformType; + channelId: string; + guildId: string; + + + constructor(public appId: string, public appSecret: string) { + super(); + + window.addEventListener('message', this._handleMessage.bind(this)); + + const params = new URLSearchParams(window.location.search); + const frameParam = params.get('frame_id'); + const instanceParam = params.get('instance_id'); + const platformParam = params.get('platform'); + if (isPlatform(platformParam)) this.platform = platformParam; + else throw new Error("Unsupported or invalid platform."); + + const channelParam = params.get('channel_id'); + const guildParam = params.get('guild_id'); + + if (!frameParam) throw new Error("Window missing frame_id"); else this.frameId = frameParam; + if (!instanceParam) throw new Error("Window missing instance_id"); else this.instanceId = instanceParam; + if (!channelParam) throw new Error("Window missing frame_id"); else this.channelId = channelParam; + if (!guildParam) throw new Error("Window missing frame_id"); else this.guildId = guildParam; + + this._init(); + } + + private _handleMessage(message: MessageEvent) { + if (typeof message.data !== "object") { + console.log("Recieved message: ", message.data); + return; + } + const opcode = message.data[0]; + const payload = message.data[1]; + if (!(opcode in OPCODES)) throw new Error("Invalid opcode recieved: " + opcode); + console.log("Recieved opcode " + OPCODES[opcode], message); + switch (OPCODES[opcode]) { + case "HANDSHAKE": + return; + case "FRAME": + this._handleFrame(payload); + return; + case "CLOSE": + return; + case "HELLO": + this.isReady = true; + return; + default: + throw "Unable to handle opcode: " + OPCODES[opcode]; + } + } + + private _postRawPayload(opcode: OPCODES, payload: RPCPayload) { + console.log("post " + OPCODES[opcode] + " with", payload); + this.rpcTarget.postMessage([opcode, payload], this.rpcOrigin); + } + + sendCommand(type: RPCCommand, args: Required["args"]>): Promise["data"]> { + if (!isCommand(type)) throw new Error("Invalid RPC Command: " + type); + const nonce = uuid(); + + this._postRawPayload(OPCODES.FRAME, { + nonce, args, + cmd: type, evt: null, + }); + + return new Promise["data"]>((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })) as Promise["data"]>; + } + + postPayload(payload: Omit, "nonce">) { + if (!isCommand(payload.cmd)) throw new Error("Invalid RPC Command: " + payload.cmd); + if (payload.evt) if (!isEvent(payload.evt)) throw new Error("Invalid RPC Event: " + payload.evt); + const nonce = uuid(); + + this.rpcTarget.postMessage([ + OPCODES.FRAME, + { nonce, ...payload }, + ], this.rpcOrigin); + + return new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); + } + + // Command Handling + private _resolveCommand(nonce: string, data: Required["data"]>) { + const response = this.commandCache.get(nonce); + if (response) response.resolve(data); + + this.commandCache.delete(nonce); + } + + private _rejectCommand(nonce: string, data: Required["data"]>) { + const response = this.commandCache.get(nonce); + if (response) response.reject(data); + + this.commandCache.delete(nonce); + } + + private _handleFrame(resp: RPCPayload) { + console.log("Handle frame (response) -> ", resp); + if (resp.cmd === "DISPATCH") { + if (!isEvent(resp.evt)) throw new Error("Undefined event in DISPATCH command."); + this.emit(resp.evt, resp.data); + return; + } + + if (!resp.nonce) throw new Error("Missing nonce"); + if (resp.evt === "ERROR") this._rejectCommand(resp.nonce, resp.data); + else this._resolveCommand(resp.nonce, resp.data); + }; + + // Handling RPC Events + async subscribe(type: RPCEvent, reciever: () => void) { + if (!isEvent(type)) throw new Error("Invalid RPC Event: " + type); + + await this.postPayload({ + evt: type, cmd: "SUBSCRIBE" + }); + + return this.on(type, reciever); + } + + async unsubscribe(type: RPCEvent, reciever: () => void) { + if (!isEvent(type)) throw new Error("Invalid RPC Event: " + type); + + await this.postPayload({ + evt: type, cmd: "UNSUBSCRIBE" + }); + + return this.off(type, reciever); + } + + // Helpers + getPlatform() { + return this.platform; + } + + getChannelId() { + return this.channelId; + } + + getGuildId() { + return this.guildId; + } + + // Internal startup logic + kill() { + window.removeEventListener('message', this._handleMessage.bind(this)); + this.removeAllListeners(); + } + + private _handshake() { + this.isReady = false; + this.rpcTarget.postMessage([ + OPCODES.HANDSHAKE, + { + v: 1, + encoding: 'json', + client_id: this.appId, + frame_id: this.frameId, + }, + ], this.rpcOrigin); + } + + private _init() { + this._handshake(); + } + +} + +export default ActivitySDK; diff --git a/src/rpc/command.js b/src/rpc/command.js deleted file mode 100644 index e0f2aa5..0000000 --- a/src/rpc/command.js +++ /dev/null @@ -1,61 +0,0 @@ -// RPC Commands - -class ActivitySDKCommands { - constructor(send) { - this.sendCommand = send; - } - - authorize(data){ - return this.sendCommand("AUTHORIZE", data); - } - - authenticate(data){ - return this.sendCommand("AUTHENTICATE", data); - } - - setConfig(data){ - return this.sendCommand("SET_CONFIG", data); - } - - getSelectedVoiceChannel(){ - return this.sendCommand("GET_SELECTED_VOICE_CHANNEL", {}); - } - - setActivity(data){ - return this.sendCommand("SET_ACTIVITY", data); - } - - getGuild(){ - return this.sendCommand("GET_GUILD", {}); - } - - getGuilds(){ - return this.sendCommand("GET_GUILDS", {}); - } - - getChannel(){ - return this.sendCommand("GET_CHANNEL", {}); - } - - getChannels(){ - return this.sendCommand("GET_CHANNELS", {}); - } - - createChannelInvite(){ - return this.sendCommand("CREATE_CHANNEL_INVITE", {}); - } - - openInviteDialog(){ - return this.sendCommand("OPEN_INVITE_DIALOG", {}) - } - - encourageHardwareAcceleration(){ - return this.sendCommand("ENCOURAGE_HW_ACCELERATION", {}) - } - - getUserLocale(){ - return this.sendCommand("USER_SETTINGS_GET_LOCALE", {}) - } -} - -module.exports = ActivitySDKCommands \ No newline at end of file diff --git a/src/rpc/command.ts b/src/rpc/command.ts new file mode 100644 index 0000000..4e6af52 --- /dev/null +++ b/src/rpc/command.ts @@ -0,0 +1,147 @@ +import { RPCCommand, RPCPayload, malformedRequestError, malformedResponseError } from "../constants"; + +export default class ActivitySDKCommands { + + constructor(private appId: string, private appSecret: string, public sendCommandHandler: (type: RPCCommand, args: Required["args"]>) => Promise["data"]>) {} + + async authenticate(scopes: string[], rpcToken?: string) { + const authorizeRes = await this.sendCommandHandler("AUTHORIZE", { + client_id: this.appId, rpc_token: rpcToken, scopes + }); + if (!authorizeRes || !("code" in authorizeRes) || typeof authorizeRes.code !== "string") throw malformedResponseError(); + const authenticateRes: object = await (await fetch("https://discord.com/api/oauth2/token", { + method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ + grant_type: "authorization_code", + code: authorizeRes.code, + client_id: this.appId, + client_secret: this.appSecret + }) + })).json(); + if (!authenticateRes || "error" in authenticateRes || !("access_token" in authenticateRes) || typeof authenticateRes.access_token !== "string") throw malformedRequestError(); + return await this.sendCommandHandler("AUTHENTICATE", { + access_token: authenticateRes.access_token + }); + } + + async setConfig(data: object) { + return await this.sendCommandHandler("SET_CONFIG", data); + } + + async getSelectedVoiceChannel() { + return await this.sendCommandHandler("GET_SELECTED_VOICE_CHANNEL", {}); + } + + async setActivity(pid: number, activity: object) { + return await this.sendCommandHandler("SET_ACTIVITY", { + pid, activity + }); + } + + async getGuild(guildId: string, timeout?: number) { + return await this.sendCommandHandler("GET_GUILD", { guild_id: guildId, timeout }); + } + + async getGuilds() { + return await this.sendCommandHandler("GET_GUILDS", {}); + } + + async getChannel(channelId: string) { + return await this.sendCommandHandler("GET_CHANNEL", { channel_id: channelId }); + } + + async getChannels(guildId: string) { + return await this.sendCommandHandler("GET_CHANNELS", { guild_id: guildId }); + } + + async createChannelInvite() { + return await this.sendCommandHandler("CREATE_CHANNEL_INVITE", {}); + } + + async openInviteDialog() { + return await this.sendCommandHandler("OPEN_INVITE_DIALOG", {}); + } + + async encourageHardwareAcceleration() { + return await this.sendCommandHandler("ENCOURAGE_HW_ACCELERATION", {}); + } + + async getUserLocale() { + return await this.sendCommandHandler("USER_SETTINGS_GET_LOCALE", {}); + } +} + +export interface AuthorizeResponseData { + code: string; +} +export interface AuthenticateResponseData { + scopes: string[]; + expires: string; + user: { + id: string; + username: string; + discriminator: string; + avatar?: string; + bot?: boolean; + system?: boolean; + mfa_enabled?: boolean; + banner?: string; + accent_color?: number; + locale?: string; + verified?: boolean; + email?: string; + flags?: number; + premium_type?: number; + public_flags?: number; + } + application: { + id: string; + name: string; + description: string; + icon: string; + rpc_origins: string[]; + } +} +export interface GetGuildsResponseData { + guilds: object[]; +} +export interface GetGuildResponseData { + id: string; + name: string; + icon_url: string; + members: { + user: AuthenticateResponseData["user"]; + nick?: string; + avatar?: string; + roles: string[]; + joined_at: string; + premium_since?: string; + deaf: boolean; + mute: boolean; + flags: number; + pending?: string; + permissions?: string[]; + communication_disabled_until?: string; + }[]; + vanity_url_code?: string; +} +export interface GetChannelResponseData { + id: string; + name?: string; + type: number; + guild_id?: string; + position?: number; + nsfw?: boolean; + topic?: string; + last_message_id?: number; + user_limit?: number; + recipients?: AuthenticateResponseData["user"][]; + parent_id?: string; + permissions?: string; + flags?: number; + bitrate?: number; + voice_states: object[]; //* https://discord.com/developers/docs/resources/voice#voice-state-object + messages: object[]; //* https://discord.com/developers/docs/resources/channel#message-object +} +export interface GetChannelsResponseData { + channels: GetChannelResponseData[]; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e710f71 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compilerOptions": { + "alwaysStrict": true, + "target": "ES2015", + "module": "CommonJS", + "sourceMap": true, + "outDir": "./dist/lib/", + "declarationDir": "./dist/types/", + "declaration": true, + "declarationMap": true, + "rootDir": "./src", + "lib": [ + "ES2015", + "DOM" + ], + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "pretty": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "strictPropertyInitialization": true, + "newLine": "lf", + "importHelpers": true + }, + "buildOptions": {}, + "exclude": [ + "node_modules", + "**/*.spec.ts" + ], + "include": [ + "src/**/*.ts" + ] +} From 63f71383e0a2ed4abb9a6069911bd73f360cd8a2 Mon Sep 17 00:00:00 2001 From: UserUNP <39243708+UserUNP@users.noreply.github.com> Date: Sun, 12 Mar 2023 08:02:06 +0100 Subject: [PATCH 2/5] updated gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 15ac82e..35ac33e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules package-lock.json .test +dist From 022869a34c4fc4d68bf2b9b05ae0ec277c925fca Mon Sep 17 00:00:00 2001 From: oven <39243708+UserUNP@users.noreply.github.com> Date: Sun, 12 Mar 2023 16:03:06 +0100 Subject: [PATCH 3/5] Delete dist directory i forgor --- dist/lib/constants.js | 180 -------------------------------- dist/lib/constants.js.map | 1 - dist/lib/index.js | 161 ---------------------------- dist/lib/index.js.map | 1 - dist/lib/rpc/command.js | 55 ---------- dist/lib/rpc/command.js.map | 1 - dist/types/constants.d.ts | 24 ----- dist/types/constants.d.ts.map | 1 - dist/types/index.d.ts | 36 ------- dist/types/index.d.ts.map | 1 - dist/types/rpc/command.d.ts | 21 ---- dist/types/rpc/command.d.ts.map | 1 - 12 files changed, 483 deletions(-) delete mode 100644 dist/lib/constants.js delete mode 100644 dist/lib/constants.js.map delete mode 100644 dist/lib/index.js delete mode 100644 dist/lib/index.js.map delete mode 100644 dist/lib/rpc/command.js delete mode 100644 dist/lib/rpc/command.js.map delete mode 100644 dist/types/constants.d.ts delete mode 100644 dist/types/constants.d.ts.map delete mode 100644 dist/types/index.d.ts delete mode 100644 dist/types/index.d.ts.map delete mode 100644 dist/types/rpc/command.d.ts delete mode 100644 dist/types/rpc/command.d.ts.map diff --git a/dist/lib/constants.js b/dist/lib/constants.js deleted file mode 100644 index 8432415..0000000 --- a/dist/lib/constants.js +++ /dev/null @@ -1,180 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.isMessage = exports.isCommand = exports.isEvent = exports.isPlatform = exports.RPC_COMMANDS = exports.RPC_EVENTS = exports.PLATFORM_TYPES = exports.OPCODES = void 0; -var OPCODES; -(function (OPCODES) { - OPCODES[OPCODES["HANDSHAKE"] = 0] = "HANDSHAKE"; - OPCODES[OPCODES["FRAME"] = 1] = "FRAME"; - OPCODES[OPCODES["CLOSE"] = 2] = "CLOSE"; - OPCODES[OPCODES["HELLO"] = 3] = "HELLO"; -})(OPCODES = exports.OPCODES || (exports.OPCODES = {})); -; -exports.PLATFORM_TYPES = [ - "desktop", - "mobile" -]; -exports.RPC_EVENTS = [ - "CURRENT_USER_UPDATE", - "GUILD_STATUS", - "GUILD_CREATE", - "CHANNEL_CREATE", - "RELATIONSHIP_UPDATE", - "VOICE_CHANNEL_SELECT", - "VOICE_STATE_CREATE", - "VOICE_STATE_DELETE", - "VOICE_STATE_UPDATE", - "VOICE_SETTINGS_UPDATE", - "VOICE_SETTINGS_UPDATE_2", - "VOICE_CONNECTION_STATUS", - "SPEAKING_START", - "SPEAKING_STOP", - "GAME_JOIN", - "GAME_SPECTATE", - "ACTIVITY_JOIN", - "ACTIVITY_JOIN_REQUEST", - "ACTIVITY_SPECTATE", - "ACTIVITY_INVITE", - "ACTIVITY_PIP_MODE_UPDATE", - "THERMAL_STATE_UPDATE", - "ORIENTATION_UPDATE", - "NOTIFICATION_CREATE", - "MESSAGE_CREATE", - "MESSAGE_UPDATE", - "MESSAGE_DELETE", - "LOBBY_DELETE", - "LOBBY_UPDATE", - "LOBBY_MEMBER_CONNECT", - "LOBBY_MEMBER_DISCONNECT", - "LOBBY_MEMBER_UPDATE", - "LOBBY_MESSAGE", - "OVERLAY", - "OVERLAY_UPDATE", - "ENTITLEMENT_CREATE", - "ENTITLEMENT_DELETE", - "USER_ACHIEVEMENT_UPDATE", - "VOICE_CHANNEL_EFFECT_SEND", - "VOICE_CHANNEL_EFFECT_RECENT_EMOJI", - "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE", - "READY", - "ERROR" -]; -exports.RPC_COMMANDS = [ - "DISPATCH", - "SET_CONFIG", - "AUTHORIZE", - "AUTHENTICATE", - "GET_GUILD", - "GET_GUILDS", - "GET_CHANNEL", - "GET_CHANNELS", - "CREATE_CHANNEL_INVITE", - "GET_RELATIONSHIPS", - "GET_USER", - "SUBSCRIBE", - "UNSUBSCRIBE", - "SET_USER_VOICE_SETTINGS", - "SET_USER_VOICE_SETTINGS_2", - "SELECT_VOICE_CHANNEL", - "GET_SELECTED_VOICE_CHANNEL", - "SELECT_TEXT_CHANNEL", - "GET_VOICE_SETTINGS", - "SET_VOICE_SETTINGS_2", - "SET_VOICE_SETTINGS", - "SET_ACTIVITY", - "SEND_ACTIVITY_JOIN_INVITE", - "CLOSE_ACTIVITY_JOIN_REQUEST", - "ACTIVITY_INVITE_USER", - "ACCEPT_ACTIVITY_INVITE", - "OPEN_INVITE_DIALOG", - "INVITE_BROWSER", - "DEEP_LINK", - "CONNECTIONS_CALLBACK", - "BILLING_POPUP_BRIDGE_CALLBACK", - "BRAINTREE_POPUP_BRIDGE_CALLBACK", - "GIFT_CODE_BROWSER", - "GUILD_TEMPLATE_BROWSER", - "OVERLAY", - "BROWSER_HANDOFF", - "SET_CERTIFIED_DEVICES", - "GET_IMAGE", - "CREATE_LOBBY", - "UPDATE_LOBBY", - "DELETE_LOBBY", - "UPDATE_LOBBY_MEMBER", - "CONNECT_TO_LOBBY", - "DISCONNECT_FROM_LOBBY", - "SEND_TO_LOBBY", - "SEARCH_LOBBIES", - "CONNECT_TO_LOBBY_VOICE", - "DISCONNECT_FROM_LOBBY_VOICE", - "SET_OVERLAY_LOCKED", - "OPEN_OVERLAY_ACTIVITY_INVITE", - "OPEN_OVERLAY_GUILD_INVITE", - "OPEN_OVERLAY_VOICE_SETTINGS", - "VALIDATE_APPLICATION", - "GET_ENTITLEMENT_TICKET", - "GET_APPLICATION_TICKET", - "START_PURCHASE", - "START_PREMIUM_PURCHASE", - "GET_SKUS", - "GET_ENTITLEMENTS", - "GET_NETWORKING_CONFIG", - "NETWORKING_SYSTEM_METRICS", - "NETWORKING_PEER_METRICS", - "NETWORKING_CREATE_TOKEN", - "SET_USER_ACHIEVEMENT", - "GET_USER_ACHIEVEMENTS", - "USER_SETTINGS_GET_LOCALE", - "GET_ACTIVITY_JOIN_TICKET", - "SEND_GENERIC_EVENT", - "SEND_ANALYTICS_EVENT", - "OPEN_EXTERNAL_LINK", - "CAPTURE_LOG", - "ENCOURAGE_HW_ACCELERATION", - "SET_ORIENTATION_LOCK_STATE" -]; -function isPlatform(platform) { - if (!platform) - return false; - if (typeof platform !== "string") - return false; - if (!exports.PLATFORM_TYPES.join(" ").includes(platform)) - return false; - else - return true; -} -exports.isPlatform = isPlatform; -function isEvent(event) { - if (!event) - return false; - if (typeof event !== "string") - return false; - if (!exports.RPC_EVENTS.join(" ").includes(event)) - return false; - else - return true; -} -exports.isEvent = isEvent; -function isCommand(command) { - if (!command) - return false; - if (typeof command !== "string") - return false; - if (!exports.RPC_COMMANDS.join(" ").includes(command)) - return false; - else - return true; -} -exports.isCommand = isCommand; -function isMessage(message) { - if (!message) - return false; - if (typeof message !== "object") - return false; - if (!("cmd" in message && "nonce" in message && "data" in message)) - return false; - else - return true; -} -exports.isMessage = isMessage; -//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/lib/constants.js.map b/dist/lib/constants.js.map deleted file mode 100644 index 01c1c74..0000000 --- a/dist/lib/constants.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/index.js b/dist/lib/index.js deleted file mode 100644 index 1eeda07..0000000 --- a/dist/lib/index.js +++ /dev/null @@ -1,161 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const tslib_1 = require("tslib"); -const eventemitter3_1 = tslib_1.__importDefault(require("eventemitter3")); -const uuid_1 = tslib_1.__importDefault(require("uuid")); -const constants_1 = require("./constants"); -const command_1 = tslib_1.__importDefault(require("./rpc/command")); -class ActivitySDK extends eventemitter3_1.default { - constructor(appId) { - super(); - this.appId = appId; - this.rpcTarget = window.parent.opener || window.parent; - this.rpcOrigin = document.referrer || "*"; - this.commands = new command_1.default(this.appId, this.sendCommand); - this.commandCache = new Map(); - window.addEventListener('message', this._handleMessage); - const params = new URLSearchParams(window.location.search); - const frameParam = params.get('frame_id'); - const instanceParam = params.get('instance_id'); - const platformParam = params.get('platform'); - if ((0, constants_1.isPlatform)(platformParam)) - this.platform = platformParam; - else - throw new Error("Unsupported or invalid platform."); - const channelParam = params.get('channel_id'); - const guildParam = params.get('guild_id'); - if (!frameParam) - throw new Error("Window missing frame_id"); - else - this.frameId = frameParam; - if (!instanceParam) - throw new Error("Window missing instance_id"); - else - this.instanceId = instanceParam; - if (!channelParam) - throw new Error("Window missing frame_id"); - else - this.channelId = channelParam; - if (!guildParam) - throw new Error("Window missing frame_id"); - else - this.guildId = guildParam; - this._init(); - } - _handleMessage(message) { - const opcode = message.data[0]; - const payload = message.data[1]; - if (!(opcode in constants_1.OPCODES)) - throw new Error("Invalid opcode recieved: " + opcode); - switch (constants_1.OPCODES[opcode]) { - case "HANDSHAKE": - return; - case "FRAME": - this._handleFrame(payload); - return; - case "CLOSE": - return; - case "HELLO": - return; - default: - throw "Unable to handle opcode: " + constants_1.OPCODES[opcode]; - } - } - _postRawPayload(opcode, payload) { - this.rpcTarget.postMessage([opcode, payload], this.rpcOrigin); - } - sendCommand(type, args) { - if (!(0, constants_1.isCommand)(type)) - throw new Error("Invalid RPC Command: " + type); - const nonce = uuid_1.default.v4(); - this._postRawPayload(constants_1.OPCODES.FRAME, { nonce, cmd: type, args }); - return new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); - } - postPayload(type, payload) { - if (!(0, constants_1.isCommand)(type)) - throw new Error("Invalid RPC Command: " + type); - const nonce = uuid_1.default.v4(); - this.rpcTarget.postMessage([ - constants_1.OPCODES.FRAME, - Object.assign({ nonce, cmd: type }, payload), - ], this.rpcOrigin); - return new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); - } - // Command Handling - _resolveCommand(nonce, data) { - const response = this.commandCache.get(nonce); - if (response) - response.resolve(data); - this.commandCache.delete(nonce); - } - _rejectCommand(nonce, data) { - const response = this.commandCache.get(nonce); - if (response) - response.reject(data); - this.commandCache.delete(nonce); - } - _handleFrame(resp) { - if (resp.cmd === "DISPATCH") { - this.emit(`${resp.evt}`, resp.data); - } - if (!resp.nonce) - throw new Error("Missing nonce"); - if (resp.evt === "ERROR") - this._rejectCommand(resp.nonce, resp.data); - else - this._resolveCommand(resp.nonce, resp.data); - } - ; - // Handling RPC Events - subscribe(type, reciever) { - return tslib_1.__awaiter(this, void 0, void 0, function* () { - if (!(0, constants_1.isEvent)(type)) - throw new Error("Invalid RPC Event: " + type); - yield this.postPayload("SUBSCRIBE", { - evt: type - }); - return this.on(type, reciever); - }); - } - unsubscribe(type, reciever) { - return tslib_1.__awaiter(this, void 0, void 0, function* () { - if (!(0, constants_1.isEvent)(type)) - throw new Error("Invalid RPC Event: " + type); - yield this.postPayload("UNSUBSCRIBE", { - evt: type - }); - return this.off(type, reciever); - }); - } - // Helpers - getPlatform() { - return this.platform; - } - getChannelId() { - return this.channelId; - } - getGuildId() { - return this.guildId; - } - // Internal startup logic - _kill() { - window.removeEventListener('message', this._handleMessage); - this.removeAllListeners(); - } - _handshake() { - this.rpcTarget.postMessage([ - constants_1.OPCODES.HANDSHAKE, - { - v: 1, - encoding: 'json', - client_id: this.appId, - frame_id: this.frameId, - }, - ], this.rpcOrigin); - } - _init() { - this._handshake(); - } -} -exports.default = ActivitySDK; -//# sourceMappingURL=index.js.map diff --git a/dist/lib/index.js.map b/dist/lib/index.js.map deleted file mode 100644 index f075dab..0000000 --- a/dist/lib/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/rpc/command.js b/dist/lib/rpc/command.js deleted file mode 100644 index 6bbae2b..0000000 --- a/dist/lib/rpc/command.js +++ /dev/null @@ -1,55 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ActivitySDKCommands { - constructor(appId, sendCommandHandler) { - this.appId = appId; - this.sendCommandHandler = sendCommandHandler; - } - authorize(scopes, rpcToken) { - return this.sendCommandHandler("AUTHORIZE", { - client_id: this.appId, rpc_token: rpcToken, scopes - }); - } - authenticate(accessToken) { - return this.sendCommandHandler("AUTHENTICATE", { - access_token: accessToken - }); - } - setConfig(data) { - return this.sendCommandHandler("SET_CONFIG", data); - } - getSelectedVoiceChannel() { - return this.sendCommandHandler("GET_SELECTED_VOICE_CHANNEL", { nonce: null }); - } - setActivity(pid, activity) { - return this.sendCommandHandler("SET_ACTIVITY", { - pid, activity - }); - } - getGuild() { - return this.sendCommandHandler("GET_GUILD", { nonce: null }); - } - getGuilds() { - return this.sendCommandHandler("GET_GUILDS", { nonce: null }); - } - getChannel() { - return this.sendCommandHandler("GET_CHANNEL", { nonce: null }); - } - getChannels() { - return this.sendCommandHandler("GET_CHANNELS", { nonce: null }); - } - createChannelInvite() { - return this.sendCommandHandler("CREATE_CHANNEL_INVITE", { nonce: null }); - } - openInviteDialog() { - return this.sendCommandHandler("OPEN_INVITE_DIALOG", { nonce: null }); - } - encourageHardwareAcceleration() { - return this.sendCommandHandler("ENCOURAGE_HW_ACCELERATION", { nonce: null }); - } - getUserLocale() { - return this.sendCommandHandler("USER_SETTINGS_GET_LOCALE", { nonce: null }); - } -} -exports.default = ActivitySDKCommands; -//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/dist/lib/rpc/command.js.map b/dist/lib/rpc/command.js.map deleted file mode 100644 index 2e828f7..0000000 --- a/dist/lib/rpc/command.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/rpc/command.ts"],"names":[],"mappings":";;AAEA,MAAM,mBAAmB;IAEvB,YAAoB,KAAa,EAAS,kBAA4D;QAAlF,UAAK,GAAL,KAAK,CAAQ;QAAS,uBAAkB,GAAlB,kBAAkB,CAA0C;IAAG,CAAC;IAE1G,SAAS,CAAC,MAAgB,EAAE,QAAgB;QAC1C,OAAO,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE;YAC1C,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM;SACnD,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,WAAmB;QAC9B,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE;YAC7C,YAAY,EAAE,WAAW;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,IAAgB;QACxB,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,uBAAuB;QACrB,OAAO,IAAI,CAAC,kBAAkB,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,WAAW,CAAC,GAAW,EAAE,QAAgB;QACvC,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE;YAC7C,GAAG,EAAE,QAAQ;SACd,CAAC,CAAC;IACL,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,mBAAmB;QACjB,OAAO,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,kBAAkB,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,6BAA6B;QAC3B,OAAO,IAAI,CAAC,kBAAkB,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,kBAAkB,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,CAAC;CACF;AAED,kBAAe,mBAAmB,CAAC"} \ No newline at end of file diff --git a/dist/types/constants.d.ts b/dist/types/constants.d.ts deleted file mode 100644 index d0c7771..0000000 --- a/dist/types/constants.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -export declare enum OPCODES { - "HANDSHAKE" = 0, - "FRAME" = 1, - "CLOSE" = 2, - "HELLO" = 3 -} -export declare const PLATFORM_TYPES: readonly ["desktop", "mobile"]; -export declare const RPC_EVENTS: readonly ["CURRENT_USER_UPDATE", "GUILD_STATUS", "GUILD_CREATE", "CHANNEL_CREATE", "RELATIONSHIP_UPDATE", "VOICE_CHANNEL_SELECT", "VOICE_STATE_CREATE", "VOICE_STATE_DELETE", "VOICE_STATE_UPDATE", "VOICE_SETTINGS_UPDATE", "VOICE_SETTINGS_UPDATE_2", "VOICE_CONNECTION_STATUS", "SPEAKING_START", "SPEAKING_STOP", "GAME_JOIN", "GAME_SPECTATE", "ACTIVITY_JOIN", "ACTIVITY_JOIN_REQUEST", "ACTIVITY_SPECTATE", "ACTIVITY_INVITE", "ACTIVITY_PIP_MODE_UPDATE", "THERMAL_STATE_UPDATE", "ORIENTATION_UPDATE", "NOTIFICATION_CREATE", "MESSAGE_CREATE", "MESSAGE_UPDATE", "MESSAGE_DELETE", "LOBBY_DELETE", "LOBBY_UPDATE", "LOBBY_MEMBER_CONNECT", "LOBBY_MEMBER_DISCONNECT", "LOBBY_MEMBER_UPDATE", "LOBBY_MESSAGE", "OVERLAY", "OVERLAY_UPDATE", "ENTITLEMENT_CREATE", "ENTITLEMENT_DELETE", "USER_ACHIEVEMENT_UPDATE", "VOICE_CHANNEL_EFFECT_SEND", "VOICE_CHANNEL_EFFECT_RECENT_EMOJI", "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE", "READY", "ERROR"]; -export declare const RPC_COMMANDS: readonly ["DISPATCH", "SET_CONFIG", "AUTHORIZE", "AUTHENTICATE", "GET_GUILD", "GET_GUILDS", "GET_CHANNEL", "GET_CHANNELS", "CREATE_CHANNEL_INVITE", "GET_RELATIONSHIPS", "GET_USER", "SUBSCRIBE", "UNSUBSCRIBE", "SET_USER_VOICE_SETTINGS", "SET_USER_VOICE_SETTINGS_2", "SELECT_VOICE_CHANNEL", "GET_SELECTED_VOICE_CHANNEL", "SELECT_TEXT_CHANNEL", "GET_VOICE_SETTINGS", "SET_VOICE_SETTINGS_2", "SET_VOICE_SETTINGS", "SET_ACTIVITY", "SEND_ACTIVITY_JOIN_INVITE", "CLOSE_ACTIVITY_JOIN_REQUEST", "ACTIVITY_INVITE_USER", "ACCEPT_ACTIVITY_INVITE", "OPEN_INVITE_DIALOG", "INVITE_BROWSER", "DEEP_LINK", "CONNECTIONS_CALLBACK", "BILLING_POPUP_BRIDGE_CALLBACK", "BRAINTREE_POPUP_BRIDGE_CALLBACK", "GIFT_CODE_BROWSER", "GUILD_TEMPLATE_BROWSER", "OVERLAY", "BROWSER_HANDOFF", "SET_CERTIFIED_DEVICES", "GET_IMAGE", "CREATE_LOBBY", "UPDATE_LOBBY", "DELETE_LOBBY", "UPDATE_LOBBY_MEMBER", "CONNECT_TO_LOBBY", "DISCONNECT_FROM_LOBBY", "SEND_TO_LOBBY", "SEARCH_LOBBIES", "CONNECT_TO_LOBBY_VOICE", "DISCONNECT_FROM_LOBBY_VOICE", "SET_OVERLAY_LOCKED", "OPEN_OVERLAY_ACTIVITY_INVITE", "OPEN_OVERLAY_GUILD_INVITE", "OPEN_OVERLAY_VOICE_SETTINGS", "VALIDATE_APPLICATION", "GET_ENTITLEMENT_TICKET", "GET_APPLICATION_TICKET", "START_PURCHASE", "START_PREMIUM_PURCHASE", "GET_SKUS", "GET_ENTITLEMENTS", "GET_NETWORKING_CONFIG", "NETWORKING_SYSTEM_METRICS", "NETWORKING_PEER_METRICS", "NETWORKING_CREATE_TOKEN", "SET_USER_ACHIEVEMENT", "GET_USER_ACHIEVEMENTS", "USER_SETTINGS_GET_LOCALE", "GET_ACTIVITY_JOIN_TICKET", "SEND_GENERIC_EVENT", "SEND_ANALYTICS_EVENT", "OPEN_EXTERNAL_LINK", "CAPTURE_LOG", "ENCOURAGE_HW_ACCELERATION", "SET_ORIENTATION_LOCK_STATE"]; -export type PlatformType = (typeof PLATFORM_TYPES)[number]; -export type RPCEvent = (typeof RPC_EVENTS)[number]; -export type RPCCommand = (typeof RPC_COMMANDS)[number]; -export interface RPCPayload { - cmd: RPCCommand; - nonce: string | null; - data?: object; - args?: object; - evt?: string; -} -export declare function isPlatform(platform: unknown): platform is PlatformType; -export declare function isEvent(event: unknown): event is RPCEvent; -export declare function isCommand(command: unknown): command is RPCCommand; -export declare function isMessage(message: unknown): message is RPCPayload; -//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/types/constants.d.ts.map b/dist/types/constants.d.ts.map deleted file mode 100644 index 0def50f..0000000 --- a/dist/types/constants.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,oBAAY,OAAO;IACjB,WAAW,IAAA;IACX,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED,eAAO,MAAM,cAAc,gCAGjB,CAAC;AAEX,eAAO,MAAM,UAAU,+5BA4Cb,CAAC;AAEX,eAAO,MAAM,YAAY,0lDA0Ef,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC3D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,IAAI,YAAY,CAKtE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAKzD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,UAAU,CAKjE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,UAAU,CAKjE"} \ No newline at end of file diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts deleted file mode 100644 index c03787d..0000000 --- a/dist/types/index.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import EventEmitter from 'eventemitter3'; -import { OPCODES, PlatformType, RPCCommand, RPCEvent, RPCPayload } from './constants'; -import ActivitySDKCommands from './rpc/command'; -declare class ActivitySDK extends EventEmitter { - appId: string; - rpcTarget: Window; - rpcOrigin: string; - commands: ActivitySDKCommands; - commandCache: Map void; - reject: (reason?: any) => void; - }>; - frameId: string; - instanceId: string; - platform: PlatformType; - channelId: string; - guildId: string; - constructor(appId: string); - _handleMessage(message: MessageEvent): void; - _postRawPayload(opcode: OPCODES, payload: RPCPayload): void; - sendCommand(type: RPCCommand, args: Required): Promise; - postPayload(type: RPCCommand, payload: Omit): Promise; - _resolveCommand(nonce: string, data: Required): void; - _rejectCommand(nonce: string, data: Required): void; - _handleFrame(resp: RPCPayload): void; - subscribe(type: RPCEvent, reciever: () => void): Promise; - unsubscribe(type: RPCEvent, reciever: () => void): Promise; - getPlatform(): "desktop" | "mobile"; - getChannelId(): string; - getGuildId(): string; - _kill(): void; - _handshake(): void; - _init(): void; -} -export default ActivitySDK; -//# sourceMappingURL=index.d.ts.map diff --git a/dist/types/index.d.ts.map b/dist/types/index.d.ts.map deleted file mode 100644 index 8082517..0000000 --- a/dist/types/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAGzC,OAAO,EACL,OAAO,EACP,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,UAAU,EACX,MAAM,aAAa,CAAC;AACrB,OAAO,mBAAmB,MAAM,eAAe,CAAC;AAEhD,cAAM,WAAY,SAAQ,YAAY;IAejB,KAAK,EAAE,MAAM;IAbhC,SAAS,EAAE,MAAM,CAAyC;IAC1D,SAAS,EAAE,MAAM,CAA4B;IAE7C,QAAQ,sBAA0D;IAClE,YAAY;yBAAsC,OAAO,KAAK,IAAI;0BAAoB,GAAG,KAAK,IAAI;OAAM;IAExG,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;gBAGG,KAAK,EAAE,MAAM;IAuBhC,cAAc,CAAC,OAAO,EAAE,YAAY;IAmBpC,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU;IAIpD,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IASjE,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,KAAK,CAAC;IAaxE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAOjE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAOhE,YAAY,CAAC,IAAI,EAAE,UAAU;IAWvB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,IAAI;IAU9C,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,IAAI;IAWtD,WAAW;IAIX,YAAY;IAIZ,UAAU;IAKV,KAAK;IAKL,UAAU;IAYV,KAAK;CAIN;AAED,eAAe,WAAW,CAAC"} \ No newline at end of file diff --git a/dist/types/rpc/command.d.ts b/dist/types/rpc/command.d.ts deleted file mode 100644 index d51cbd8..0000000 --- a/dist/types/rpc/command.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { RPCCommand, RPCPayload } from "../constants"; -declare class ActivitySDKCommands { - private appId; - sendCommandHandler: (type: RPCCommand, args: object) => void; - constructor(appId: string, sendCommandHandler: (type: RPCCommand, args: object) => void); - authorize(scopes: string[], rpcToken: string): void; - authenticate(accessToken: string): void; - setConfig(data: RPCPayload): void; - getSelectedVoiceChannel(): void; - setActivity(pid: number, activity: object): void; - getGuild(): void; - getGuilds(): void; - getChannel(): void; - getChannels(): void; - createChannelInvite(): void; - openInviteDialog(): void; - encourageHardwareAcceleration(): void; - getUserLocale(): void; -} -export default ActivitySDKCommands; -//# sourceMappingURL=command.d.ts.map \ No newline at end of file diff --git a/dist/types/rpc/command.d.ts.map b/dist/types/rpc/command.d.ts.map deleted file mode 100644 index cbcb17b..0000000 --- a/dist/types/rpc/command.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/rpc/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,cAAM,mBAAmB;IAEX,OAAO,CAAC,KAAK;IAAiB,kBAAkB,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI;gBAAlF,KAAK,EAAE,MAAM,EAAS,kBAAkB,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI;IAEtG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM;IAM5C,YAAY,CAAC,WAAW,EAAE,MAAM;IAMhC,SAAS,CAAC,IAAI,EAAE,UAAU;IAI1B,uBAAuB;IAIvB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAMzC,QAAQ;IAIR,SAAS;IAIT,UAAU;IAIV,WAAW;IAIX,mBAAmB;IAInB,gBAAgB;IAIhB,6BAA6B;IAI7B,aAAa;CAGd;AAED,eAAe,mBAAmB,CAAC"} \ No newline at end of file From 9c6725609654f9e5b3dea56140edeccf4043f062 Mon Sep 17 00:00:00 2001 From: UserUNP <39243708+UserUNP@users.noreply.github.com> Date: Wed, 15 Mar 2023 11:18:06 +0100 Subject: [PATCH 4/5] package.json --- .gitignore | 2 +- package.json | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 35ac33e..0a52377 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ node_modules package-lock.json .test -dist +dist/ diff --git a/package.json b/package.json index ad613ad..4a518dc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "activitysdk", + "name": "activitysdk-ts", "version": "0.1.1", - "description": "Unofficial SDK to communicate between the discord client and an embedded activity.", + "description": "Typescript fork of activitysdk.", "main": "./dist/lib/index.js", "types": "./dist/types/index.d.ts", "dependencies": { @@ -15,7 +15,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/justsomederpystuff/activitysdk.git" + "url": "git+https://github.com/UserUNP/activitysdk-ts.git" }, "files": [ "./dist", "./src", @@ -24,7 +24,7 @@ "author": "big nutty", "license": "MIT", "bugs": { - "url": "https://github.com/justsomederpystuff/activitysdk/issues" + "url": "https://github.com/UserUNP/activitysdk-ts/issues" }, - "homepage": "https://github.com/justsomederpystuff/activitysdk#readme" + "homepage": "https://github.com/UserUNP/activitysdk-ts" } From c0955c683c7c30eeb0060e0759752e70b09459bc Mon Sep 17 00:00:00 2001 From: oven <39243708+UserUNP@users.noreply.github.com> Date: Thu, 16 Mar 2023 19:48:21 +0100 Subject: [PATCH 5/5] v0.2.1 merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * use console.debug * v0.2.0 - bug fixes - all (""useful"") rpc commands implemented - added close method to close the Embedded Activity * README example * 🔖 v0.2.0 * typescript & bug fixes * updated gitignore * package.json * use console.debug * README example * 🔖 v0.2.0 * 📄 copyright * ♻️ rebase merge conflict * ♻️✨ authorize & authenticate commands * package.json (v0.2.1) --------- Co-authored-by: derpystuff <3515180-derpystuff@users.noreply.gitlab.com> --- LICENSE | 1 + README.md | 36 ++++++++++++++++-- package.json | 4 +- src/constants.ts | 51 ++++++++++++++++++------- src/index.ts | 93 ++++++++++++++++++++++++++++++++-------------- src/rpc/command.ts | 75 ++++++++++++++++++++++++++----------- tsconfig.json | 4 +- 7 files changed, 195 insertions(+), 69 deletions(-) diff --git a/LICENSE b/LICENSE index 40e6ab7..d7636eb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT License Copyright (c) 2023 big nutty +Copyright (c) 2023 UserUNP Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 03019aa..6ab3f78 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,36 @@ # ActivitySDK -![npm](https://img.shields.io/npm/v/activitysdk) -Unofficial SDK to communicate between the discord client and an embedded activity. +| activitysdk-ts | activitysdk | +| :------------: | :---------: | +| ![npm](https://img.shields.io/npm/v/activitysdk-ts) | ![npm](https://img.shields.io/npm/v/activitysdk) | -Documentation and examples will be coming soon. \ No newline at end of file +Typescript fork of [activitysdk](http://npmjs.org/activitysdk). + +**Example usage:** +_you **need** to use a bundler such as [vite](https://vitejs.dev/) or [webpack](https://webpack.js.org/) or any bundler you like._ +```js +import ActivitySDK from "activitysdk-ts"; + +const sdk = new ActivitySDK("app id"); + +sdk.on("READY", async () => { + let user; + try { + user = (await sdk.commands.authenticate("app secret", ["identify"])).user; + } catch (e) { + console.error("could not authorize/authenticate"); + return; + } + + const info = document.createElement("div"); + info.style.backgroundColor = "gray"; + info.style.display = "inline-block"; + + const username = document.createElement("p"); + username.innerText = user.username; + username.style.color = "cyan"; + + info.append("Hello ", username); + document.body.append(info); +}); +``` diff --git a/package.json b/package.json index 4a518dc..caf1e5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "activitysdk-ts", - "version": "0.1.1", + "version": "0.2.1", "description": "Typescript fork of activitysdk.", "main": "./dist/lib/index.js", "types": "./dist/types/index.d.ts", @@ -21,7 +21,7 @@ "./dist", "./src", "./README.md", "./LICENSE" ], - "author": "big nutty", + "author": "UserUNP", "license": "MIT", "bugs": { "url": "https://github.com/UserUNP/activitysdk-ts/issues" diff --git a/src/constants.ts b/src/constants.ts index 138f27f..b9c3b60 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,16 +1,27 @@ export enum OPCODES { //* same as the object you had. - "HANDSHAKE", - "FRAME", - "CLOSE", - "HELLO", + HANDSHAKE, + FRAME, + CLOSE, + HELLO, }; -export const PLATFORM_TYPES = [ +export enum ORIENTATION_LOCK_STATES { + UNLOCKED = 1, + PORTRAIT, + LANDSCAPE +}; + +export const PLATFORM_TYPES = Object.freeze([ "desktop", "mobile" -] as const; +] as const); -export const RPC_EVENTS = [ +export const DEFAULT_AUTH_SCOPES = Object.freeze([ + "identify", "rpc", + "guilds", "guilds.members.read" +] as const); + +export const RPC_EVENTS = Object.freeze([ "CURRENT_USER_UPDATE", "GUILD_STATUS", "GUILD_CREATE", @@ -53,10 +64,12 @@ export const RPC_EVENTS = [ "VOICE_CHANNEL_EFFECT_RECENT_EMOJI", "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE", "READY", - "ERROR" -] as const; + "ERROR", + "SET_ORIENTATION_LOCK_STATE", + "GET_PLATFORM_BEHAVIORS" +] as const); -export const RPC_COMMANDS = [ +export const RPC_COMMANDS = Object.freeze([ "DISPATCH", "SET_CONFIG", "AUTHORIZE", @@ -130,7 +143,7 @@ export const RPC_COMMANDS = [ "CAPTURE_LOG", "ENCOURAGE_HW_ACCELERATION", "SET_ORIENTATION_LOCK_STATE" -] as const; +] as const); //* pov: ottelino hates typescript //* (something) as const -> infers the type as the literal of this object -> makes it readonly. @@ -142,11 +155,12 @@ export const RPC_COMMANDS = [ //? interface -> object type but compiles faster. //? you can have functions that work as a type guard +export type OrientationState = "unlocked" | "portrait" | "landscape"; export type PlatformType = (typeof PLATFORM_TYPES)[number]; export type RPCEvent = (typeof RPC_EVENTS)[number]; export type RPCCommand = (typeof RPC_COMMANDS)[number]; export interface RPCPayload { - cmd: RPCCommand; + cmd: RPCCommand | null; evt: RPCEvent | null; nonce: string | null; data?: DataObj; // sometimes its type of string for some reason. @@ -161,6 +175,10 @@ export function malformedResponseError() { new Error("Malformed response from server."); } +export function debug(...message: any[]) { + console.debug("[ActivitySDK]", ...message); +} + export function isPlatform(platform: unknown): platform is PlatformType { if (!platform) return false; if (typeof platform !== "string") return false; @@ -182,10 +200,17 @@ export function isCommand(command: unknown): command is RPCCommand { else return true; } -export function isMessage(message: unknown): message is RPCPayload { +export function isPayload(message: unknown): message is RPCPayload { if (!message) return false; if (typeof message !== "object") return false; if (!("cmd" in message && "nonce" in message && "data" in message)) return false; else return true; } +export function isOrientationState(orientationCode: unknown): orientationCode is ORIENTATION_LOCK_STATES { + if (!orientationCode) return false; + if (typeof orientationCode !== "number") return false; + if (!ORIENTATION_LOCK_STATES[orientationCode]) return false; + else return true; +} + diff --git a/src/index.ts b/src/index.ts index f0d7ac9..de2953d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,11 +2,16 @@ import EventEmitter from 'eventemitter3'; import { v4 as uuid } from 'uuid'; import { + debug, + malformedResponseError, malformedRequestError, + OPCODES, + DEFAULT_AUTH_SCOPES, + PlatformType, isPlatform, RPCCommand, isCommand, RPCEvent, isEvent, - RPCPayload, + RPCPayload, isPayload, } from './constants'; import ActivitySDKCommands from './rpc/command'; @@ -16,8 +21,8 @@ class ActivitySDK extends EventEmitter { rpcTarget: Window = window.parent.opener || window.parent; rpcOrigin: string = document.referrer || "*"; - commands = new ActivitySDKCommands(this.appId, this.appSecret, this.sendCommand.bind(this)); - commandCache = new Map["data"]) => void; reject: (reason?: any) => void }>(); + commands = new ActivitySDKCommands(this.appId, this.sendCommand.bind(this)); + commandCache = new Map void; reject: (reason?: any) => void }>(); frameId: string; instanceId: string; @@ -26,7 +31,7 @@ class ActivitySDK extends EventEmitter { guildId: string; - constructor(public appId: string, public appSecret: string) { + constructor(public appId: string) { super(); window.addEventListener('message', this._handleMessage.bind(this)); @@ -43,21 +48,26 @@ class ActivitySDK extends EventEmitter { if (!frameParam) throw new Error("Window missing frame_id"); else this.frameId = frameParam; if (!instanceParam) throw new Error("Window missing instance_id"); else this.instanceId = instanceParam; - if (!channelParam) throw new Error("Window missing frame_id"); else this.channelId = channelParam; - if (!guildParam) throw new Error("Window missing frame_id"); else this.guildId = guildParam; + if (!channelParam) throw new Error("Window missing channel_id"); else this.channelId = channelParam; + if (!guildParam) throw new Error("Window missing guild_id"); else this.guildId = guildParam; + + this._handshake(); + } - this._init(); + async login(appSecret: string, scopes: readonly string[] = DEFAULT_AUTH_SCOPES, consent: boolean = false) { + const authorizeRes = await this.commands.authorize(scopes, consent); + if (!authorizeRes || !("code" in authorizeRes) || typeof authorizeRes.code !== "string") throw malformedResponseError(); + const authorizationGrant = await utils.exchangeAuthorizationCode(this.appId, appSecret, authorizeRes.code); + if (!authorizationGrant || "error" in authorizationGrant || !("access_token" in authorizationGrant) || typeof authorizationGrant.access_token !== "string") throw malformedRequestError(); + return await this.commands.authenticate(authorizationGrant.access_token); } private _handleMessage(message: MessageEvent) { - if (typeof message.data !== "object") { - console.log("Recieved message: ", message.data); - return; - } + if (typeof message.data !== "object") return debug("Recieved message: ", message.data); const opcode = message.data[0]; const payload = message.data[1]; if (!(opcode in OPCODES)) throw new Error("Invalid opcode recieved: " + opcode); - console.log("Recieved opcode " + OPCODES[opcode], message); + debug("Recieved opcode " + OPCODES[opcode], message); switch (OPCODES[opcode]) { case "HANDSHAKE": return; @@ -70,16 +80,16 @@ class ActivitySDK extends EventEmitter { this.isReady = true; return; default: - throw "Unable to handle opcode: " + OPCODES[opcode]; + throw new Error("Unable to handle opcode: " + OPCODES[opcode]); } } - private _postRawPayload(opcode: OPCODES, payload: RPCPayload) { - console.log("post " + OPCODES[opcode] + " with", payload); + _postRawPayload(opcode: OPCODES, payload: object) { + debug("Posting " + OPCODES[opcode] + " with", payload); this.rpcTarget.postMessage([opcode, payload], this.rpcOrigin); } - sendCommand(type: RPCCommand, args: Required["args"]>): Promise["data"]> { + sendCommand(type: RPCCommand, args: Required["args"]>): Promise { if (!isCommand(type)) throw new Error("Invalid RPC Command: " + type); const nonce = uuid(); @@ -88,7 +98,12 @@ class ActivitySDK extends EventEmitter { cmd: type, evt: null, }); - return new Promise["data"]>((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })) as Promise["data"]>; + return new Promise["data"]>((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })) as Promise; + } + + close(data: { code: number; message: string }) { + window.removeEventListener('message', this._handleMessage); + this._sendData(OPCODES.CLOSE, { code: data.code, message: data.message }) } postPayload(payload: Omit, "nonce">) { @@ -104,23 +119,36 @@ class ActivitySDK extends EventEmitter { return new Promise((resolve, reject) => this.commandCache.set(nonce, { resolve, reject })); } + _sendData(opcode: Exclude, data: object) { + const nonce = uuid(); + this._postRawPayload(opcode, {nonce, ...data}); + } + // Command Handling - private _resolveCommand(nonce: string, data: Required["data"]>) { + private _resolveCommand(nonce: string, data?: DataObj) { const response = this.commandCache.get(nonce); if (response) response.resolve(data); - this.commandCache.delete(nonce); } - private _rejectCommand(nonce: string, data: Required["data"]>) { + private _rejectCommand(nonce: string, data?: DataObj) { const response = this.commandCache.get(nonce); if (response) response.reject(data); - this.commandCache.delete(nonce); + if (!data || !isPayload(data)) return; + if (!data.evt || !data.data) throw malformedResponseError(); + else if (data.cmd == "DISPATCH") { + this.emit(data.evt, data.data); + return; + } + if (!data.nonce) throw new Error("Missing nonce"); + else if (data.evt == "ERROR") this._rejectCommand(data.nonce, data.data); + else this._resolveCommand(data.nonce, data.data); + } private _handleFrame(resp: RPCPayload) { - console.log("Handle frame (response) -> ", resp); + debug("Handle frame (response) -> ", resp); if (resp.cmd === "DISPATCH") { if (!isEvent(resp.evt)) throw new Error("Undefined event in DISPATCH command."); this.emit(resp.evt, resp.data); @@ -133,11 +161,11 @@ class ActivitySDK extends EventEmitter { }; // Handling RPC Events - async subscribe(type: RPCEvent, reciever: () => void) { + async subscribe(type: RPCEvent, args: object, reciever: () => void) { if (!isEvent(type)) throw new Error("Invalid RPC Event: " + type); await this.postPayload({ - evt: type, cmd: "SUBSCRIBE" + evt: type, cmd: "SUBSCRIBE", args }); return this.on(type, reciever); @@ -185,10 +213,19 @@ class ActivitySDK extends EventEmitter { ], this.rpcOrigin); } - private _init() { - this._handshake(); - } - } +export const utils = { + async exchangeAuthorizationCode(appId: string, appSecret: string, code: string) { + return await (await fetch("https://discord.com/api/oauth2/token", { + method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ + grant_type: "authorization_code", + code: code, + client_id: appId, + client_secret: appSecret + }) + })).json() as object; + }, +} as const; + export default ActivitySDK; diff --git a/src/rpc/command.ts b/src/rpc/command.ts index 4e6af52..626aef8 100644 --- a/src/rpc/command.ts +++ b/src/rpc/command.ts @@ -1,25 +1,25 @@ -import { RPCCommand, RPCPayload, malformedRequestError, malformedResponseError } from "../constants"; +import { + RPCCommand, + DEFAULT_AUTH_SCOPES, + ORIENTATION_LOCK_STATES, + OrientationState +} from "../constants"; export default class ActivitySDKCommands { - constructor(private appId: string, private appSecret: string, public sendCommandHandler: (type: RPCCommand, args: Required["args"]>) => Promise["data"]>) {} + constructor(private appId: string, public sendCommandHandler: (type: RPCCommand, args: object) => Promise) { } - async authenticate(scopes: string[], rpcToken?: string) { - const authorizeRes = await this.sendCommandHandler("AUTHORIZE", { - client_id: this.appId, rpc_token: rpcToken, scopes - }); - if (!authorizeRes || !("code" in authorizeRes) || typeof authorizeRes.code !== "string") throw malformedResponseError(); - const authenticateRes: object = await (await fetch("https://discord.com/api/oauth2/token", { - method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ - grant_type: "authorization_code", - code: authorizeRes.code, - client_id: this.appId, - client_secret: this.appSecret - }) - })).json(); - if (!authenticateRes || "error" in authenticateRes || !("access_token" in authenticateRes) || typeof authenticateRes.access_token !== "string") throw malformedRequestError(); + async authenticate(accessToken: string) { return await this.sendCommandHandler("AUTHENTICATE", { - access_token: authenticateRes.access_token + access_token: accessToken + }); + } + + async authorize(scopes: readonly string[] = DEFAULT_AUTH_SCOPES, consent: boolean = false) { + return await this.sendCommandHandler("AUTHORIZE", { + client_id: this.appId, scopes, + response_type: "code", state: "", + prompt: !consent ? "none" : "consent", }); } @@ -53,8 +53,8 @@ export default class ActivitySDKCommands { return await this.sendCommandHandler("GET_CHANNELS", { guild_id: guildId }); } - async createChannelInvite() { - return await this.sendCommandHandler("CREATE_CHANNEL_INVITE", {}); + async createChannelInvite(channelId: string) { + return await this.sendCommandHandler("CREATE_CHANNEL_INVITE", { channel_id: channelId }); } async openInviteDialog() { @@ -68,6 +68,28 @@ export default class ActivitySDKCommands { async getUserLocale() { return await this.sendCommandHandler("USER_SETTINGS_GET_LOCALE", {}); } + + async setOrientationStateLock(state: OrientationState | ORIENTATION_LOCK_STATES) { + return this.sendCommandHandler("SET_ORIENTATION_LOCK_STATE", { + lock_state: typeof state === "string" ? ORIENTATION_LOCK_STATES[Object.values(ORIENTATION_LOCK_STATES).indexOf(state) + 1] : state + }) + } + + async openExternalLink(url: string) { + return this.sendCommandHandler("OPEN_EXTERNAL_LINK", { url }); + } + + async getVoiceSettings() { + return this.sendCommandHandler("GET_VOICE_SETTINGS", {}); + } + + async setVoiceSettings(settings: object) { + return this.sendCommandHandler("SET_VOICE_SETTINGS", settings); + } + + async selectTextChannel(channelId: string) { + return this.sendCommandHandler("SELECT_TEXT_CHANNEL", { channel_id: channelId }); + } } export interface AuthorizeResponseData { @@ -139,9 +161,20 @@ export interface GetChannelResponseData { permissions?: string; flags?: number; bitrate?: number; - voice_states: object[]; //* https://discord.com/developers/docs/resources/voice#voice-state-object - messages: object[]; //* https://discord.com/developers/docs/resources/channel#message-object + /** + * @see https://discord.com/developers/docs/resources/voice#voice-state-object + */ + voice_states?: object[]; + /** + * @see https://discord.com/developers/docs/resources/channel#message-object + */ + messages: object[]; } export interface GetChannelsResponseData { channels: GetChannelResponseData[]; } + +export interface CreateChannelInviteResponseData { + code: string; + expires: number; +} diff --git a/tsconfig.json b/tsconfig.json index e710f71..9cd89ef 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "alwaysStrict": true, - "target": "ES2015", + "target": "ES2017", "module": "CommonJS", "sourceMap": true, "outDir": "./dist/lib/", @@ -10,7 +10,7 @@ "declarationMap": true, "rootDir": "./src", "lib": [ - "ES2015", + "ES2017", "DOM" ], "strict": true,