qaut.js 1.0.1 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qaut.js",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Official QauT bot framework for building bots and integrations.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
package/src/index.d.ts CHANGED
@@ -98,9 +98,16 @@ export declare class TextChannel {
98
98
  send(payload: string | Record<string, unknown>): Promise<unknown>;
99
99
  }
100
100
 
101
+ export declare class User {
102
+ id: string;
103
+ constructor(client: Client, data?: Record<string, unknown>);
104
+ send(payload: string | Record<string, unknown>): Promise<unknown>;
105
+ }
106
+
101
107
  export declare class Message {
102
108
  client: Client;
103
109
  channel: TextChannel | null;
110
+ author: User | null;
104
111
  content?: string;
105
112
  constructor(client: Client, data?: Record<string, unknown>);
106
113
  reply(payload: string | Record<string, unknown>): Promise<unknown>;
@@ -111,14 +118,19 @@ export declare class Client extends EventEmitter {
111
118
  rest: REST;
112
119
  user: unknown;
113
120
  intents: IntentBitField;
121
+ polling: boolean;
122
+ pollIntervalMs: number;
114
123
  keepAlive: boolean;
115
- constructor(options?: { token?: string; intents?: Array<number | bigint | string> | number | bigint | string; restBaseUrl?: string; keepAlive?: boolean });
124
+ constructor(options?: { token?: string; intents?: Array<number | bigint | string> | number | bigint | string; restBaseUrl?: string; keepAlive?: boolean; polling?: boolean; pollIntervalMs?: number; registerProcessShutdown?: boolean });
116
125
  login(token?: string): Promise<string>;
117
126
  startKeepAlive(): this;
118
- destroy(): this;
127
+ startPolling(): this;
128
+ destroy(options?: { setOffline?: boolean }): Promise<this>;
129
+ attachProcessShutdown(): this;
119
130
  setPresence(presence?: Record<string, unknown>): Promise<unknown>;
120
131
  setStatus(status: string): Promise<unknown>;
121
132
  channel(id: string): TextChannel;
133
+ user(id: string): User;
122
134
  emitGatewayEvent(eventName: string, payload: unknown): boolean;
123
135
  }
124
136
 
package/src/index.js CHANGED
@@ -222,11 +222,23 @@ class TextChannel {
222
222
  }
223
223
  }
224
224
 
225
+ class User {
226
+ constructor(client, data = {}) {
227
+ this.client = client;
228
+ Object.assign(this, data);
229
+ }
230
+
231
+ send(payload) {
232
+ return this.client.rest.post(`/bot/users/${this.id}/messages`, normalizeMessagePayload(payload));
233
+ }
234
+ }
235
+
225
236
  class Message {
226
237
  constructor(client, data = {}) {
227
238
  this.client = client;
228
239
  Object.assign(this, data);
229
240
  this.channel = data.channel || (data.channelId ? new TextChannel(client, { id: data.channelId }) : null);
241
+ this.author = data.author ? new User(client, data.author) : null;
230
242
  }
231
243
 
232
244
  reply(payload) {
@@ -245,6 +257,13 @@ class Client extends EventEmitter {
245
257
  this.user = null;
246
258
  this.keepAlive = options.keepAlive !== false;
247
259
  this.keepAliveInterval = null;
260
+ this.polling = options.polling !== false;
261
+ this.pollIntervalMs = Number(options.pollIntervalMs || 1500);
262
+ this.pollInterval = null;
263
+ this.gatewayCursor = null;
264
+ this.destroyed = false;
265
+ this.registerProcessShutdown = options.registerProcessShutdown !== false;
266
+ this.boundShutdown = null;
248
267
  }
249
268
 
250
269
  async login(token = this.token) {
@@ -254,6 +273,8 @@ class Client extends EventEmitter {
254
273
  const me = await this.rest.get('/bot/me');
255
274
  this.user = me;
256
275
  if (this.keepAlive) this.startKeepAlive();
276
+ if (this.polling) this.startPolling();
277
+ if (this.registerProcessShutdown) this.attachProcessShutdown();
257
278
  this.emit(Events.ClientReady, me);
258
279
  return token;
259
280
  }
@@ -266,13 +287,54 @@ class Client extends EventEmitter {
266
287
  return this;
267
288
  }
268
289
 
269
- destroy() {
290
+ async destroy(options = {}) {
291
+ if (this.destroyed) return this;
292
+ this.destroyed = true;
293
+ if (options.setOffline !== false && this.token) {
294
+ try {
295
+ await this.setPresence({ status: Status.Offline });
296
+ } catch (err) {
297
+ this.emit(Events.Debug, `Failed to set offline presence: ${err.message}`);
298
+ }
299
+ }
270
300
  if (this.keepAliveInterval) clearInterval(this.keepAliveInterval);
301
+ if (this.pollInterval) clearInterval(this.pollInterval);
271
302
  this.keepAliveInterval = null;
303
+ this.pollInterval = null;
272
304
  this.user = null;
273
305
  return this;
274
306
  }
275
307
 
308
+ attachProcessShutdown() {
309
+ if (this.boundShutdown || typeof process === 'undefined') return this;
310
+ this.boundShutdown = async () => {
311
+ await this.destroy();
312
+ process.exit(0);
313
+ };
314
+ process.once('SIGINT', this.boundShutdown);
315
+ process.once('SIGTERM', this.boundShutdown);
316
+ return this;
317
+ }
318
+
319
+ startPolling() {
320
+ if (this.pollInterval) return this;
321
+ this.gatewayCursor = new Date().toISOString();
322
+ const tick = async () => {
323
+ try {
324
+ const query = this.gatewayCursor ? `?after=${encodeURIComponent(this.gatewayCursor)}` : '';
325
+ const data = await this.rest.get(`/bot/gateway/messages${query}`);
326
+ this.gatewayCursor = data.cursor || new Date().toISOString();
327
+ for (const payload of data.messages || []) {
328
+ this.emitGatewayEvent(Events.MessageCreate, payload);
329
+ }
330
+ } catch (err) {
331
+ this.emit(Events.Error, err);
332
+ }
333
+ };
334
+ this.pollInterval = setInterval(tick, this.pollIntervalMs);
335
+ return this;
336
+ }
337
+
276
338
  async setPresence(presence = {}) {
277
339
  return this.rest.patch('/bot/presence', presence);
278
340
  }
@@ -285,6 +347,10 @@ class Client extends EventEmitter {
285
347
  return new TextChannel(this, { id });
286
348
  }
287
349
 
350
+ user(id) {
351
+ return new User(this, { id });
352
+ }
353
+
288
354
  emitGatewayEvent(eventName, payload) {
289
355
  if (eventName === Events.MessageCreate) return this.emit(eventName, new Message(this, payload));
290
356
  return this.emit(eventName, payload);
@@ -337,4 +403,5 @@ module.exports = {
337
403
  SlashCommandBuilder,
338
404
  Status,
339
405
  TextChannel
406
+ , User
340
407
  };