@hieuxyz/rpc 1.2.1 → 1.2.3
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 +40 -8
- package/dist/hieuxyz/Client.d.ts +22 -2
- package/dist/hieuxyz/Client.js +54 -5
- package/dist/hieuxyz/rpc/HieuxyzRPC.d.ts +39 -11
- package/dist/hieuxyz/rpc/HieuxyzRPC.js +81 -30
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ An easy-to-use and powerful Discord Rich Presence (RPC) library built for the No
|
|
|
15
15
|
|
|
16
16
|
## Outstanding features
|
|
17
17
|
|
|
18
|
+
- **Multi-RPC Support:** Display multiple activities simultaneously (e.g., Playing a game AND Listening to music) on a single client connection.
|
|
18
19
|
- **Flexible Builder Pattern:** Easily build your RPC state with intuitive chainable methods.
|
|
19
20
|
- **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
21
|
|
|
@@ -105,6 +106,31 @@ start().catch(err => {
|
|
|
105
106
|
});
|
|
106
107
|
```
|
|
107
108
|
|
|
109
|
+
## Multi-RPC Usage
|
|
110
|
+
|
|
111
|
+
You can display multiple statuses at once (Discord limits how these are shown, but the data is sent).
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Configure the default RPC
|
|
115
|
+
client.rpc
|
|
116
|
+
.setName("Visual Studio Code")
|
|
117
|
+
.setState("Coding...")
|
|
118
|
+
.setType(0); // Playing
|
|
119
|
+
|
|
120
|
+
// Create a second RPC instance
|
|
121
|
+
const musicRpc = client.createRPC();
|
|
122
|
+
musicRpc
|
|
123
|
+
.setName("Spotify")
|
|
124
|
+
.setDetails("Listening to music")
|
|
125
|
+
.setApplicationId('12345678901234567') // A different ID is needed than the one already in use
|
|
126
|
+
.setType(2); // Listening
|
|
127
|
+
|
|
128
|
+
await client.rpc.build();
|
|
129
|
+
|
|
130
|
+
// To remove a specific RPC later and free memory:
|
|
131
|
+
// client.removeRPC(musicRpc);
|
|
132
|
+
```
|
|
133
|
+
|
|
108
134
|
## Advanced Usage
|
|
109
135
|
|
|
110
136
|
### Client Spoofing
|
|
@@ -169,8 +195,8 @@ This is the main starting point.
|
|
|
169
195
|
- `options.connectionTimeout` (optional): Timeout in milliseconds for the initial connection. Defaults to `30000`.
|
|
170
196
|
- `client.run()`: Start connecting to Discord Gateway.
|
|
171
197
|
- `client.rpc`: Access the instance of `HieuxyzRPC` to build the state.
|
|
198
|
+
- `client.createRPC()`: Create a new separate RPC instance (Multi-RPC).
|
|
172
199
|
- `client.close(force?: boolean)`: Closes the connection to the Discord Gateway.
|
|
173
|
-
- `force` (optional, boolean): If `true`, the client closes permanently and will not reconnect.
|
|
174
200
|
|
|
175
201
|
### Class `HieuxyzRPC`
|
|
176
202
|
|
|
@@ -179,23 +205,26 @@ Main builder class for RPC.
|
|
|
179
205
|
#### Getter Properties
|
|
180
206
|
- `.largeImageUrl`: Returns the resolved URL for the large image, or `null`.
|
|
181
207
|
- `.smallImageUrl`: Returns the resolved URL for the small image, or `null`.
|
|
208
|
+
- `.currentStatus`: Returns the current status string (e.g. 'online').
|
|
182
209
|
|
|
183
210
|
#### Setter Methods
|
|
184
211
|
- `.setName(string)`: Sets the activity name (first line).
|
|
185
212
|
- `.setDetails(string)`: Sets the activity details (second line).
|
|
186
213
|
- `.setState(string)`: Sets the activity state (third line).
|
|
187
|
-
- `.
|
|
188
|
-
- `.
|
|
189
|
-
- `.
|
|
190
|
-
- `.
|
|
214
|
+
- `.setStatus('online' | 'dnd' | 'idle' | 'invisible' | 'offline')`: Sets the user's presence status.
|
|
215
|
+
- `.setType(ActivityType | string | number)`: Sets the activity type (Playing, Listening, etc.).
|
|
216
|
+
- `.setTimestamps(start?, end?)`: Sets the start and/or end times (ms).
|
|
217
|
+
- `.setParty(current, max, id?)`: Sets the party information.
|
|
218
|
+
- `.setLargeImage(RpcImage | string, text?)`: Sets the large image and its tooltip text.
|
|
219
|
+
- `.setSmallImage(RpcImage | string, text?)`: Sets the small image and its tooltip text.
|
|
191
220
|
- `.setButtons(buttons[])`: Sets up to two clickable buttons. Each button is an object `{ label: string, url: string }`.
|
|
221
|
+
- `.addButton(label, url)`: Adds a single button (max 2).
|
|
192
222
|
- `.setSecrets({ join?, spectate?, match? })`: Sets secrets for game invites.
|
|
193
223
|
- `.setSyncId(string)`: Sets the sync ID, used for features like Spotify track syncing.
|
|
194
224
|
- `.setFlags(number)`: Sets activity flags (e.g., for instanced games). Use the `ActivityFlags` enum.
|
|
195
|
-
- `.setPlatform(platform)`: Sets the platform (`'desktop'`, `'xbox'`, etc.).
|
|
225
|
+
- `.setPlatform(platform)`: Sets the platform (`'desktop'`, `'android'`, `'ios'`, `'xbox'`, etc.).
|
|
196
226
|
- `.setInstance(boolean)`: Marks the activity as a specific, joinable instance.
|
|
197
227
|
- `.setApplicationId(string)`: Sets a custom Application ID.
|
|
198
|
-
- `.setStatus('online' | ...)`: Sets the user's presence status.
|
|
199
228
|
|
|
200
229
|
#### Clearer Methods
|
|
201
230
|
- `.clearDetails()`: Removes activity details.
|
|
@@ -212,14 +241,17 @@ Main builder class for RPC.
|
|
|
212
241
|
- `.build()`: Builds and sends the presence payload to Discord.
|
|
213
242
|
- `.updateRPC()`: Alias for `build()`.
|
|
214
243
|
- `.clear()`: Clears the Rich Presence from the user's profile and resets the builder.
|
|
244
|
+
- `.clearCache()`: Clears the internal asset cache.
|
|
245
|
+
- `.destroy()`: Destroys the RPC instance and stops background tasks.
|
|
215
246
|
|
|
216
247
|
### Types of images
|
|
217
248
|
|
|
218
249
|
- `new ExternalImage(url)`: Use an image from an external URL (will be proxied).
|
|
219
250
|
- `new LocalImage(filePath, fileName?)`: Upload a photo from your device.
|
|
220
|
-
- `new RawImage(assetKey)`: Use an existing asset key directly
|
|
251
|
+
- `new RawImage(assetKey)`: Use an existing asset key directly.
|
|
221
252
|
- `new DiscordImage(key)`: Use assets already on Discord (e.g., `mp:attachments/...`).
|
|
222
253
|
- `new ApplicationImage(name)`: Use an asset name from your Discord Application (requires .setApplicationId()).
|
|
254
|
+
|
|
223
255
|
## Author
|
|
224
256
|
|
|
225
257
|
Developed by **hieuxyz**.
|
package/dist/hieuxyz/Client.d.ts
CHANGED
|
@@ -39,10 +39,14 @@ export interface ClientOptions {
|
|
|
39
39
|
*/
|
|
40
40
|
export declare class Client {
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
* Use this to set your Rich Presence state details.
|
|
42
|
+
* The default RPC instance.
|
|
43
|
+
* Use this to set your main Rich Presence state details.
|
|
44
44
|
*/
|
|
45
45
|
readonly rpc: HieuxyzRPC;
|
|
46
|
+
/**
|
|
47
|
+
* List of all RPC instances managed by this client.
|
|
48
|
+
*/
|
|
49
|
+
private rpcs;
|
|
46
50
|
/**
|
|
47
51
|
* Information about the logged-in user.
|
|
48
52
|
* Populated after run() resolves.
|
|
@@ -57,6 +61,22 @@ export declare class Client {
|
|
|
57
61
|
* @throws {Error} If no token is provided in the options.
|
|
58
62
|
*/
|
|
59
63
|
constructor(options: ClientOptions);
|
|
64
|
+
/**
|
|
65
|
+
* Create a new RPC instance.
|
|
66
|
+
* Use this if you want to display multiple activities simultaneously (Multi-RPC).
|
|
67
|
+
* @returns {HieuxyzRPC} A new RPC builder instance.
|
|
68
|
+
*/
|
|
69
|
+
createRPC(): HieuxyzRPC;
|
|
70
|
+
/**
|
|
71
|
+
* Removes an RPC instance and cleans up its resources.
|
|
72
|
+
* @param {HieuxyzRPC} rpcInstance The RPC instance to remove.
|
|
73
|
+
*/
|
|
74
|
+
removeRPC(rpcInstance: HieuxyzRPC): void;
|
|
75
|
+
/**
|
|
76
|
+
* Aggregates activities from all RPC instances and sends them to Discord.
|
|
77
|
+
* Uses Promise.all for parallel asset resolution.
|
|
78
|
+
*/
|
|
79
|
+
private sendAllActivities;
|
|
60
80
|
/**
|
|
61
81
|
* Displays information about the library.
|
|
62
82
|
*/
|
package/dist/hieuxyz/Client.js
CHANGED
|
@@ -20,10 +20,14 @@ const types_1 = require("./gateway/entities/types");
|
|
|
20
20
|
*/
|
|
21
21
|
class Client {
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
* Use this to set your Rich Presence state details.
|
|
23
|
+
* The default RPC instance.
|
|
24
|
+
* Use this to set your main Rich Presence state details.
|
|
25
25
|
*/
|
|
26
26
|
rpc;
|
|
27
|
+
/**
|
|
28
|
+
* List of all RPC instances managed by this client.
|
|
29
|
+
*/
|
|
30
|
+
rpcs = [];
|
|
27
31
|
/**
|
|
28
32
|
* Information about the logged-in user.
|
|
29
33
|
* Populated after run() resolves.
|
|
@@ -48,14 +52,59 @@ class Client {
|
|
|
48
52
|
properties: options.properties,
|
|
49
53
|
connectionTimeout: options.connectionTimeout,
|
|
50
54
|
});
|
|
51
|
-
this.rpc =
|
|
55
|
+
this.rpc = this.createRPC();
|
|
52
56
|
this.printAbout();
|
|
53
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Create a new RPC instance.
|
|
60
|
+
* Use this if you want to display multiple activities simultaneously (Multi-RPC).
|
|
61
|
+
* @returns {HieuxyzRPC} A new RPC builder instance.
|
|
62
|
+
*/
|
|
63
|
+
createRPC() {
|
|
64
|
+
const newRpc = new HieuxyzRPC_1.HieuxyzRPC(this.imageService, async () => {
|
|
65
|
+
await this.sendAllActivities();
|
|
66
|
+
});
|
|
67
|
+
this.rpcs.push(newRpc);
|
|
68
|
+
return newRpc;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Removes an RPC instance and cleans up its resources.
|
|
72
|
+
* @param {HieuxyzRPC} rpcInstance The RPC instance to remove.
|
|
73
|
+
*/
|
|
74
|
+
removeRPC(rpcInstance) {
|
|
75
|
+
const index = this.rpcs.indexOf(rpcInstance);
|
|
76
|
+
if (index > -1) {
|
|
77
|
+
rpcInstance.destroy();
|
|
78
|
+
this.rpcs.splice(index, 1);
|
|
79
|
+
this.sendAllActivities();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Aggregates activities from all RPC instances and sends them to Discord.
|
|
84
|
+
* Uses Promise.all for parallel asset resolution.
|
|
85
|
+
*/
|
|
86
|
+
async sendAllActivities() {
|
|
87
|
+
const potentialActivities = await Promise.all(this.rpcs.map((rpc) => rpc.buildActivity()));
|
|
88
|
+
const activities = potentialActivities.filter((a) => a !== null);
|
|
89
|
+
let status = 'online';
|
|
90
|
+
for (let i = this.rpcs.length - 1; i >= 0; i--) {
|
|
91
|
+
if (this.rpcs[i].currentStatus) {
|
|
92
|
+
status = this.rpcs[i].currentStatus;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
this.websocket.sendActivity({
|
|
97
|
+
since: 0,
|
|
98
|
+
activities: activities,
|
|
99
|
+
status: status,
|
|
100
|
+
afk: true,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
54
103
|
/**
|
|
55
104
|
* Displays information about the library.
|
|
56
105
|
*/
|
|
57
106
|
printAbout() {
|
|
58
|
-
const version = '1.2.
|
|
107
|
+
const version = '1.2.3';
|
|
59
108
|
console.log(`
|
|
60
109
|
_ _
|
|
61
110
|
| |__ (_) ___ _ ___ ___ _ ______
|
|
@@ -200,7 +249,7 @@ class Client {
|
|
|
200
249
|
* even if `alwaysReconnect` is enabled. Defaults to false.
|
|
201
250
|
*/
|
|
202
251
|
close(force = false) {
|
|
203
|
-
this.rpc.
|
|
252
|
+
this.rpcs.forEach((rpc) => rpc.destroy());
|
|
204
253
|
this.websocket.close(force);
|
|
205
254
|
}
|
|
206
255
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { SettableActivityType } from '../gateway/entities/types';
|
|
1
|
+
import { Activity, SettableActivityType } from '../gateway/entities/types';
|
|
3
2
|
import { ImageService } from './ImageService';
|
|
4
3
|
import { RpcImage } from './RpcImage';
|
|
5
4
|
/**
|
|
@@ -24,12 +23,13 @@ interface RpcSecrets {
|
|
|
24
23
|
match?: string;
|
|
25
24
|
}
|
|
26
25
|
export type DiscordPlatform = 'desktop' | 'android' | 'ios' | 'samsung' | 'xbox' | 'ps4' | 'ps5' | 'embedded';
|
|
26
|
+
type UpdateCallback = () => Promise<void>;
|
|
27
27
|
/**
|
|
28
28
|
* Class built for creating and managing Discord Rich Presence states.
|
|
29
29
|
*/
|
|
30
30
|
export declare class HieuxyzRPC {
|
|
31
|
-
private websocket;
|
|
32
31
|
private imageService;
|
|
32
|
+
private onUpdate;
|
|
33
33
|
private activity;
|
|
34
34
|
private assets;
|
|
35
35
|
private status;
|
|
@@ -41,13 +41,17 @@ export declare class HieuxyzRPC {
|
|
|
41
41
|
* Value: The resolved asset key (e.g., "mp:attachments/...").
|
|
42
42
|
*/
|
|
43
43
|
private resolvedAssetsCache;
|
|
44
|
+
/**
|
|
45
|
+
* Maximum number of items in cache to prevent memory leaks/bloat over long runtime.
|
|
46
|
+
*/
|
|
47
|
+
private readonly MAX_CACHE_SIZE;
|
|
44
48
|
private renewalInterval;
|
|
45
49
|
/**
|
|
46
50
|
* Cache for Application Assets (Bot Assets).
|
|
47
51
|
* Map<ApplicationID, Map<AssetName, AssetID>>
|
|
48
52
|
*/
|
|
49
53
|
private applicationAssetsCache;
|
|
50
|
-
constructor(
|
|
54
|
+
constructor(imageService: ImageService, onUpdate: UpdateCallback);
|
|
51
55
|
/**
|
|
52
56
|
* Returns the URL of the large image asset, if available.
|
|
53
57
|
* @type {string | null}
|
|
@@ -99,9 +103,10 @@ export declare class HieuxyzRPC {
|
|
|
99
103
|
* Set party information for the activity.
|
|
100
104
|
* @param {number} currentSize - Current number of players.
|
|
101
105
|
* @param {number} maxSize - Maximum number of players.
|
|
106
|
+
* @param {string} [id] - Optional custom party ID. Defaults to 'hieuxyz'.
|
|
102
107
|
* @returns {this}
|
|
103
108
|
*/
|
|
104
|
-
setParty(currentSize: number, maxSize: number): this;
|
|
109
|
+
setParty(currentSize: number, maxSize: number, id?: string): this;
|
|
105
110
|
/**
|
|
106
111
|
* Set large image and its caption text.
|
|
107
112
|
* @param {string | RpcImage} source - Image source (URL, asset key, Asset Name or RpcImage object).
|
|
@@ -116,8 +121,16 @@ export declare class HieuxyzRPC {
|
|
|
116
121
|
* @returns {this}
|
|
117
122
|
*/
|
|
118
123
|
setSmallImage(source: string | RpcImage, text?: string): this;
|
|
124
|
+
/**
|
|
125
|
+
* Add a single button to the activity.
|
|
126
|
+
* @param {string} label - The text displayed on the button.
|
|
127
|
+
* @param {string} url - The URL opened when the button is clicked.
|
|
128
|
+
* @returns {this}
|
|
129
|
+
*/
|
|
130
|
+
addButton(label: string, url: string): this;
|
|
119
131
|
/**
|
|
120
132
|
* Set clickable buttons for RPC (up to 2).
|
|
133
|
+
* This will overwrite any existing buttons.
|
|
121
134
|
* @param {RpcButton[]} buttons - An array of button objects, each with a `label` and `url`.
|
|
122
135
|
* @returns {this}
|
|
123
136
|
*/
|
|
@@ -186,9 +199,14 @@ export declare class HieuxyzRPC {
|
|
|
186
199
|
*/
|
|
187
200
|
private ensureAppAssetsLoaded;
|
|
188
201
|
private resolveImage;
|
|
189
|
-
private buildActivity;
|
|
190
202
|
/**
|
|
191
|
-
*
|
|
203
|
+
* Publicly accessible method to build the Activity object.
|
|
204
|
+
* Used by Client to aggregate activities from multiple RPC instances.
|
|
205
|
+
* @returns {Promise<Activity | null>} The constructed activity or null if empty.
|
|
206
|
+
*/
|
|
207
|
+
buildActivity(): Promise<Activity | null>;
|
|
208
|
+
/**
|
|
209
|
+
* Build the final Rich Presence payload and notify the Client to send it to Discord.
|
|
192
210
|
* @returns {Promise<void>}
|
|
193
211
|
*/
|
|
194
212
|
build(): Promise<void>;
|
|
@@ -199,11 +217,21 @@ export declare class HieuxyzRPC {
|
|
|
199
217
|
*/
|
|
200
218
|
updateRPC(): Promise<void>;
|
|
201
219
|
/**
|
|
202
|
-
* Clears the current Rich Presence from
|
|
203
|
-
* This sends an empty activity payload to Discord and then resets all configured
|
|
204
|
-
* options (name, details, images, etc.) to their default values, allowing you
|
|
205
|
-
* to build a new presence from scratch.
|
|
220
|
+
* Clears the current Rich Presence from the user's profile and resets the builder.
|
|
206
221
|
*/
|
|
207
222
|
clear(): void;
|
|
223
|
+
/**
|
|
224
|
+
* Manually clear the asset cache to free memory.
|
|
225
|
+
*/
|
|
226
|
+
clearCache(): void;
|
|
227
|
+
/**
|
|
228
|
+
* Permanently destroy this RPC instance.
|
|
229
|
+
* Stops renewal timers and clears memory.
|
|
230
|
+
*/
|
|
231
|
+
destroy(): void;
|
|
232
|
+
/**
|
|
233
|
+
* Get the current status set for this RPC instance.
|
|
234
|
+
*/
|
|
235
|
+
get currentStatus(): "online" | "dnd" | "idle" | "invisible" | "offline";
|
|
208
236
|
}
|
|
209
237
|
export {};
|
|
@@ -21,8 +21,8 @@ var ActivityFlags;
|
|
|
21
21
|
* Class built for creating and managing Discord Rich Presence states.
|
|
22
22
|
*/
|
|
23
23
|
class HieuxyzRPC {
|
|
24
|
-
websocket;
|
|
25
24
|
imageService;
|
|
25
|
+
onUpdate;
|
|
26
26
|
activity = {};
|
|
27
27
|
assets = {};
|
|
28
28
|
status = 'online';
|
|
@@ -34,15 +34,19 @@ class HieuxyzRPC {
|
|
|
34
34
|
* Value: The resolved asset key (e.g., "mp:attachments/...").
|
|
35
35
|
*/
|
|
36
36
|
resolvedAssetsCache = new Map();
|
|
37
|
+
/**
|
|
38
|
+
* Maximum number of items in cache to prevent memory leaks/bloat over long runtime.
|
|
39
|
+
*/
|
|
40
|
+
MAX_CACHE_SIZE = 50;
|
|
37
41
|
renewalInterval = null;
|
|
38
42
|
/**
|
|
39
43
|
* Cache for Application Assets (Bot Assets).
|
|
40
44
|
* Map<ApplicationID, Map<AssetName, AssetID>>
|
|
41
45
|
*/
|
|
42
46
|
applicationAssetsCache = new Map();
|
|
43
|
-
constructor(
|
|
44
|
-
this.websocket = websocket;
|
|
47
|
+
constructor(imageService, onUpdate) {
|
|
45
48
|
this.imageService = imageService;
|
|
49
|
+
this.onUpdate = onUpdate;
|
|
46
50
|
this.startBackgroundRenewal();
|
|
47
51
|
}
|
|
48
52
|
/**
|
|
@@ -184,10 +188,11 @@ class HieuxyzRPC {
|
|
|
184
188
|
* Set party information for the activity.
|
|
185
189
|
* @param {number} currentSize - Current number of players.
|
|
186
190
|
* @param {number} maxSize - Maximum number of players.
|
|
191
|
+
* @param {string} [id] - Optional custom party ID. Defaults to 'hieuxyz'.
|
|
187
192
|
* @returns {this}
|
|
188
193
|
*/
|
|
189
|
-
setParty(currentSize, maxSize) {
|
|
190
|
-
this.activity.party = { id:
|
|
194
|
+
setParty(currentSize, maxSize, id = 'hieuxyz') {
|
|
195
|
+
this.activity.party = { id: id, size: [currentSize, maxSize] };
|
|
191
196
|
return this;
|
|
192
197
|
}
|
|
193
198
|
/**
|
|
@@ -214,8 +219,33 @@ class HieuxyzRPC {
|
|
|
214
219
|
this.assets.small_text = this.sanitize(text);
|
|
215
220
|
return this;
|
|
216
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Add a single button to the activity.
|
|
224
|
+
* @param {string} label - The text displayed on the button.
|
|
225
|
+
* @param {string} url - The URL opened when the button is clicked.
|
|
226
|
+
* @returns {this}
|
|
227
|
+
*/
|
|
228
|
+
addButton(label, url) {
|
|
229
|
+
if (!this.activity.buttons) {
|
|
230
|
+
this.activity.buttons = [];
|
|
231
|
+
}
|
|
232
|
+
if (!this.activity.metadata) {
|
|
233
|
+
this.activity.metadata = { button_urls: [] };
|
|
234
|
+
}
|
|
235
|
+
if (!this.activity.metadata.button_urls) {
|
|
236
|
+
this.activity.metadata.button_urls = [];
|
|
237
|
+
}
|
|
238
|
+
if (this.activity.buttons.length >= 2) {
|
|
239
|
+
logger_1.logger.warn('Cannot add more than 2 buttons. Button ignored.');
|
|
240
|
+
return this;
|
|
241
|
+
}
|
|
242
|
+
this.activity.buttons.push(this.sanitize(label, 32));
|
|
243
|
+
this.activity.metadata.button_urls.push(url);
|
|
244
|
+
return this;
|
|
245
|
+
}
|
|
217
246
|
/**
|
|
218
247
|
* Set clickable buttons for RPC (up to 2).
|
|
248
|
+
* This will overwrite any existing buttons.
|
|
219
249
|
* @param {RpcButton[]} buttons - An array of button objects, each with a `label` and `url`.
|
|
220
250
|
* @returns {this}
|
|
221
251
|
*/
|
|
@@ -350,7 +380,7 @@ class HieuxyzRPC {
|
|
|
350
380
|
async renewAssetIfNeeded(cacheKey, assetKey) {
|
|
351
381
|
const expiryTimeMs = this.getExpiryTime(assetKey);
|
|
352
382
|
if (expiryTimeMs && expiryTimeMs < Date.now() + 3600000) {
|
|
353
|
-
|
|
383
|
+
// logger.info(`Asset ${cacheKey} is expiring soon. Renewing...`);
|
|
354
384
|
const assetId = assetKey.split('mp:attachments/')[1];
|
|
355
385
|
const newAsset = await this.imageService.renewImage(assetId);
|
|
356
386
|
if (newAsset) {
|
|
@@ -366,7 +396,7 @@ class HieuxyzRPC {
|
|
|
366
396
|
clearInterval(this.renewalInterval);
|
|
367
397
|
}
|
|
368
398
|
this.renewalInterval = setInterval(async () => {
|
|
369
|
-
|
|
399
|
+
// logger.info('Running background asset renewal check...');
|
|
370
400
|
for (const [cacheKey, assetKey] of this.resolvedAssetsCache.entries()) {
|
|
371
401
|
await this.renewAssetIfNeeded(cacheKey, assetKey);
|
|
372
402
|
}
|
|
@@ -379,7 +409,7 @@ class HieuxyzRPC {
|
|
|
379
409
|
if (this.renewalInterval) {
|
|
380
410
|
clearInterval(this.renewalInterval);
|
|
381
411
|
this.renewalInterval = null;
|
|
382
|
-
|
|
412
|
+
// logger.info('Stopped background asset renewal process.');
|
|
383
413
|
}
|
|
384
414
|
}
|
|
385
415
|
/**
|
|
@@ -412,6 +442,12 @@ class HieuxyzRPC {
|
|
|
412
442
|
}
|
|
413
443
|
return assetId;
|
|
414
444
|
}
|
|
445
|
+
if (this.resolvedAssetsCache.size >= this.MAX_CACHE_SIZE && !this.resolvedAssetsCache.has(cacheKey)) {
|
|
446
|
+
const oldestKey = this.resolvedAssetsCache.keys().next().value;
|
|
447
|
+
if (oldestKey) {
|
|
448
|
+
this.resolvedAssetsCache.delete(oldestKey);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
415
451
|
const cachedAsset = this.resolvedAssetsCache.get(cacheKey);
|
|
416
452
|
if (cachedAsset) {
|
|
417
453
|
return await this.renewAssetIfNeeded(cacheKey, cachedAsset);
|
|
@@ -425,7 +461,15 @@ class HieuxyzRPC {
|
|
|
425
461
|
}
|
|
426
462
|
return resolvedAsset;
|
|
427
463
|
}
|
|
464
|
+
/**
|
|
465
|
+
* Publicly accessible method to build the Activity object.
|
|
466
|
+
* Used by Client to aggregate activities from multiple RPC instances.
|
|
467
|
+
* @returns {Promise<Activity | null>} The constructed activity or null if empty.
|
|
468
|
+
*/
|
|
428
469
|
async buildActivity() {
|
|
470
|
+
if (Object.keys(this.activity).length === 0 && !this.assets.large_image && !this.assets.small_image) {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
429
473
|
const large_image = await this.resolveImage(this.assets.large_image);
|
|
430
474
|
const small_image = await this.resolveImage(this.assets.small_image);
|
|
431
475
|
const finalAssets = {
|
|
@@ -449,18 +493,11 @@ class HieuxyzRPC {
|
|
|
449
493
|
return this.cleanupNulls(finalActivity);
|
|
450
494
|
}
|
|
451
495
|
/**
|
|
452
|
-
* Build the final Rich Presence payload and send it to Discord.
|
|
496
|
+
* Build the final Rich Presence payload and notify the Client to send it to Discord.
|
|
453
497
|
* @returns {Promise<void>}
|
|
454
498
|
*/
|
|
455
499
|
async build() {
|
|
456
|
-
|
|
457
|
-
const presencePayload = {
|
|
458
|
-
since: 0,
|
|
459
|
-
activities: [activity],
|
|
460
|
-
status: this.status,
|
|
461
|
-
afk: true,
|
|
462
|
-
};
|
|
463
|
-
this.websocket.sendActivity(presencePayload);
|
|
500
|
+
await this.onUpdate();
|
|
464
501
|
}
|
|
465
502
|
/**
|
|
466
503
|
* Sends an update to an existing RPC.
|
|
@@ -471,25 +508,39 @@ class HieuxyzRPC {
|
|
|
471
508
|
await this.build();
|
|
472
509
|
}
|
|
473
510
|
/**
|
|
474
|
-
* Clears the current Rich Presence from
|
|
475
|
-
* This sends an empty activity payload to Discord and then resets all configured
|
|
476
|
-
* options (name, details, images, etc.) to their default values, allowing you
|
|
477
|
-
* to build a new presence from scratch.
|
|
511
|
+
* Clears the current Rich Presence from the user's profile and resets the builder.
|
|
478
512
|
*/
|
|
479
513
|
clear() {
|
|
480
|
-
const clearPayload = {
|
|
481
|
-
since: 0,
|
|
482
|
-
activities: [],
|
|
483
|
-
status: this.status,
|
|
484
|
-
afk: true,
|
|
485
|
-
};
|
|
486
|
-
this.websocket.sendActivity(clearPayload);
|
|
487
|
-
logger_1.logger.info('Rich Presence cleared from Discord.');
|
|
488
514
|
this.activity = {};
|
|
489
515
|
this.assets = {};
|
|
490
516
|
this.applicationId = '1416676323459469363'; // Reset to default
|
|
491
517
|
this.platform = 'desktop'; // Reset to default
|
|
492
|
-
logger_1.logger.info('RPC
|
|
518
|
+
logger_1.logger.info('RPC instance cleared.');
|
|
519
|
+
this.onUpdate();
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Manually clear the asset cache to free memory.
|
|
523
|
+
*/
|
|
524
|
+
clearCache() {
|
|
525
|
+
this.resolvedAssetsCache.clear();
|
|
526
|
+
this.applicationAssetsCache.clear();
|
|
527
|
+
logger_1.logger.info('RPC Asset cache has been cleared.');
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Permanently destroy this RPC instance.
|
|
531
|
+
* Stops renewal timers and clears memory.
|
|
532
|
+
*/
|
|
533
|
+
destroy() {
|
|
534
|
+
this.stopBackgroundRenewal();
|
|
535
|
+
this.clearCache();
|
|
536
|
+
this.activity = {};
|
|
537
|
+
this.assets = {};
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Get the current status set for this RPC instance.
|
|
541
|
+
*/
|
|
542
|
+
get currentStatus() {
|
|
543
|
+
return this.status;
|
|
493
544
|
}
|
|
494
545
|
}
|
|
495
546
|
exports.HieuxyzRPC = HieuxyzRPC;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hieuxyz/rpc",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "A Discord Rich Presence library for Node.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,8 +10,15 @@
|
|
|
10
10
|
"LICENSE"
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
|
+
"tsx": "tsx",
|
|
14
|
+
"esbuild": "esbuild",
|
|
15
|
+
"check": "tsc --noEmit",
|
|
16
|
+
"dev": "tsx --env-file=.env examples/main.ts",
|
|
17
|
+
"dev:ts": "node -r ts-node/register --env-file=.env examples/main.ts",
|
|
13
18
|
"build": "tsc",
|
|
14
|
-
"
|
|
19
|
+
"build:es": "esbuild src/index.ts --bundle --platform=node --minify --outfile=dist/index.ts",
|
|
20
|
+
"build:ex": "esbuild examples/main.ts --bundle --platform=node --minify --outfile=dist/main.js",
|
|
21
|
+
"start:ex": "node --env-file=.env dist/main.js",
|
|
15
22
|
"lint": "eslint \"src/**/*.ts\" --report-unused-disable-directives --max-warnings 0",
|
|
16
23
|
"lint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
17
24
|
"format": "prettier --write \"src/**/*.ts\" \"examples/**/*.ts\""
|
|
@@ -38,11 +45,13 @@
|
|
|
38
45
|
"devDependencies": {
|
|
39
46
|
"@types/node": "^25.0.3",
|
|
40
47
|
"@types/ws": "^8.18.1",
|
|
48
|
+
"esbuild": "^0.27.2",
|
|
41
49
|
"eslint": "^9.39.2",
|
|
42
50
|
"eslint-config-prettier": "^10.1.8",
|
|
43
51
|
"eslint-plugin-prettier": "^5.5.4",
|
|
44
52
|
"prettier": "^3.7.4",
|
|
45
53
|
"ts-node": "^10.9.2",
|
|
54
|
+
"tsx": "^4.21.0",
|
|
46
55
|
"typescript": "^5.9.3",
|
|
47
56
|
"typescript-eslint": "^8.51.0"
|
|
48
57
|
}
|