@hieuxyz/rpc 1.2.4 → 1.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hieuxyz/rpc",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "description": "A Discord Rich Presence library for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -39,20 +39,21 @@
39
39
  },
40
40
  "homepage": "https://github.com/hieuxyz00/hieuxyz_rpc#readme",
41
41
  "dependencies": {
42
- "axios": "^1.13.2",
43
- "ws": "^8.18.3"
42
+ "axios": "^1.13.6",
43
+ "ws": "^8.19.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@types/node": "^25.0.3",
46
+ "@eslint/js": "^10.0.1",
47
+ "@types/node": "^25.3.3",
47
48
  "@types/ws": "^8.18.1",
48
- "esbuild": "^0.27.2",
49
- "eslint": "^9.39.2",
49
+ "esbuild": "^0.27.3",
50
+ "eslint": "^10.0.2",
50
51
  "eslint-config-prettier": "^10.1.8",
51
- "eslint-plugin-prettier": "^5.5.4",
52
- "prettier": "^3.7.4",
52
+ "eslint-plugin-prettier": "^5.5.5",
53
+ "prettier": "^3.8.1",
53
54
  "ts-node": "^10.9.2",
54
55
  "tsx": "^4.21.0",
55
56
  "typescript": "^5.9.3",
56
- "typescript-eslint": "^8.51.0"
57
+ "typescript-eslint": "^8.56.1"
57
58
  }
58
59
  }
@@ -1,100 +0,0 @@
1
- import { HieuxyzRPC } from './rpc/HieuxyzRPC';
2
- import { ClientProperties } from './gateway/entities/identify';
3
- import { DiscordUser } from './gateway/entities/types';
4
- /**
5
- * Option to initialize Client.
6
- */
7
- export interface ClientOptions {
8
- /** Your Discord user token. */
9
- token: string;
10
- /** (Optional) Base URL of the image proxy service. */
11
- apiBaseUrl?: string;
12
- /**
13
- * (Optional) If true, the client will attempt to reconnect even after a normal close (code 1000).
14
- * Defaults to false.
15
- */
16
- alwaysReconnect?: boolean;
17
- /**
18
- * (Optional) Client properties to send to Discord gateway.
19
- * Used for client spoofing (e.g., appearing as on mobile).
20
- */
21
- properties?: ClientProperties;
22
- /**
23
- * (Optional) The timeout in milliseconds for the initial gateway connection.
24
- * Defaults to 30000 (30 seconds).
25
- */
26
- connectionTimeout?: number;
27
- }
28
- /**
29
- * The main Client class for interacting with Discord Rich Presence.
30
- * This is the starting point for creating and managing your RPC state.
31
- * @example
32
- * const client = new Client({
33
- * token: "YOUR_DISCORD_TOKEN",
34
- * alwaysReconnect: true // Keep the RPC alive no matter what
35
- * });
36
- * await client.run();
37
- * client.rpc.setName("Visual Studio Code");
38
- * await client.rpc.build();
39
- */
40
- export declare class Client {
41
- /**
42
- * The default RPC instance.
43
- * Use this to set your main Rich Presence state details.
44
- */
45
- readonly rpc: HieuxyzRPC;
46
- /**
47
- * List of all RPC instances managed by this client.
48
- */
49
- private rpcs;
50
- /**
51
- * Information about the logged-in user.
52
- * Populated after run() resolves.
53
- */
54
- user: DiscordUser | null;
55
- private readonly websocket;
56
- private readonly imageService;
57
- private readonly token;
58
- /**
59
- * Create a new Client instance.
60
- * @param {ClientOptions} options - Options to configure the client.
61
- * @throws {Error} If no token is provided in the options.
62
- */
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;
80
- /**
81
- * Displays information about the library.
82
- */
83
- private printAbout;
84
- /**
85
- * Connect to Discord Gateway and prepare the client for RPC updates.
86
- * This method must be called before sending any Rich Presence updates.
87
- * @returns {Promise<DiscordUser>} A promise will be resolved when the client is ready.
88
- */
89
- run(): Promise<DiscordUser>;
90
- private formatters;
91
- private formatFlags;
92
- private printDynamicTree;
93
- private logUserProfile;
94
- /**
95
- * Close the connection to Discord Gateway.
96
- * @param {boolean} [force=false] - If true, the client closes permanently and will not reconnect.
97
- * even if `alwaysReconnect` is enabled. Defaults to false.
98
- */
99
- close(force?: boolean): void;
100
- }
@@ -1,256 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Client = void 0;
4
- const DiscordWebSocket_1 = require("./gateway/DiscordWebSocket");
5
- const HieuxyzRPC_1 = require("./rpc/HieuxyzRPC");
6
- const ImageService_1 = require("./rpc/ImageService");
7
- const logger_1 = require("./utils/logger");
8
- const types_1 = require("./gateway/entities/types");
9
- /**
10
- * The main Client class for interacting with Discord Rich Presence.
11
- * This is the starting point for creating and managing your RPC state.
12
- * @example
13
- * const client = new Client({
14
- * token: "YOUR_DISCORD_TOKEN",
15
- * alwaysReconnect: true // Keep the RPC alive no matter what
16
- * });
17
- * await client.run();
18
- * client.rpc.setName("Visual Studio Code");
19
- * await client.rpc.build();
20
- */
21
- class Client {
22
- /**
23
- * The default RPC instance.
24
- * Use this to set your main Rich Presence state details.
25
- */
26
- rpc;
27
- /**
28
- * List of all RPC instances managed by this client.
29
- */
30
- rpcs = [];
31
- /**
32
- * Information about the logged-in user.
33
- * Populated after run() resolves.
34
- */
35
- user = null;
36
- websocket;
37
- imageService;
38
- token;
39
- /**
40
- * Create a new Client instance.
41
- * @param {ClientOptions} options - Options to configure the client.
42
- * @throws {Error} If no token is provided in the options.
43
- */
44
- constructor(options) {
45
- if (!options.token) {
46
- throw new Error('Tokens are required to connect to Discord.');
47
- }
48
- this.token = options.token;
49
- this.imageService = new ImageService_1.ImageService(options.apiBaseUrl);
50
- this.websocket = new DiscordWebSocket_1.DiscordWebSocket(this.token, {
51
- alwaysReconnect: options.alwaysReconnect ?? false,
52
- properties: options.properties,
53
- connectionTimeout: options.connectionTimeout,
54
- });
55
- this.rpc = this.createRPC();
56
- this.printAbout();
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
- }
103
- /**
104
- * Displays information about the library.
105
- */
106
- printAbout() {
107
- const version = '1.2.3';
108
- console.log(`
109
- _ _
110
- | |__ (_) ___ _ ___ ___ _ ______
111
- | '_ \\| |/ _ \\ | | \\ \\/ / | | |_ /
112
- | | | | | __/ |_| |> <| |_| |/ /
113
- |_| |_|_|\\___|\\__,_/_/\\_\\\\__, /___|
114
- |___/
115
- @hieuxyz/rpc v${version}
116
- A powerful Discord Rich Presence library.
117
- Developed by: hieuxyz
118
- `);
119
- }
120
- /**
121
- * Connect to Discord Gateway and prepare the client for RPC updates.
122
- * This method must be called before sending any Rich Presence updates.
123
- * @returns {Promise<DiscordUser>} A promise will be resolved when the client is ready.
124
- */
125
- async run() {
126
- this.websocket.connect();
127
- logger_1.logger.info('Waiting for Discord session to be ready...');
128
- const user = await this.websocket.readyPromise;
129
- this.user = user;
130
- this.logUserProfile(user);
131
- logger_1.logger.info('Client is ready to send Rich Presence updates.');
132
- return user;
133
- }
134
- formatters = {
135
- email: (val) => (val ? `\x1b[90m<Hidden>\x1b[0m` : 'null'),
136
- phone: (val) => (val ? `\x1b[90m<Hidden>\x1b[0m` : 'null'),
137
- avatar: (val, parent) => {
138
- if (!val)
139
- return 'null';
140
- const ext = val.startsWith('a_') ? 'gif' : 'png';
141
- const userId = parent?.id;
142
- const url = userId ? `https://cdn.discordapp.com/avatars/${userId}/${val}.${ext}` : '';
143
- return `"${val}" ${url ? `(\x1b[34m${url}\x1b[0m)` : ''}`;
144
- },
145
- banner: (val, parent) => {
146
- if (!val)
147
- return 'null';
148
- const ext = val.startsWith('a_') ? 'gif' : 'png';
149
- const userId = parent?.id;
150
- const url = userId ? `https://cdn.discordapp.com/banners/${userId}/${val}.${ext}` : '';
151
- return `"${val}" ${url ? `(\x1b[34m${url}\x1b[0m)` : ''}`;
152
- },
153
- asset: (val) => {
154
- const url = `https://cdn.discordapp.com/avatar-decoration-presets/${val}.png`;
155
- return `"${val}" (\x1b[34m${url}\x1b[0m)`;
156
- },
157
- accent_color: (val) => `${val} (\x1b[33m#${val.toString(16).padStart(6, '0').toUpperCase()}\x1b[0m)`,
158
- banner_color: (val) => `\x1b[33m${val}\x1b[0m`,
159
- expires_at: (val) => (val ? `${val} (${new Date(val).toLocaleString()})` : 'Never'),
160
- premium_type: (val) => {
161
- const map = { 0: 'None', 1: 'Classic', 2: 'Nitro', 3: 'Basic' };
162
- return `${val} (\x1b[32m${map[val] || 'Unknown'}\x1b[0m)`;
163
- },
164
- flags: (val) => this.formatFlags(val),
165
- public_flags: (val) => this.formatFlags(val),
166
- purchased_flags: (val) => `\x1b[33m${val}\x1b[0m`,
167
- };
168
- formatFlags(flags) {
169
- const flagNames = [];
170
- if (flags & types_1.UserFlags.STAFF)
171
- flagNames.push('Staff');
172
- if (flags & types_1.UserFlags.PARTNER)
173
- flagNames.push('Partner');
174
- if (flags & types_1.UserFlags.HYPESQUAD)
175
- flagNames.push('HypeSquad');
176
- if (flags & types_1.UserFlags.BUG_HUNTER_LEVEL_1)
177
- flagNames.push('BugHunter I');
178
- if (flags & types_1.UserFlags.HYPESQUAD_ONLINE_HOUSE_1)
179
- flagNames.push('Bravery');
180
- if (flags & types_1.UserFlags.HYPESQUAD_ONLINE_HOUSE_2)
181
- flagNames.push('Brilliance');
182
- if (flags & types_1.UserFlags.HYPESQUAD_ONLINE_HOUSE_3)
183
- flagNames.push('Balance');
184
- if (flags & types_1.UserFlags.PREMIUM_EARLY_SUPPORTER)
185
- flagNames.push('EarlySupporter');
186
- if (flags & types_1.UserFlags.BUG_HUNTER_LEVEL_2)
187
- flagNames.push('BugHunter II');
188
- if (flags & types_1.UserFlags.VERIFIED_DEVELOPER)
189
- flagNames.push('VerifiedDev');
190
- if (flags & types_1.UserFlags.CERTIFIED_MODERATOR)
191
- flagNames.push('CertifiedMod');
192
- if (flags & types_1.UserFlags.ACTIVE_DEVELOPER)
193
- flagNames.push('ActiveDev');
194
- return `${flags} \x1b[36m[${flagNames.length > 0 ? flagNames.join(', ') : 'None'}]\x1b[0m`;
195
- }
196
- printDynamicTree(obj, prefix = '') {
197
- const entries = Object.entries(obj);
198
- entries.forEach(([key, value], index) => {
199
- const isLastItem = index === entries.length - 1;
200
- const connector = isLastItem ? '└── ' : '├── ';
201
- const childPrefix = prefix + (isLastItem ? ' ' : '│ ');
202
- let displayValue = '';
203
- let isObject = false;
204
- if (value === null) {
205
- displayValue = '\x1b[90mnull\x1b[0m';
206
- }
207
- else if (typeof value === 'object' && !Array.isArray(value)) {
208
- isObject = true;
209
- console.log(`${prefix}${connector}\x1b[1m${key}\x1b[0m`);
210
- this.printDynamicTree(value, childPrefix);
211
- }
212
- else if (Array.isArray(value)) {
213
- if (value.length > 0 && typeof value[0] !== 'object') {
214
- displayValue = `[ ${value.join(', ')} ]`;
215
- }
216
- else {
217
- displayValue = `[Array(${value.length})]`;
218
- }
219
- }
220
- else {
221
- if (this.formatters[key]) {
222
- displayValue = this.formatters[key](value, obj);
223
- }
224
- else {
225
- if (typeof value === 'string')
226
- displayValue = `"\x1b[32m${value}\x1b[0m"`;
227
- else if (typeof value === 'boolean')
228
- displayValue = value ? '\x1b[32mtrue\x1b[0m' : '\x1b[31mfalse\x1b[0m';
229
- else if (typeof value === 'number')
230
- displayValue = `\x1b[33m${value}\x1b[0m`;
231
- else
232
- displayValue = String(value);
233
- }
234
- }
235
- if (!isObject) {
236
- console.log(`${prefix}${connector}${key}: ${displayValue}`);
237
- }
238
- });
239
- }
240
- logUserProfile(user) {
241
- logger_1.logger.info('-> User Data:');
242
- this.printDynamicTree(user);
243
- /*logger.info('-> Raw JSON:');
244
- console.log(JSON.stringify(user));*/
245
- }
246
- /**
247
- * Close the connection to Discord Gateway.
248
- * @param {boolean} [force=false] - If true, the client closes permanently and will not reconnect.
249
- * even if `alwaysReconnect` is enabled. Defaults to false.
250
- */
251
- close(force = false) {
252
- this.rpcs.forEach((rpc) => rpc.destroy());
253
- this.websocket.close(force);
254
- }
255
- }
256
- exports.Client = Client;
@@ -1,69 +0,0 @@
1
- import { ClientProperties } from './entities/identify';
2
- import { PresenceUpdatePayload, DiscordUser } from './entities/types';
3
- interface DiscordWebSocketOptions {
4
- alwaysReconnect: boolean;
5
- properties?: ClientProperties;
6
- connectionTimeout?: number;
7
- }
8
- /**
9
- * Manage WebSocket connections to Discord Gateway.
10
- * Handles low-level operations like heartbeating, identifying, and resuming.
11
- */
12
- export declare class DiscordWebSocket {
13
- private token;
14
- private ws;
15
- private sequence;
16
- private heartbeatInterval;
17
- private heartbeatIntervalValue;
18
- private sessionId;
19
- private resumeGatewayUrl;
20
- private options;
21
- private isReconnecting;
22
- private permanentClose;
23
- private connectTimeout;
24
- private resolveReady;
25
- private lastHeartbeatAck;
26
- /**
27
- * Current logged in user info.
28
- */
29
- user: DiscordUser | null;
30
- /**
31
- * A promise will be resolved when the Gateway connection is ready.
32
- * and received the READY event.
33
- */
34
- readyPromise: Promise<DiscordUser>;
35
- /**
36
- * Create a DiscordWebSocket instance.
37
- * @param {string} token - Discord user token for authentication.
38
- * @param {DiscordWebSocketOptions} options - Configuration options for the WebSocket client.
39
- * @throws {Error} If the token is invalid.
40
- */
41
- constructor(token: string, options: DiscordWebSocketOptions);
42
- private resetReadyPromise;
43
- private isTokenValid;
44
- /**
45
- * Initiate connection to Discord Gateway.
46
- * If there was a previous session, it will try to resume.
47
- */
48
- connect(): void;
49
- private handleClose;
50
- private onMessage;
51
- private startHeartbeating;
52
- private sendHeartbeat;
53
- private identify;
54
- private resume;
55
- /**
56
- * Send presence update payload to Gateway.
57
- * @param {PresenceUpdatePayload} presence - Payload update status to send.
58
- */
59
- sendActivity(presence: PresenceUpdatePayload): void;
60
- private sendJson;
61
- /**
62
- * Closes the WebSocket connection.
63
- * @param {boolean} force If true, prevents any automatic reconnection attempts.
64
- */
65
- close(force?: boolean): void;
66
- private cleanupHeartbeat;
67
- private shouldReconnect;
68
- }
69
- export {};