@hieuxyz/rpc 1.1.0 → 1.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -21
- package/dist/hieuxyz/Client.d.ts +13 -2
- package/dist/hieuxyz/Client.js +4 -2
- package/dist/hieuxyz/gateway/DiscordWebSocket.d.ts +9 -4
- package/dist/hieuxyz/gateway/DiscordWebSocket.js +63 -34
- package/dist/hieuxyz/gateway/entities/identify.d.ts +12 -1
- package/dist/hieuxyz/gateway/entities/identify.js +7 -6
- package/dist/hieuxyz/gateway/entities/types.d.ts +13 -5
- package/dist/hieuxyz/rpc/HieuxyzRPC.d.ts +66 -17
- package/dist/hieuxyz/rpc/HieuxyzRPC.js +106 -19
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/hieuxyz/rpc/blob/main/LICENSE)
|
|
5
5
|
[](https://www.npmjs.com/package/@hieuxyz/rpc)
|
|
6
6
|
|
|
7
|
-
An easy-to-use Discord Rich Presence (RPC) library built for the Node.js environment using TypeScript. This library is designed to simplify the creation and management of custom RPC states for Discord user accounts.
|
|
7
|
+
An easy-to-use and powerful Discord Rich Presence (RPC) library built for the Node.js environment using TypeScript. This library is designed to simplify the creation and management of custom RPC states for Discord user accounts.
|
|
8
8
|
|
|
9
9
|
> [!WARNING]
|
|
10
10
|
> **I don't take any responsibility for blocked Discord accounts that used this module.**
|
|
@@ -17,7 +17,6 @@ An easy-to-use Discord Rich Presence (RPC) library built for the Node.js environ
|
|
|
17
17
|
|
|
18
18
|
- **Flexible Builder Pattern:** Easily build your RPC state with intuitive chainable methods.
|
|
19
19
|
- **Easy to use:** The `Client` class abstracts away all the complex connection and setup logic, letting you get started with just a few lines of code.
|
|
20
|
-
- **Auto Resume:** Built-in auto reconnect and session recovery mechanism in case of network failure, ensuring your RPC is always stable.
|
|
21
20
|
|
|
22
21
|
## Install
|
|
23
22
|
|
|
@@ -65,17 +64,21 @@ async function start() {
|
|
|
65
64
|
.setName("Visual Studio Code")
|
|
66
65
|
.setDetails("Developing a new library")
|
|
67
66
|
.setState("Workspace: @hieuxyz/rpc")
|
|
68
|
-
.setPlatform('desktop')
|
|
67
|
+
.setPlatform('desktop')
|
|
69
68
|
.setType(0) // 0: Playing
|
|
70
69
|
.setTimestamps(Date.now())
|
|
71
70
|
.setParty(1, 5)
|
|
72
71
|
.setLargeImage("https://i.ibb.co/MDP0hfTM/typescript.png", "TypeScript")
|
|
73
|
-
.setSmallImage(new LocalImage(path.join(__dirname, 'vscode.png')), "VS Code")
|
|
72
|
+
.setSmallImage(new LocalImage(path.join(__dirname, 'vscode.png')), "VS Code")
|
|
73
|
+
.setButtons([
|
|
74
|
+
{ label: 'View on GitHub', url: 'https://github.com/hieuxyz00/hieuxyz_rpc' },
|
|
75
|
+
{ label: 'View on NPM', url: 'https://www.npmjs.com/package/@hieuxyz/rpc' }
|
|
76
|
+
]);
|
|
74
77
|
|
|
75
78
|
await client.rpc.build();
|
|
76
79
|
logger.info("Initial RPC has been set!");
|
|
77
80
|
|
|
78
|
-
setTimeout(() => {
|
|
81
|
+
setTimeout(async () => {
|
|
79
82
|
logger.info("Clearing RPC and resetting builder...");
|
|
80
83
|
client.rpc.clear();
|
|
81
84
|
|
|
@@ -84,7 +87,7 @@ async function start() {
|
|
|
84
87
|
.setDetails("Thinking about the next feature")
|
|
85
88
|
.setLargeImage("mp:external/dZwPAoMNVxT5qYqecH3Mfgxv1RQEdtGBU8nAspOcAo4/https/c.tenor.com/fvuYGhI1vgUAAAAC/tenor.gif", "Coffee Time");
|
|
86
89
|
|
|
87
|
-
client.rpc.build();
|
|
90
|
+
await client.rpc.build();
|
|
88
91
|
logger.info("A new RPC has been set after clearing.");
|
|
89
92
|
|
|
90
93
|
}, 20000);
|
|
@@ -102,11 +105,32 @@ start().catch(err => {
|
|
|
102
105
|
});
|
|
103
106
|
```
|
|
104
107
|
|
|
108
|
+
## Advanced Usage
|
|
109
|
+
|
|
110
|
+
### Client Spoofing
|
|
111
|
+
|
|
112
|
+
You can make it appear as though you are using Discord from a different device (e.g., mobile) by providing the `properties` option during client initialization.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { Client } from '@hieuxyz/rpc';
|
|
116
|
+
|
|
117
|
+
const client = new Client({
|
|
118
|
+
token: "YOUR_TOKEN",
|
|
119
|
+
properties: {
|
|
120
|
+
os: 'Android',
|
|
121
|
+
browser: 'Discord Android',
|
|
122
|
+
device: 'Android16',
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// ...
|
|
127
|
+
```
|
|
128
|
+
|
|
105
129
|
## Get Token ?
|
|
106
130
|
|
|
107
131
|
- Based: [findByProps](https://discord.com/channels/603970300668805120/1085682686607249478/1085682686607249478)
|
|
108
132
|
|
|
109
|
-
|
|
133
|
+
**Run code (Discord Console - [Ctrl + Shift + I])**
|
|
110
134
|
|
|
111
135
|
```js
|
|
112
136
|
window.webpackChunkdiscord_app.push([
|
|
@@ -140,16 +164,22 @@ This is the main starting point.
|
|
|
140
164
|
- `new Client(options)`: Create a new instance.
|
|
141
165
|
- `options.token` (required): Your Discord user token.
|
|
142
166
|
- `options.apiBaseUrl` (optional): Override the default image proxy service URL.
|
|
143
|
-
- `options.alwaysReconnect` (optional): If `true`, the client will attempt to reconnect even after a normal close
|
|
167
|
+
- `options.alwaysReconnect` (optional): If `true`, the client will attempt to reconnect even after a normal close. Defaults to `false`.
|
|
168
|
+
- `options.properties` (optional): An object to spoof client properties (OS, browser, device).
|
|
169
|
+
- `options.connectionTimeout` (optional): Timeout in milliseconds for the initial connection. Defaults to `30000`.
|
|
144
170
|
- `client.run()`: Start connecting to Discord Gateway.
|
|
145
171
|
- `client.rpc`: Access the instance of `HieuxyzRPC` to build the state.
|
|
146
172
|
- `client.close(force?: boolean)`: Closes the connection to the Discord Gateway.
|
|
147
|
-
- `force` (optional, boolean): If
|
|
173
|
+
- `force` (optional, boolean): If `true`, the client closes permanently and will not reconnect.
|
|
148
174
|
|
|
149
175
|
### Class `HieuxyzRPC`
|
|
150
176
|
|
|
151
177
|
Main builder class for RPC.
|
|
152
178
|
|
|
179
|
+
#### Getter Properties
|
|
180
|
+
- `.largeImageUrl`: Returns the resolved URL for the large image, or `null`.
|
|
181
|
+
- `.smallImageUrl`: Returns the resolved URL for the small image, or `null`.
|
|
182
|
+
|
|
153
183
|
#### Setter Methods
|
|
154
184
|
- `.setName(string)`: Sets the activity name (first line).
|
|
155
185
|
- `.setDetails(string)`: Sets the activity details (second line).
|
|
@@ -158,33 +188,37 @@ Main builder class for RPC.
|
|
|
158
188
|
- `.setParty(current, max)`: Sets the party information.
|
|
159
189
|
- `.setLargeImage(RpcImage, text?)`: Sets the large image and its tooltip text.
|
|
160
190
|
- `.setSmallImage(RpcImage, text?)`: Sets the small image and its tooltip text.
|
|
161
|
-
- `.setButtons(buttons[])`: Sets up to two clickable buttons.
|
|
191
|
+
- `.setButtons(buttons[])`: Sets up to two clickable buttons. Each button is an object `{ label: string, url: string }`.
|
|
192
|
+
- `.setSecrets({ join?, spectate?, match? })`: Sets secrets for game invites.
|
|
193
|
+
- `.setSyncId(string)`: Sets the sync ID, used for features like Spotify track syncing.
|
|
194
|
+
- `.setFlags(number)`: Sets activity flags (e.g., for instanced games). Use the `ActivityFlags` enum.
|
|
162
195
|
- `.setPlatform(platform)`: Sets the platform (`'desktop'`, `'xbox'`, etc.).
|
|
163
196
|
- `.setInstance(boolean)`: Marks the activity as a specific, joinable instance.
|
|
164
197
|
- `.setApplicationId(string)`: Sets a custom Application ID.
|
|
165
198
|
- `.setStatus('online' | ...)`: Sets the user's presence status.
|
|
166
199
|
|
|
167
200
|
#### Clearer Methods
|
|
168
|
-
- `.clearDetails()`: Removes
|
|
169
|
-
- `.clearState()`: Removes
|
|
170
|
-
- `.clearTimestamps()`: Removes
|
|
171
|
-
- `.clearParty()`: Removes
|
|
172
|
-
- `.clearLargeImage()`: Removes the large image and
|
|
173
|
-
- `.clearSmallImage()`: Removes the small image and
|
|
201
|
+
- `.clearDetails()`: Removes activity details.
|
|
202
|
+
- `.clearState()`: Removes activity state.
|
|
203
|
+
- `.clearTimestamps()`: Removes timestamps.
|
|
204
|
+
- `.clearParty()`: Removes party information.
|
|
205
|
+
- `.clearLargeImage()`: Removes the large image and text.
|
|
206
|
+
- `.clearSmallImage()`: Removes the small image and text.
|
|
174
207
|
- `.clearButtons()`: Removes all buttons.
|
|
208
|
+
- `.clearSecrets()`: Removes all secrets.
|
|
175
209
|
- `.clearInstance()`: Removes the instance flag.
|
|
176
210
|
|
|
177
211
|
#### Core Methods
|
|
178
212
|
- `.build()`: Builds and sends the presence payload to Discord.
|
|
179
|
-
- `.updateRPC()`:
|
|
180
|
-
- `.clear()`: Clears the
|
|
213
|
+
- `.updateRPC()`: Alias for `build()`.
|
|
214
|
+
- `.clear()`: Clears the Rich Presence from the user's profile and resets the builder.
|
|
181
215
|
|
|
182
216
|
### Types of images
|
|
183
217
|
|
|
184
|
-
- `new ExternalImage(url)`: Use image from an external URL (will be
|
|
218
|
+
- `new ExternalImage(url)`: Use an image from an external URL (will be proxied).
|
|
185
219
|
- `new LocalImage(filePath, fileName?)`: Upload a photo from your device.
|
|
186
|
-
- `new RawImage(assetKey)`: Use an existing asset key directly.
|
|
187
|
-
- `new DiscordImage(key)`: Use assets already on Discord.
|
|
220
|
+
- `new RawImage(assetKey)`: Use an existing asset key directly (e.g., `spotify:track_id`).
|
|
221
|
+
- `new DiscordImage(key)`: Use assets already on Discord (e.g., `mp:attachments/...`).
|
|
188
222
|
|
|
189
223
|
## Author
|
|
190
224
|
|
package/dist/hieuxyz/Client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HieuxyzRPC } from './rpc/HieuxyzRPC';
|
|
2
|
+
import { ClientProperties } from './gateway/entities/identify';
|
|
2
3
|
/**
|
|
3
4
|
* Option to initialize Client.
|
|
4
5
|
*/
|
|
@@ -12,6 +13,16 @@ export interface ClientOptions {
|
|
|
12
13
|
* Defaults to false.
|
|
13
14
|
*/
|
|
14
15
|
alwaysReconnect?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* (Optional) Client properties to send to Discord gateway.
|
|
18
|
+
* Used for client spoofing (e.g., appearing as on mobile).
|
|
19
|
+
*/
|
|
20
|
+
properties?: ClientProperties;
|
|
21
|
+
/**
|
|
22
|
+
* (Optional) The timeout in milliseconds for the initial gateway connection.
|
|
23
|
+
* Defaults to 30000 (30 seconds).
|
|
24
|
+
*/
|
|
25
|
+
connectionTimeout?: number;
|
|
15
26
|
}
|
|
16
27
|
/**
|
|
17
28
|
* The main Client class for interacting with Discord Rich Presence.
|
|
@@ -28,7 +39,7 @@ export interface ClientOptions {
|
|
|
28
39
|
export declare class Client {
|
|
29
40
|
/**
|
|
30
41
|
* Provides access to RPC constructor methods.
|
|
31
|
-
* Use this
|
|
42
|
+
* Use this to set your Rich Presence state details.
|
|
32
43
|
*/
|
|
33
44
|
readonly rpc: HieuxyzRPC;
|
|
34
45
|
private readonly websocket;
|
|
@@ -36,7 +47,7 @@ export declare class Client {
|
|
|
36
47
|
private readonly token;
|
|
37
48
|
/**
|
|
38
49
|
* Create a new Client instance.
|
|
39
|
-
* @param options - Options to configure the client.
|
|
50
|
+
* @param {ClientOptions} options - Options to configure the client.
|
|
40
51
|
* @throws {Error} If no token is provided in the options.
|
|
41
52
|
*/
|
|
42
53
|
constructor(options: ClientOptions);
|
package/dist/hieuxyz/Client.js
CHANGED
|
@@ -20,7 +20,7 @@ const logger_1 = require("./utils/logger");
|
|
|
20
20
|
class Client {
|
|
21
21
|
/**
|
|
22
22
|
* Provides access to RPC constructor methods.
|
|
23
|
-
* Use this
|
|
23
|
+
* Use this to set your Rich Presence state details.
|
|
24
24
|
*/
|
|
25
25
|
rpc;
|
|
26
26
|
websocket;
|
|
@@ -28,7 +28,7 @@ class Client {
|
|
|
28
28
|
token;
|
|
29
29
|
/**
|
|
30
30
|
* Create a new Client instance.
|
|
31
|
-
* @param options - Options to configure the client.
|
|
31
|
+
* @param {ClientOptions} options - Options to configure the client.
|
|
32
32
|
* @throws {Error} If no token is provided in the options.
|
|
33
33
|
*/
|
|
34
34
|
constructor(options) {
|
|
@@ -39,6 +39,8 @@ class Client {
|
|
|
39
39
|
this.imageService = new ImageService_1.ImageService(options.apiBaseUrl);
|
|
40
40
|
this.websocket = new DiscordWebSocket_1.DiscordWebSocket(this.token, {
|
|
41
41
|
alwaysReconnect: options.alwaysReconnect ?? false,
|
|
42
|
+
properties: options.properties,
|
|
43
|
+
connectionTimeout: options.connectionTimeout,
|
|
42
44
|
});
|
|
43
45
|
this.rpc = new HieuxyzRPC_1.HieuxyzRPC(this.websocket, this.imageService);
|
|
44
46
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { ClientProperties } from './entities/identify';
|
|
1
2
|
import { PresenceUpdatePayload } from './entities/types';
|
|
2
3
|
interface DiscordWebSocketOptions {
|
|
3
4
|
alwaysReconnect: boolean;
|
|
5
|
+
properties?: ClientProperties;
|
|
6
|
+
connectionTimeout?: number;
|
|
4
7
|
}
|
|
5
8
|
/**
|
|
6
9
|
* Manage WebSocket connections to Discord Gateway.
|
|
@@ -17,6 +20,7 @@ export declare class DiscordWebSocket {
|
|
|
17
20
|
private options;
|
|
18
21
|
private isReconnecting;
|
|
19
22
|
private permanentClose;
|
|
23
|
+
private connectTimeout;
|
|
20
24
|
private resolveReady;
|
|
21
25
|
/**
|
|
22
26
|
* A promise will be resolved when the Gateway connection is ready.
|
|
@@ -25,8 +29,8 @@ export declare class DiscordWebSocket {
|
|
|
25
29
|
readyPromise: Promise<void>;
|
|
26
30
|
/**
|
|
27
31
|
* Create a DiscordWebSocket instance.
|
|
28
|
-
* @param token - Discord user token for authentication.
|
|
29
|
-
* @param options - Configuration options for the WebSocket client.
|
|
32
|
+
* @param {string} token - Discord user token for authentication.
|
|
33
|
+
* @param {DiscordWebSocketOptions} options - Configuration options for the WebSocket client.
|
|
30
34
|
* @throws {Error} If the token is invalid.
|
|
31
35
|
*/
|
|
32
36
|
constructor(token: string, options: DiscordWebSocketOptions);
|
|
@@ -37,6 +41,7 @@ export declare class DiscordWebSocket {
|
|
|
37
41
|
* If there was a previous session, it will try to resume.
|
|
38
42
|
*/
|
|
39
43
|
connect(): void;
|
|
44
|
+
private handleClose;
|
|
40
45
|
private onMessage;
|
|
41
46
|
private startHeartbeating;
|
|
42
47
|
private sendHeartbeat;
|
|
@@ -44,13 +49,13 @@ export declare class DiscordWebSocket {
|
|
|
44
49
|
private resume;
|
|
45
50
|
/**
|
|
46
51
|
* Send presence update payload to Gateway.
|
|
47
|
-
* @param presence - Payload update status to send.
|
|
52
|
+
* @param {PresenceUpdatePayload} presence - Payload update status to send.
|
|
48
53
|
*/
|
|
49
54
|
sendActivity(presence: PresenceUpdatePayload): void;
|
|
50
55
|
private sendJson;
|
|
51
56
|
/**
|
|
52
57
|
* Closes the WebSocket connection.
|
|
53
|
-
* @param force If true, prevents any automatic reconnection attempts.
|
|
58
|
+
* @param {boolean} force If true, prevents any automatic reconnection attempts.
|
|
54
59
|
*/
|
|
55
60
|
close(force?: boolean): void;
|
|
56
61
|
private cleanupHeartbeat;
|
|
@@ -57,6 +57,7 @@ class DiscordWebSocket {
|
|
|
57
57
|
options;
|
|
58
58
|
isReconnecting = false;
|
|
59
59
|
permanentClose = false;
|
|
60
|
+
connectTimeout = null;
|
|
60
61
|
resolveReady = () => { };
|
|
61
62
|
/**
|
|
62
63
|
* A promise will be resolved when the Gateway connection is ready.
|
|
@@ -65,8 +66,8 @@ class DiscordWebSocket {
|
|
|
65
66
|
readyPromise;
|
|
66
67
|
/**
|
|
67
68
|
* Create a DiscordWebSocket instance.
|
|
68
|
-
* @param token - Discord user token for authentication.
|
|
69
|
-
* @param options - Configuration options for the WebSocket client.
|
|
69
|
+
* @param {string} token - Discord user token for authentication.
|
|
70
|
+
* @param {DiscordWebSocketOptions} options - Configuration options for the WebSocket client.
|
|
70
71
|
* @throws {Error} If the token is invalid.
|
|
71
72
|
*/
|
|
72
73
|
constructor(token, options) {
|
|
@@ -74,7 +75,11 @@ class DiscordWebSocket {
|
|
|
74
75
|
throw new Error('Invalid token provided.');
|
|
75
76
|
}
|
|
76
77
|
this.token = token;
|
|
77
|
-
this.options =
|
|
78
|
+
this.options = {
|
|
79
|
+
alwaysReconnect: options.alwaysReconnect ?? false,
|
|
80
|
+
properties: options.properties,
|
|
81
|
+
connectionTimeout: options.connectionTimeout ?? 30000,
|
|
82
|
+
};
|
|
78
83
|
this.readyPromise = new Promise((resolve) => (this.resolveReady = resolve));
|
|
79
84
|
}
|
|
80
85
|
resetReadyPromise() {
|
|
@@ -99,39 +104,53 @@ class DiscordWebSocket {
|
|
|
99
104
|
const url = this.resumeGatewayUrl || 'wss://gateway.discord.gg/?v=10&encoding=json';
|
|
100
105
|
logger_1.logger.info(`Attempting to connect to ${url}...`);
|
|
101
106
|
this.ws = new ws_1.default(url);
|
|
107
|
+
this.connectTimeout = setTimeout(() => {
|
|
108
|
+
logger_1.logger.error('Connection timed out. Terminating connection attempt.');
|
|
109
|
+
if (this.ws) {
|
|
110
|
+
this.ws.terminate();
|
|
111
|
+
}
|
|
112
|
+
}, this.options.connectionTimeout);
|
|
102
113
|
this.ws.on('open', () => {
|
|
103
114
|
logger_1.logger.info(`Successfully connected to Discord Gateway at ${url}.`);
|
|
104
115
|
this.isReconnecting = false;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
logger_1.logger.warn(`Connection closed: ${code} - ${reason.toString('utf-8')}`);
|
|
109
|
-
this.cleanupHeartbeat();
|
|
110
|
-
if (this.permanentClose) {
|
|
111
|
-
logger_1.logger.info('Connection permanently closed by client. Not reconnecting.');
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (this.isReconnecting)
|
|
115
|
-
return;
|
|
116
|
-
if (this.shouldReconnect(code)) {
|
|
117
|
-
setTimeout(() => {
|
|
118
|
-
const canResume = code !== 4004 && !!this.sessionId;
|
|
119
|
-
if (!canResume) {
|
|
120
|
-
this.sessionId = null;
|
|
121
|
-
this.sequence = null;
|
|
122
|
-
this.resumeGatewayUrl = null;
|
|
123
|
-
}
|
|
124
|
-
this.connect();
|
|
125
|
-
}, 500);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
logger_1.logger.info('Not attempting to reconnect based on close code and client options.');
|
|
116
|
+
if (this.connectTimeout) {
|
|
117
|
+
clearTimeout(this.connectTimeout);
|
|
118
|
+
this.connectTimeout = null;
|
|
129
119
|
}
|
|
130
120
|
});
|
|
121
|
+
this.ws.on('message', this.onMessage.bind(this));
|
|
122
|
+
this.ws.on('close', this.handleClose.bind(this));
|
|
131
123
|
this.ws.on('error', (err) => {
|
|
132
|
-
|
|
124
|
+
if (err.message !== 'WebSocket was closed before the connection was established') {
|
|
125
|
+
logger_1.logger.error(`WebSocket Error: ${err.message}`);
|
|
126
|
+
}
|
|
133
127
|
});
|
|
134
128
|
}
|
|
129
|
+
handleClose(code, reason) {
|
|
130
|
+
logger_1.logger.warn(`Connection closed: ${code} - ${reason.toString('utf-8')}`);
|
|
131
|
+
this.cleanupHeartbeat();
|
|
132
|
+
if (this.connectTimeout) {
|
|
133
|
+
clearTimeout(this.connectTimeout);
|
|
134
|
+
this.connectTimeout = null;
|
|
135
|
+
}
|
|
136
|
+
this.isReconnecting = false;
|
|
137
|
+
if (code === 4004) {
|
|
138
|
+
this.sessionId = null;
|
|
139
|
+
this.sequence = null;
|
|
140
|
+
this.resumeGatewayUrl = null;
|
|
141
|
+
}
|
|
142
|
+
if (this.permanentClose) {
|
|
143
|
+
logger_1.logger.info('Connection permanently closed by client. Not reconnecting.');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (this.shouldReconnect(code)) {
|
|
147
|
+
logger_1.logger.info('Attempting to reconnect in 5 seconds...');
|
|
148
|
+
setTimeout(() => this.connect(), 5000);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
logger_1.logger.info('Not attempting to reconnect based on close code and client options.');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
135
154
|
onMessage(data, isBinary) {
|
|
136
155
|
let decompressedData;
|
|
137
156
|
if (isBinary) {
|
|
@@ -146,6 +165,10 @@ class DiscordWebSocket {
|
|
|
146
165
|
}
|
|
147
166
|
switch (payload.op) {
|
|
148
167
|
case OpCode_1.OpCode.HELLO:
|
|
168
|
+
if (this.connectTimeout) {
|
|
169
|
+
clearTimeout(this.connectTimeout);
|
|
170
|
+
this.connectTimeout = null;
|
|
171
|
+
}
|
|
149
172
|
this.heartbeatIntervalValue = payload.d.heartbeat_interval;
|
|
150
173
|
logger_1.logger.info(`Received HELLO. Setting heartbeat interval to ${this.heartbeatIntervalValue}ms.`);
|
|
151
174
|
this.startHeartbeating();
|
|
@@ -211,7 +234,7 @@ class DiscordWebSocket {
|
|
|
211
234
|
logger_1.logger.info(`Heartbeat sent with sequence ${this.sequence}.`);
|
|
212
235
|
}
|
|
213
236
|
identify() {
|
|
214
|
-
const identifyPayload = (0, identify_1.getIdentifyPayload)(this.token);
|
|
237
|
+
const identifyPayload = (0, identify_1.getIdentifyPayload)(this.token, this.options.properties);
|
|
215
238
|
this.sendJson({ op: OpCode_1.OpCode.IDENTIFY, d: identifyPayload });
|
|
216
239
|
logger_1.logger.info('Identify payload sent.');
|
|
217
240
|
}
|
|
@@ -231,7 +254,7 @@ class DiscordWebSocket {
|
|
|
231
254
|
}
|
|
232
255
|
/**
|
|
233
256
|
* Send presence update payload to Gateway.
|
|
234
|
-
* @param presence - Payload update status to send.
|
|
257
|
+
* @param {PresenceUpdatePayload} presence - Payload update status to send.
|
|
235
258
|
*/
|
|
236
259
|
sendActivity(presence) {
|
|
237
260
|
this.sendJson({ op: OpCode_1.OpCode.PRESENCE_UPDATE, d: presence });
|
|
@@ -247,7 +270,7 @@ class DiscordWebSocket {
|
|
|
247
270
|
}
|
|
248
271
|
/**
|
|
249
272
|
* Closes the WebSocket connection.
|
|
250
|
-
* @param force If true, prevents any automatic reconnection attempts.
|
|
273
|
+
* @param {boolean} force If true, prevents any automatic reconnection attempts.
|
|
251
274
|
*/
|
|
252
275
|
close(force = false) {
|
|
253
276
|
if (force) {
|
|
@@ -257,9 +280,13 @@ class DiscordWebSocket {
|
|
|
257
280
|
else {
|
|
258
281
|
logger_1.logger.info('Closing connection manually...');
|
|
259
282
|
}
|
|
260
|
-
this.isReconnecting = false;
|
|
261
283
|
if (this.ws) {
|
|
262
|
-
this.ws.
|
|
284
|
+
if (this.ws.readyState === ws_1.default.OPEN) {
|
|
285
|
+
this.ws.close(1000, 'Client initiated closure');
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
this.ws.terminate();
|
|
289
|
+
}
|
|
263
290
|
}
|
|
264
291
|
}
|
|
265
292
|
cleanupHeartbeat() {
|
|
@@ -269,7 +296,9 @@ class DiscordWebSocket {
|
|
|
269
296
|
}
|
|
270
297
|
}
|
|
271
298
|
shouldReconnect(code) {
|
|
272
|
-
|
|
299
|
+
if (code === 1006)
|
|
300
|
+
return true;
|
|
301
|
+
const fatalErrorCodes = [4004, 4010, 4011, 4013, 4014];
|
|
273
302
|
if (fatalErrorCodes.includes(code)) {
|
|
274
303
|
logger_1.logger.error(`Fatal WebSocket error received (code: ${code}). Will not reconnect.`);
|
|
275
304
|
return false;
|
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
import { IdentifyPayload } from './types';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {object} ClientProperties
|
|
4
|
+
* @property {string} [os] - The operating system. (e.g., 'Windows', 'Android')
|
|
5
|
+
* @property {string} [browser] - The browser or client. (e.g., 'Discord Client', 'Discord Android')
|
|
6
|
+
* @property {string} [device] - The device. (e.g., 'Android16')
|
|
7
|
+
*/
|
|
8
|
+
export interface ClientProperties {
|
|
9
|
+
os?: string;
|
|
10
|
+
browser?: string;
|
|
11
|
+
device?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function getIdentifyPayload(token: string, properties?: ClientProperties): IdentifyPayload;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getIdentifyPayload = getIdentifyPayload;
|
|
4
|
-
function getIdentifyPayload(token) {
|
|
4
|
+
function getIdentifyPayload(token, properties) {
|
|
5
|
+
const defaultProperties = {
|
|
6
|
+
os: 'Windows',
|
|
7
|
+
browser: 'Discord Client',
|
|
8
|
+
device: 'hieuxyz©rpc',
|
|
9
|
+
};
|
|
5
10
|
return {
|
|
6
11
|
token: token,
|
|
7
12
|
capabilities: 65,
|
|
8
13
|
largeThreshold: 50,
|
|
9
|
-
properties: {
|
|
10
|
-
os: 'Windows',
|
|
11
|
-
browser: 'Discord Client',
|
|
12
|
-
device: 'hieuxyz©rpc',
|
|
13
|
-
},
|
|
14
|
+
properties: { ...defaultProperties, ...properties },
|
|
14
15
|
compress: true,
|
|
15
16
|
};
|
|
16
17
|
}
|
|
@@ -15,15 +15,16 @@ export interface GatewayPayload {
|
|
|
15
15
|
s?: number | null;
|
|
16
16
|
t?: string | null;
|
|
17
17
|
}
|
|
18
|
+
export interface IdentifyProperties {
|
|
19
|
+
os: string;
|
|
20
|
+
browser: string;
|
|
21
|
+
device: string;
|
|
22
|
+
}
|
|
18
23
|
export interface IdentifyPayload {
|
|
19
24
|
token: string;
|
|
20
25
|
capabilities: number;
|
|
21
26
|
largeThreshold: number;
|
|
22
|
-
properties:
|
|
23
|
-
os: string;
|
|
24
|
-
browser: string;
|
|
25
|
-
device: string;
|
|
26
|
-
};
|
|
27
|
+
properties: IdentifyProperties;
|
|
27
28
|
compress: boolean;
|
|
28
29
|
}
|
|
29
30
|
export interface Activity {
|
|
@@ -34,6 +35,8 @@ export interface Activity {
|
|
|
34
35
|
state?: string;
|
|
35
36
|
platform?: string;
|
|
36
37
|
instance?: boolean;
|
|
38
|
+
flags?: number;
|
|
39
|
+
sync_id?: string;
|
|
37
40
|
party?: {
|
|
38
41
|
id?: string;
|
|
39
42
|
size?: [number, number];
|
|
@@ -48,6 +51,11 @@ export interface Activity {
|
|
|
48
51
|
small_image?: string;
|
|
49
52
|
small_text?: string;
|
|
50
53
|
};
|
|
54
|
+
secrets?: {
|
|
55
|
+
join?: string;
|
|
56
|
+
spectate?: string;
|
|
57
|
+
match?: string;
|
|
58
|
+
};
|
|
51
59
|
buttons?: string[];
|
|
52
60
|
metadata?: {
|
|
53
61
|
button_urls?: string[];
|
|
@@ -2,10 +2,27 @@ import { DiscordWebSocket } from '../gateway/DiscordWebSocket';
|
|
|
2
2
|
import { SettableActivityType } from '../gateway/entities/types';
|
|
3
3
|
import { ImageService } from './ImageService';
|
|
4
4
|
import { RpcImage } from './RpcImage';
|
|
5
|
+
/**
|
|
6
|
+
* Flags for activities, used with `.setFlags()`.
|
|
7
|
+
* @enum {number}
|
|
8
|
+
*/
|
|
9
|
+
export declare enum ActivityFlags {
|
|
10
|
+
INSTANCE = 1,
|
|
11
|
+
JOIN = 2,
|
|
12
|
+
SPECTATE = 4,
|
|
13
|
+
JOIN_REQUEST = 8,
|
|
14
|
+
SYNC = 16,
|
|
15
|
+
PLAY = 32
|
|
16
|
+
}
|
|
5
17
|
interface RpcButton {
|
|
6
18
|
label: string;
|
|
7
19
|
url: string;
|
|
8
20
|
}
|
|
21
|
+
interface RpcSecrets {
|
|
22
|
+
join?: string;
|
|
23
|
+
spectate?: string;
|
|
24
|
+
match?: string;
|
|
25
|
+
}
|
|
9
26
|
export type DiscordPlatform = 'desktop' | 'android' | 'ios' | 'samsung' | 'xbox' | 'ps4' | 'ps5' | 'embedded';
|
|
10
27
|
/**
|
|
11
28
|
* Class built for creating and managing Discord Rich Presence states.
|
|
@@ -26,89 +43,120 @@ export declare class HieuxyzRPC {
|
|
|
26
43
|
private resolvedAssetsCache;
|
|
27
44
|
private renewalInterval;
|
|
28
45
|
constructor(websocket: DiscordWebSocket, imageService: ImageService);
|
|
46
|
+
/**
|
|
47
|
+
* Returns the URL of the large image asset, if available.
|
|
48
|
+
* @type {string | null}
|
|
49
|
+
* @readonly
|
|
50
|
+
*/
|
|
51
|
+
get largeImageUrl(): string | null;
|
|
52
|
+
/**
|
|
53
|
+
* Returns the URL of the small image asset, if available.
|
|
54
|
+
* @type {string | null}
|
|
55
|
+
* @readonly
|
|
56
|
+
*/
|
|
57
|
+
get smallImageUrl(): string | null;
|
|
58
|
+
private _resolveAssetUrl;
|
|
29
59
|
private _toRpcImage;
|
|
30
60
|
private cleanupNulls;
|
|
31
61
|
private sanitize;
|
|
32
62
|
/**
|
|
33
63
|
* Name the operation (first line of RPC).
|
|
34
|
-
* @param name - Name to display.
|
|
64
|
+
* @param {string} name - Name to display.
|
|
35
65
|
* @returns {this}
|
|
36
66
|
*/
|
|
37
67
|
setName(name: string): this;
|
|
38
68
|
/**
|
|
39
69
|
* Set details for the operation (second line of RPC).
|
|
40
|
-
* @param details - Details to display.
|
|
70
|
+
* @param {string} details - Details to display.
|
|
41
71
|
* @returns {this}
|
|
42
72
|
*/
|
|
43
73
|
setDetails(details: string): this;
|
|
44
74
|
/**
|
|
45
75
|
* Set the state for the operation (third line of the RPC).
|
|
46
|
-
* @param state - State to display.
|
|
76
|
+
* @param {string} state - State to display.
|
|
47
77
|
* @returns {this}
|
|
48
78
|
*/
|
|
49
79
|
setState(state: string): this;
|
|
50
80
|
/**
|
|
51
81
|
* Set the activity type.
|
|
52
|
-
* @param type - The type of activity (e.g. 0, 'playing', or ActivityType.Playing).
|
|
82
|
+
* @param {SettableActivityType} type - The type of activity (e.g. 0, 'playing', or ActivityType.Playing).
|
|
53
83
|
* @returns {this}
|
|
54
84
|
*/
|
|
55
85
|
setType(type: SettableActivityType): this;
|
|
56
86
|
/**
|
|
57
87
|
* Set a start and/or end timestamp for the activity.
|
|
58
|
-
* @param start - Unix timestamp (milliseconds) for start time.
|
|
59
|
-
* @param end - Unix timestamp (milliseconds) for the end time.
|
|
88
|
+
* @param {number} [start] - Unix timestamp (milliseconds) for start time.
|
|
89
|
+
* @param {number} [end] - Unix timestamp (milliseconds) for the end time.
|
|
60
90
|
* @returns {this}
|
|
61
91
|
*/
|
|
62
92
|
setTimestamps(start?: number, end?: number): this;
|
|
63
93
|
/**
|
|
64
94
|
* Set party information for the activity.
|
|
65
|
-
* @param currentSize - Current number of players.
|
|
66
|
-
* @param maxSize - Maximum number of players.
|
|
95
|
+
* @param {number} currentSize - Current number of players.
|
|
96
|
+
* @param {number} maxSize - Maximum number of players.
|
|
67
97
|
* @returns {this}
|
|
68
98
|
*/
|
|
69
99
|
setParty(currentSize: number, maxSize: number): this;
|
|
70
100
|
/**
|
|
71
101
|
* Set large image and its caption text.
|
|
72
|
-
* @param source - Image source (URL, asset key, or RpcImage object).
|
|
73
|
-
* @param text - Text displayed when hovering over image.
|
|
102
|
+
* @param {string | RpcImage} source - Image source (URL, asset key, or RpcImage object).
|
|
103
|
+
* @param {string} [text] - Text displayed when hovering over image.
|
|
74
104
|
* @returns {this}
|
|
75
105
|
*/
|
|
76
106
|
setLargeImage(source: string | RpcImage, text?: string): this;
|
|
77
107
|
/**
|
|
78
108
|
* Set the small image and its caption text.
|
|
79
|
-
* @param source - Image source (URL, asset key, or RpcImage object).
|
|
80
|
-
* @param text - Text displayed when hovering over image.
|
|
109
|
+
* @param {string | RpcImage} source - Image source (URL, asset key, or RpcImage object).
|
|
110
|
+
* @param {string} [text] - Text displayed when hovering over image.
|
|
81
111
|
* @returns {this}
|
|
82
112
|
*/
|
|
83
113
|
setSmallImage(source: string | RpcImage, text?: string): this;
|
|
84
114
|
/**
|
|
85
115
|
* Set clickable buttons for RPC (up to 2).
|
|
86
|
-
* @param buttons - An array of button objects
|
|
116
|
+
* @param {RpcButton[]} buttons - An array of button objects, each with a `label` and `url`.
|
|
87
117
|
* @returns {this}
|
|
88
118
|
*/
|
|
89
119
|
setButtons(buttons: RpcButton[]): this;
|
|
120
|
+
/**
|
|
121
|
+
* Set secrets for joining, spectating, and matching games.
|
|
122
|
+
* @param {RpcSecrets} secrets - An object with join, spectate, and/or match secrets.
|
|
123
|
+
* @returns {this}
|
|
124
|
+
*/
|
|
125
|
+
setSecrets(secrets: RpcSecrets): this;
|
|
126
|
+
/**
|
|
127
|
+
* Set the sync_id, typically used for Spotify track synchronization.
|
|
128
|
+
* @param {string} syncId - The synchronization ID.
|
|
129
|
+
* @returns {this}
|
|
130
|
+
*/
|
|
131
|
+
setSyncId(syncId: string): this;
|
|
132
|
+
/**
|
|
133
|
+
* Set activity flags. Use the ActivityFlags enum for convenience.
|
|
134
|
+
* @param {number} flags - A number representing the bitwise flags.
|
|
135
|
+
* @returns {this}
|
|
136
|
+
*/
|
|
137
|
+
setFlags(flags: number): this;
|
|
90
138
|
/**
|
|
91
139
|
* Set custom application ID for RPC.
|
|
92
|
-
* @param id - Discord app ID (must be an 18 or 19 digit number string).
|
|
140
|
+
* @param {string} id - Discord app ID (must be an 18 or 19 digit number string).
|
|
93
141
|
* @throws {Error} If ID is invalid.
|
|
94
142
|
* @returns {this}
|
|
95
143
|
*/
|
|
96
144
|
setApplicationId(id: string): this;
|
|
97
145
|
/**
|
|
98
146
|
* Set the user's status (e.g. online, idle, dnd).
|
|
99
|
-
* @param status - Desired state.
|
|
147
|
+
* @param {'online' | 'dnd' | 'idle' | 'invisible' | 'offline'} status - Desired state.
|
|
100
148
|
* @returns {this}
|
|
101
149
|
*/
|
|
102
150
|
setStatus(status: 'online' | 'dnd' | 'idle' | 'invisible' | 'offline'): this;
|
|
103
151
|
/**
|
|
104
152
|
* Set the platform on which the activity is running.
|
|
105
|
-
* @param platform - Platform (e.g. 'desktop', 'xbox').
|
|
153
|
+
* @param {DiscordPlatform} platform - Platform (e.g. 'desktop', 'xbox').
|
|
106
154
|
* @returns {this}
|
|
107
155
|
*/
|
|
108
156
|
setPlatform(platform: DiscordPlatform): this;
|
|
109
157
|
/**
|
|
110
158
|
* Marks the activity as a joinable instance for the game.
|
|
111
|
-
* @param instance - Whether this activity is a specific instance.
|
|
159
|
+
* @param {boolean} instance - Whether this activity is a specific instance.
|
|
112
160
|
* @returns {this}
|
|
113
161
|
*/
|
|
114
162
|
setInstance(instance: boolean): this;
|
|
@@ -117,6 +165,7 @@ export declare class HieuxyzRPC {
|
|
|
117
165
|
clearTimestamps(): this;
|
|
118
166
|
clearParty(): this;
|
|
119
167
|
clearButtons(): this;
|
|
168
|
+
clearSecrets(): this;
|
|
120
169
|
clearInstance(): this;
|
|
121
170
|
clearLargeImage(): this;
|
|
122
171
|
clearSmallImage(): this;
|
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HieuxyzRPC = void 0;
|
|
3
|
+
exports.HieuxyzRPC = exports.ActivityFlags = void 0;
|
|
4
4
|
const types_1 = require("../gateway/entities/types");
|
|
5
5
|
const RpcImage_1 = require("./RpcImage");
|
|
6
6
|
const logger_1 = require("../utils/logger");
|
|
7
|
+
/**
|
|
8
|
+
* Flags for activities, used with `.setFlags()`.
|
|
9
|
+
* @enum {number}
|
|
10
|
+
*/
|
|
11
|
+
var ActivityFlags;
|
|
12
|
+
(function (ActivityFlags) {
|
|
13
|
+
ActivityFlags[ActivityFlags["INSTANCE"] = 1] = "INSTANCE";
|
|
14
|
+
ActivityFlags[ActivityFlags["JOIN"] = 2] = "JOIN";
|
|
15
|
+
ActivityFlags[ActivityFlags["SPECTATE"] = 4] = "SPECTATE";
|
|
16
|
+
ActivityFlags[ActivityFlags["JOIN_REQUEST"] = 8] = "JOIN_REQUEST";
|
|
17
|
+
ActivityFlags[ActivityFlags["SYNC"] = 16] = "SYNC";
|
|
18
|
+
ActivityFlags[ActivityFlags["PLAY"] = 32] = "PLAY";
|
|
19
|
+
})(ActivityFlags || (exports.ActivityFlags = ActivityFlags = {}));
|
|
7
20
|
/**
|
|
8
21
|
* Class built for creating and managing Discord Rich Presence states.
|
|
9
22
|
*/
|
|
@@ -13,7 +26,7 @@ class HieuxyzRPC {
|
|
|
13
26
|
activity = {};
|
|
14
27
|
assets = {};
|
|
15
28
|
status = 'online';
|
|
16
|
-
applicationId = '1416676323459469363';
|
|
29
|
+
applicationId = '1416676323459469363';
|
|
17
30
|
platform = 'desktop';
|
|
18
31
|
/**
|
|
19
32
|
* Cache for resolved image assets to avoid re-uploading or re-fetching.
|
|
@@ -27,6 +40,49 @@ class HieuxyzRPC {
|
|
|
27
40
|
this.imageService = imageService;
|
|
28
41
|
this.startBackgroundRenewal();
|
|
29
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns the URL of the large image asset, if available.
|
|
45
|
+
* @type {string | null}
|
|
46
|
+
* @readonly
|
|
47
|
+
*/
|
|
48
|
+
get largeImageUrl() {
|
|
49
|
+
if (!this.assets.large_image)
|
|
50
|
+
return null;
|
|
51
|
+
const cacheKey = this.assets.large_image.getCacheKey();
|
|
52
|
+
const resolvedAsset = this.resolvedAssetsCache.get(cacheKey);
|
|
53
|
+
return resolvedAsset ? this._resolveAssetUrl(resolvedAsset) : null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns the URL of the small image asset, if available.
|
|
57
|
+
* @type {string | null}
|
|
58
|
+
* @readonly
|
|
59
|
+
*/
|
|
60
|
+
get smallImageUrl() {
|
|
61
|
+
if (!this.assets.small_image)
|
|
62
|
+
return null;
|
|
63
|
+
const cacheKey = this.assets.small_image.getCacheKey();
|
|
64
|
+
const resolvedAsset = this.resolvedAssetsCache.get(cacheKey);
|
|
65
|
+
return resolvedAsset ? this._resolveAssetUrl(resolvedAsset) : null;
|
|
66
|
+
}
|
|
67
|
+
_resolveAssetUrl(assetKey) {
|
|
68
|
+
if (assetKey.startsWith('mp:')) {
|
|
69
|
+
return `https://media.discordapp.net/${assetKey.substring(3)}`;
|
|
70
|
+
}
|
|
71
|
+
if (assetKey.startsWith('spotify:')) {
|
|
72
|
+
return `https://i.scdn.co/image/${assetKey.substring(8)}`;
|
|
73
|
+
}
|
|
74
|
+
if (assetKey.startsWith('youtube:')) {
|
|
75
|
+
return `https://i.ytimg.com/vi/${assetKey.substring(8)}/hqdefault.jpg`;
|
|
76
|
+
}
|
|
77
|
+
if (assetKey.startsWith('twitch:')) {
|
|
78
|
+
return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${assetKey.substring(7)}.png`;
|
|
79
|
+
}
|
|
80
|
+
// For assets uploaded to a Discord application
|
|
81
|
+
if (this.applicationId && !assetKey.startsWith('http')) {
|
|
82
|
+
return `https://cdn.discordapp.com/app-assets/${this.applicationId}/${assetKey}.png`;
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
30
86
|
_toRpcImage(source) {
|
|
31
87
|
if (typeof source !== 'string') {
|
|
32
88
|
return source;
|
|
@@ -60,7 +116,7 @@ class HieuxyzRPC {
|
|
|
60
116
|
}
|
|
61
117
|
/**
|
|
62
118
|
* Name the operation (first line of RPC).
|
|
63
|
-
* @param name - Name to display.
|
|
119
|
+
* @param {string} name - Name to display.
|
|
64
120
|
* @returns {this}
|
|
65
121
|
*/
|
|
66
122
|
setName(name) {
|
|
@@ -69,7 +125,7 @@ class HieuxyzRPC {
|
|
|
69
125
|
}
|
|
70
126
|
/**
|
|
71
127
|
* Set details for the operation (second line of RPC).
|
|
72
|
-
* @param details - Details to display.
|
|
128
|
+
* @param {string} details - Details to display.
|
|
73
129
|
* @returns {this}
|
|
74
130
|
*/
|
|
75
131
|
setDetails(details) {
|
|
@@ -78,7 +134,7 @@ class HieuxyzRPC {
|
|
|
78
134
|
}
|
|
79
135
|
/**
|
|
80
136
|
* Set the state for the operation (third line of the RPC).
|
|
81
|
-
* @param state - State to display.
|
|
137
|
+
* @param {string} state - State to display.
|
|
82
138
|
* @returns {this}
|
|
83
139
|
*/
|
|
84
140
|
setState(state) {
|
|
@@ -87,7 +143,7 @@ class HieuxyzRPC {
|
|
|
87
143
|
}
|
|
88
144
|
/**
|
|
89
145
|
* Set the activity type.
|
|
90
|
-
* @param type - The type of activity (e.g. 0, 'playing', or ActivityType.Playing).
|
|
146
|
+
* @param {SettableActivityType} type - The type of activity (e.g. 0, 'playing', or ActivityType.Playing).
|
|
91
147
|
* @returns {this}
|
|
92
148
|
*/
|
|
93
149
|
setType(type) {
|
|
@@ -109,8 +165,8 @@ class HieuxyzRPC {
|
|
|
109
165
|
}
|
|
110
166
|
/**
|
|
111
167
|
* Set a start and/or end timestamp for the activity.
|
|
112
|
-
* @param start - Unix timestamp (milliseconds) for start time.
|
|
113
|
-
* @param end - Unix timestamp (milliseconds) for the end time.
|
|
168
|
+
* @param {number} [start] - Unix timestamp (milliseconds) for start time.
|
|
169
|
+
* @param {number} [end] - Unix timestamp (milliseconds) for the end time.
|
|
114
170
|
* @returns {this}
|
|
115
171
|
*/
|
|
116
172
|
setTimestamps(start, end) {
|
|
@@ -119,8 +175,8 @@ class HieuxyzRPC {
|
|
|
119
175
|
}
|
|
120
176
|
/**
|
|
121
177
|
* Set party information for the activity.
|
|
122
|
-
* @param currentSize - Current number of players.
|
|
123
|
-
* @param maxSize - Maximum number of players.
|
|
178
|
+
* @param {number} currentSize - Current number of players.
|
|
179
|
+
* @param {number} maxSize - Maximum number of players.
|
|
124
180
|
* @returns {this}
|
|
125
181
|
*/
|
|
126
182
|
setParty(currentSize, maxSize) {
|
|
@@ -129,8 +185,8 @@ class HieuxyzRPC {
|
|
|
129
185
|
}
|
|
130
186
|
/**
|
|
131
187
|
* Set large image and its caption text.
|
|
132
|
-
* @param source - Image source (URL, asset key, or RpcImage object).
|
|
133
|
-
* @param text - Text displayed when hovering over image.
|
|
188
|
+
* @param {string | RpcImage} source - Image source (URL, asset key, or RpcImage object).
|
|
189
|
+
* @param {string} [text] - Text displayed when hovering over image.
|
|
134
190
|
* @returns {this}
|
|
135
191
|
*/
|
|
136
192
|
setLargeImage(source, text) {
|
|
@@ -141,8 +197,8 @@ class HieuxyzRPC {
|
|
|
141
197
|
}
|
|
142
198
|
/**
|
|
143
199
|
* Set the small image and its caption text.
|
|
144
|
-
* @param source - Image source (URL, asset key, or RpcImage object).
|
|
145
|
-
* @param text - Text displayed when hovering over image.
|
|
200
|
+
* @param {string | RpcImage} source - Image source (URL, asset key, or RpcImage object).
|
|
201
|
+
* @param {string} [text] - Text displayed when hovering over image.
|
|
146
202
|
* @returns {this}
|
|
147
203
|
*/
|
|
148
204
|
setSmallImage(source, text) {
|
|
@@ -153,7 +209,7 @@ class HieuxyzRPC {
|
|
|
153
209
|
}
|
|
154
210
|
/**
|
|
155
211
|
* Set clickable buttons for RPC (up to 2).
|
|
156
|
-
* @param buttons - An array of button objects
|
|
212
|
+
* @param {RpcButton[]} buttons - An array of button objects, each with a `label` and `url`.
|
|
157
213
|
* @returns {this}
|
|
158
214
|
*/
|
|
159
215
|
setButtons(buttons) {
|
|
@@ -162,9 +218,36 @@ class HieuxyzRPC {
|
|
|
162
218
|
this.activity.metadata = { button_urls: validButtons.map((b) => b.url) };
|
|
163
219
|
return this;
|
|
164
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Set secrets for joining, spectating, and matching games.
|
|
223
|
+
* @param {RpcSecrets} secrets - An object with join, spectate, and/or match secrets.
|
|
224
|
+
* @returns {this}
|
|
225
|
+
*/
|
|
226
|
+
setSecrets(secrets) {
|
|
227
|
+
this.activity.secrets = secrets;
|
|
228
|
+
return this;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Set the sync_id, typically used for Spotify track synchronization.
|
|
232
|
+
* @param {string} syncId - The synchronization ID.
|
|
233
|
+
* @returns {this}
|
|
234
|
+
*/
|
|
235
|
+
setSyncId(syncId) {
|
|
236
|
+
this.activity.sync_id = syncId;
|
|
237
|
+
return this;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Set activity flags. Use the ActivityFlags enum for convenience.
|
|
241
|
+
* @param {number} flags - A number representing the bitwise flags.
|
|
242
|
+
* @returns {this}
|
|
243
|
+
*/
|
|
244
|
+
setFlags(flags) {
|
|
245
|
+
this.activity.flags = flags;
|
|
246
|
+
return this;
|
|
247
|
+
}
|
|
165
248
|
/**
|
|
166
249
|
* Set custom application ID for RPC.
|
|
167
|
-
* @param id - Discord app ID (must be an 18 or 19 digit number string).
|
|
250
|
+
* @param {string} id - Discord app ID (must be an 18 or 19 digit number string).
|
|
168
251
|
* @throws {Error} If ID is invalid.
|
|
169
252
|
* @returns {this}
|
|
170
253
|
*/
|
|
@@ -177,7 +260,7 @@ class HieuxyzRPC {
|
|
|
177
260
|
}
|
|
178
261
|
/**
|
|
179
262
|
* Set the user's status (e.g. online, idle, dnd).
|
|
180
|
-
* @param status - Desired state.
|
|
263
|
+
* @param {'online' | 'dnd' | 'idle' | 'invisible' | 'offline'} status - Desired state.
|
|
181
264
|
* @returns {this}
|
|
182
265
|
*/
|
|
183
266
|
setStatus(status) {
|
|
@@ -186,7 +269,7 @@ class HieuxyzRPC {
|
|
|
186
269
|
}
|
|
187
270
|
/**
|
|
188
271
|
* Set the platform on which the activity is running.
|
|
189
|
-
* @param platform - Platform (e.g. 'desktop', 'xbox').
|
|
272
|
+
* @param {DiscordPlatform} platform - Platform (e.g. 'desktop', 'xbox').
|
|
190
273
|
* @returns {this}
|
|
191
274
|
*/
|
|
192
275
|
setPlatform(platform) {
|
|
@@ -195,7 +278,7 @@ class HieuxyzRPC {
|
|
|
195
278
|
}
|
|
196
279
|
/**
|
|
197
280
|
* Marks the activity as a joinable instance for the game.
|
|
198
|
-
* @param instance - Whether this activity is a specific instance.
|
|
281
|
+
* @param {boolean} instance - Whether this activity is a specific instance.
|
|
199
282
|
* @returns {this}
|
|
200
283
|
*/
|
|
201
284
|
setInstance(instance) {
|
|
@@ -223,6 +306,10 @@ class HieuxyzRPC {
|
|
|
223
306
|
this.activity.metadata = undefined;
|
|
224
307
|
return this;
|
|
225
308
|
}
|
|
309
|
+
clearSecrets() {
|
|
310
|
+
this.activity.secrets = undefined;
|
|
311
|
+
return this;
|
|
312
|
+
}
|
|
226
313
|
clearInstance() {
|
|
227
314
|
this.activity.instance = undefined;
|
|
228
315
|
return this;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hieuxyz/rpc",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.11",
|
|
4
4
|
"description": "A Discord Rich Presence library for Node.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
"lint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
17
17
|
"format": "prettier --write \"src/**/*.ts\" \"examples/**/*.ts\""
|
|
18
18
|
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/hieuxyz00/hieuxyz_rpc.git"
|
|
22
|
+
},
|
|
19
23
|
"keywords": [
|
|
20
24
|
"discord",
|
|
21
25
|
"rpc",
|
|
@@ -23,6 +27,10 @@
|
|
|
23
27
|
],
|
|
24
28
|
"author": "hieuxyz",
|
|
25
29
|
"license": "ISC",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/hieuxyz00/hieuxyz_rpc/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/hieuxyz00/hieuxyz_rpc#readme",
|
|
26
34
|
"dependencies": {
|
|
27
35
|
"axios": "^1.12.2",
|
|
28
36
|
"ws": "^8.18.3"
|