ogi-addon 1.2.2 → 1.3.1

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/build/main.js CHANGED
@@ -14,7 +14,7 @@ var ConfigurationBuilder = class {
14
14
  /**
15
15
  * Add a number option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.
16
16
  * @param option { (option: NumberOption) => NumberOption }
17
- * @returns
17
+ * @returns
18
18
  */
19
19
  addNumberOption(option) {
20
20
  let newOption = new NumberOption();
@@ -25,7 +25,7 @@ var ConfigurationBuilder = class {
25
25
  /**
26
26
  * Add a string option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.
27
27
  * @param option { (option: StringOption) => StringOption }
28
- */
28
+ */
29
29
  addStringOption(option) {
30
30
  let newOption = new StringOption();
31
31
  newOption = option(newOption);
@@ -35,7 +35,7 @@ var ConfigurationBuilder = class {
35
35
  /**
36
36
  * Add a boolean option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.
37
37
  * @param option { (option: BooleanOption) => BooleanOption }
38
- */
38
+ */
39
39
  addBooleanOption(option) {
40
40
  let newOption = new BooleanOption();
41
41
  newOption = option(newOption);
@@ -74,9 +74,9 @@ var ConfigurationOption = class {
74
74
  return this;
75
75
  }
76
76
  /**
77
- * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**
78
- * @param displayName {string} The display name of the option.
79
- * @returns
77
+ * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**
78
+ * @param displayName {string} The display name of the option.
79
+ * @returns
80
80
  */
81
81
  setDisplayName(displayName) {
82
82
  this.displayName = displayName;
@@ -84,8 +84,8 @@ var ConfigurationOption = class {
84
84
  }
85
85
  /**
86
86
  * Set the description of the option. This is to show the user a brief description of what this option does. **REQUIRED**
87
- * @param description {string} The description of the option.
88
- * @returns
87
+ * @param description {string} The description of the option.
88
+ * @returns
89
89
  */
90
90
  setDescription(description) {
91
91
  this.description = description;
@@ -107,7 +107,7 @@ var StringOption = class extends ConfigurationOption {
107
107
  inputType = "text";
108
108
  type = "string";
109
109
  /**
110
- * Set the allowed values for the string. If the array is empty, any value is allowed. When provided, the client will act like this option is a dropdown.
110
+ * Set the allowed values for the string. If the array is empty, any value is allowed. When provided, the client will act like this option is a dropdown.
111
111
  * @param allowedValues {string[]} An array of allowed values for the string. If the array is empty, any value is allowed.
112
112
  */
113
113
  setAllowedValues(allowedValues) {
@@ -123,15 +123,15 @@ var StringOption = class extends ConfigurationOption {
123
123
  return this;
124
124
  }
125
125
  /**
126
- * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.
127
- * @param minTextLength {number} The minimum text length for the string.
126
+ * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.
127
+ * @param minTextLength {number} The minimum text length for the string.
128
128
  */
129
129
  setMinTextLength(minTextLength) {
130
130
  this.minTextLength = minTextLength;
131
131
  return this;
132
132
  }
133
133
  /**
134
- * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.
134
+ * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.
135
135
  * @param maxTextLength {number} The maximum text length for the string.
136
136
  */
137
137
  setMaxTextLength(maxTextLength) {
@@ -139,8 +139,8 @@ var StringOption = class extends ConfigurationOption {
139
139
  return this;
140
140
  }
141
141
  /**
142
- * Set the input type for the string. This will change how the client renders the input.
143
- * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.
142
+ * Set the input type for the string. This will change how the client renders the input.
143
+ * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.
144
144
  */
145
145
  setInputType(inputType) {
146
146
  this.inputType = inputType;
@@ -153,9 +153,15 @@ var StringOption = class extends ConfigurationOption {
153
153
  if (this.allowedValues.length === 0 && input.length !== 0)
154
154
  return [true, ""];
155
155
  if (input.length < this.minTextLength || input.length > this.maxTextLength) {
156
- return [false, "Input is not within the text length " + this.minTextLength + " and " + this.maxTextLength + " characters (currently " + input.length + " characters)"];
156
+ return [
157
+ false,
158
+ "Input is not within the text length " + this.minTextLength + " and " + this.maxTextLength + " characters (currently " + input.length + " characters)"
159
+ ];
157
160
  }
158
- return [this.allowedValues.includes(input), "Input is not an allowed value"];
161
+ return [
162
+ this.allowedValues.includes(input),
163
+ "Input is not an allowed value"
164
+ ];
159
165
  }
160
166
  };
161
167
  var NumberOption = class extends ConfigurationOption {
@@ -173,8 +179,8 @@ var NumberOption = class extends ConfigurationOption {
173
179
  return this;
174
180
  }
175
181
  /**
176
- * Set the input type for the number. This will change how the client renders the input.
177
- * @param type {'range' | 'number'} The input type for the number.
182
+ * Set the input type for the number. This will change how the client renders the input.
183
+ * @param type {'range' | 'number'} The input type for the number.
178
184
  */
179
185
  setInputType(type) {
180
186
  this.inputType = type;
@@ -201,7 +207,10 @@ var NumberOption = class extends ConfigurationOption {
201
207
  return [false, "Input is not a number"];
202
208
  }
203
209
  if (Number(input) < this.min || Number(input) > this.max) {
204
- return [false, "Input is not within the range of " + this.min + " and " + this.max];
210
+ return [
211
+ false,
212
+ "Input is not within the range of " + this.min + " and " + this.max
213
+ ];
205
214
  }
206
215
  return [true, ""];
207
216
  }
@@ -245,20 +254,26 @@ var Configuration = class {
245
254
  const erroredKeys = /* @__PURE__ */ new Map();
246
255
  for (const key in this.storedConfigTemplate) {
247
256
  if (this.definiteConfig[key] === null || this.definiteConfig[key] === void 0) {
248
- console.warn("Option " + key + " is not defined. Using default value Value: " + this.definiteConfig[key]);
257
+ console.warn(
258
+ "Option " + key + " is not defined. Using default value Value: " + this.definiteConfig[key]
259
+ );
249
260
  this.definiteConfig[key] = this.storedConfigTemplate[key].defaultValue;
250
261
  }
251
262
  if (this.storedConfigTemplate[key].type !== typeof this.definiteConfig[key]) {
252
263
  throw new Error("Option " + key + " is not of the correct type");
253
264
  }
254
- const result = this.storedConfigTemplate[key].validate(this.definiteConfig[key]);
265
+ const result = this.storedConfigTemplate[key].validate(
266
+ this.definiteConfig[key]
267
+ );
255
268
  if (!result[0]) {
256
269
  erroredKeys.set(key, result[1]);
257
270
  }
258
271
  }
259
272
  for (const key in this.definiteConfig) {
260
273
  if (!this.storedConfigTemplate[key]) {
261
- throw new Error("Option " + key + " is not defined in the configuration template");
274
+ throw new Error(
275
+ "Option " + key + " is not defined in the configuration template"
276
+ );
262
277
  }
263
278
  }
264
279
  if (erroredKeys.size > 0) {
@@ -314,7 +329,7 @@ var EventResponse = class {
314
329
  }
315
330
  }
316
331
  /**
317
- * Resolve the event with data. This acts like a promise resolve, and will stop the event from being processed further. **You must always call this method when you are done with the event.**
332
+ * Resolve the event with data. This acts like a promise resolve, and will stop the event from being processed further. **You must always call this method when you are done with the event.**
318
333
  * @param data {T}
319
334
  */
320
335
  resolve(data) {
@@ -322,7 +337,7 @@ var EventResponse = class {
322
337
  this.data = data;
323
338
  }
324
339
  /**
325
- * Completes the event and resolves it, but does not return any data. **You must always call this method when you are done with the event.**
340
+ * Completes the event and resolves it, but does not return any data. **You must always call this method when you are done with the event.**
326
341
  */
327
342
  complete() {
328
343
  this.resolved = true;
@@ -332,7 +347,7 @@ var EventResponse = class {
332
347
  this.failed = message;
333
348
  }
334
349
  /**
335
- * Logs a message to the event. This is useful for debugging and logging information to the user.
350
+ * Logs a message to the event. This is useful for debugging and logging information to the user.
336
351
  * @param message {string}
337
352
  */
338
353
  log(message) {
@@ -363,7 +378,7 @@ var package_default = {
363
378
  module: "./build/main.js",
364
379
  type: "module",
365
380
  main: "./build/main.cjs",
366
- version: "1.2.2",
381
+ version: "1.3.1",
367
382
  exports: {
368
383
  ".": {
369
384
  import: {
@@ -406,6 +421,7 @@ var package_default = {
406
421
  devDependencies: {
407
422
  "@types/node": "^20.14.12",
408
423
  "@types/ws": "^8.4.0",
424
+ prettier: "^3.6.0",
409
425
  tsup: "^8.2.3",
410
426
  typescript: "^5.0.0"
411
427
  }
@@ -419,35 +435,51 @@ var OGIAddon = class {
419
435
  addonWSListener;
420
436
  addonInfo;
421
437
  config = new Configuration({});
438
+ eventsAvailable = [];
439
+ registeredConnectEvent = false;
422
440
  constructor(addonInfo) {
423
441
  this.addonInfo = addonInfo;
424
442
  this.addonWSListener = new OGIAddonWSListener(this, this.eventEmitter);
425
443
  }
426
444
  /**
427
- * Register an event listener for the addon. (See EventListenerTypes)
445
+ * Register an event listener for the addon. (See EventListenerTypes)
428
446
  * @param event {OGIAddonEvent}
429
- * @param listener {EventListenerTypes[OGIAddonEvent]}
447
+ * @param listener {EventListenerTypes[OGIAddonEvent]}
430
448
  */
431
449
  on(event, listener) {
432
450
  this.eventEmitter.on(event, listener);
451
+ this.eventsAvailable.push(event);
452
+ if (!this.registeredConnectEvent) {
453
+ this.addonWSListener.eventEmitter.once("connect", () => {
454
+ this.addonWSListener.send("flag", {
455
+ flag: "events-available",
456
+ value: this.eventsAvailable
457
+ });
458
+ });
459
+ this.registeredConnectEvent = true;
460
+ }
433
461
  }
434
462
  emit(event, ...args) {
435
463
  this.eventEmitter.emit(event, ...args);
436
464
  }
437
465
  /**
438
- * Notify the client using a notification. Provide the type of notification, the message, and an ID.
466
+ * Notify the client using a notification. Provide the type of notification, the message, and an ID.
439
467
  * @param notification {Notification}
440
468
  */
441
469
  notify(notification) {
442
470
  this.addonWSListener.send("notification", [notification]);
443
471
  }
444
472
  /**
445
- * Search for items in the OGI Steam-Synced Library. Query can either be a Steam AppID or a Steam Game Name.
446
- * @param query {string}
447
- * @param event {EventResponse<BasicLibraryInfo[]>}
473
+ * Get the app details for a given appID and storefront.
474
+ * @param appID {number}
475
+ * @param storefront {string}
476
+ * @returns {Promise<StoreData>}
448
477
  */
449
- async steamSearch(query, strict = false) {
450
- const id = this.addonWSListener.send("steam-search", { query, strict });
478
+ async getAppDetails(appID, storefront) {
479
+ const id = this.addonWSListener.send("get-app-details", {
480
+ appID,
481
+ storefront
482
+ });
451
483
  return await this.addonWSListener.waitForResponseFromServer(id);
452
484
  }
453
485
  /**
@@ -461,7 +493,13 @@ var OGIAddon = class {
461
493
  const progress = 0;
462
494
  const logs = [];
463
495
  const task = new CustomTask(this.addonWSListener, id, progress, logs);
464
- this.addonWSListener.send("task-update", { id, progress, logs, finished: false, failed: void 0 });
496
+ this.addonWSListener.send("task-update", {
497
+ id,
498
+ progress,
499
+ logs,
500
+ finished: false,
501
+ failed: void 0
502
+ });
465
503
  return task;
466
504
  }
467
505
  };
@@ -495,12 +533,21 @@ var CustomTask = class {
495
533
  this.update();
496
534
  }
497
535
  update() {
498
- this.ws.send("task-update", { id: this.id, progress: this.progress, logs: this.logs, finished: this.finished, failed: this.failed });
536
+ this.ws.send("task-update", {
537
+ id: this.id,
538
+ progress: this.progress,
539
+ logs: this.logs,
540
+ finished: this.finished,
541
+ failed: this.failed
542
+ });
499
543
  }
500
544
  };
501
545
  var SearchTool = class {
502
546
  fuse;
503
- constructor(items, keys, options = { threshold: 0.3, includeScore: true }) {
547
+ constructor(items, keys, options = {
548
+ threshold: 0.3,
549
+ includeScore: true
550
+ }) {
504
551
  this.fuse = new Fuse(items, {
505
552
  keys,
506
553
  ...options
@@ -519,7 +566,9 @@ var OGIAddonWSListener = class {
519
566
  addon;
520
567
  constructor(ogiAddon, eventEmitter) {
521
568
  if (process.argv[process.argv.length - 1].split("=")[0] !== "--addonSecret") {
522
- throw new Error("No secret provided. This usually happens because the addon was not started by the OGI Addon Server.");
569
+ throw new Error(
570
+ "No secret provided. This usually happens because the addon was not started by the OGI Addon Server."
571
+ );
523
572
  }
524
573
  this.addon = ogiAddon;
525
574
  this.eventEmitter = eventEmitter;
@@ -540,7 +589,9 @@ var OGIAddonWSListener = class {
540
589
  });
541
590
  this.socket.on("error", (error) => {
542
591
  if (error.message.includes("Failed to connect")) {
543
- throw new Error("OGI Addon Server is not running/is unreachable. Please start the server and try again.");
592
+ throw new Error(
593
+ "OGI Addon Server is not running/is unreachable. Please start the server and try again."
594
+ );
544
595
  }
545
596
  console.error("An error occurred:", error);
546
597
  });
@@ -563,15 +614,17 @@ var OGIAddonWSListener = class {
563
614
  if (!socket) {
564
615
  return {};
565
616
  }
566
- socket.send(JSON.stringify({
567
- event: "input-asked",
568
- args: {
569
- config,
570
- name,
571
- description
572
- },
573
- id
574
- }));
617
+ socket.send(
618
+ JSON.stringify({
619
+ event: "input-asked",
620
+ args: {
621
+ config,
622
+ name,
623
+ description
624
+ },
625
+ id
626
+ })
627
+ );
575
628
  return await this.waitForResponseFromServer(id);
576
629
  }
577
630
  registerMessageReceiver() {
@@ -581,20 +634,39 @@ var OGIAddonWSListener = class {
581
634
  case "config-update":
582
635
  const result = this.addon.config.updateConfig(message.args);
583
636
  if (!result[0]) {
584
- this.respondToMessage(message.id, { success: false, error: result[1] });
637
+ this.respondToMessage(message.id, {
638
+ success: false,
639
+ error: result[1]
640
+ });
585
641
  } else {
586
642
  this.respondToMessage(message.id, { success: true });
587
643
  }
588
644
  break;
589
645
  case "search":
590
- let searchResultEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
646
+ let searchResultEvent = new EventResponse(
647
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
648
+ );
591
649
  this.eventEmitter.emit("search", message.args, searchResultEvent);
592
650
  const searchResult = await this.waitForEventToRespond(searchResultEvent);
593
651
  this.respondToMessage(message.id, searchResult.data);
594
652
  break;
595
653
  case "setup":
596
- let setupEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
597
- this.eventEmitter.emit("setup", { path: message.args.path, appID: message.args.appID, storefront: message.args.storefront, type: message.args.type, name: message.args.name, usedRealDebrid: message.args.usedRealDebrid, multiPartFiles: message.args.multiPartFiles }, setupEvent);
654
+ let setupEvent = new EventResponse(
655
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
656
+ );
657
+ this.eventEmitter.emit(
658
+ "setup",
659
+ {
660
+ path: message.args.path,
661
+ appID: message.args.appID,
662
+ storefront: message.args.storefront,
663
+ type: message.args.type,
664
+ name: message.args.name,
665
+ usedRealDebrid: message.args.usedRealDebrid,
666
+ multiPartFiles: message.args.multiPartFiles
667
+ },
668
+ setupEvent
669
+ );
598
670
  const interval = setInterval(() => {
599
671
  if (setupEvent.resolved) {
600
672
  clearInterval(interval);
@@ -611,42 +683,75 @@ var OGIAddonWSListener = class {
611
683
  this.respondToMessage(message.id, setupResult.data);
612
684
  break;
613
685
  case "library-search":
614
- let librarySearchEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
686
+ let librarySearchEvent = new EventResponse(
687
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
688
+ );
615
689
  if (this.eventEmitter.listenerCount("game-details") === 0) {
616
690
  this.respondToMessage(message.id, []);
617
691
  break;
618
692
  }
619
- this.eventEmitter.emit("library-search", message.args, librarySearchEvent);
693
+ this.eventEmitter.emit(
694
+ "library-search",
695
+ message.args,
696
+ librarySearchEvent
697
+ );
620
698
  const librarySearchResult = await this.waitForEventToRespond(librarySearchEvent);
621
699
  this.respondToMessage(message.id, librarySearchResult.data);
622
700
  break;
623
701
  case "game-details":
624
- let gameDetailsEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
702
+ let gameDetailsEvent = new EventResponse(
703
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
704
+ );
625
705
  if (this.eventEmitter.listenerCount("game-details") === 0) {
626
- this.respondToMessage(message.id, { error: "No event listener for game-details" });
706
+ this.respondToMessage(message.id, {
707
+ error: "No event listener for game-details"
708
+ });
627
709
  break;
628
710
  }
629
- this.eventEmitter.emit("game-details", message.args, gameDetailsEvent);
711
+ this.eventEmitter.emit(
712
+ "game-details",
713
+ message.args,
714
+ gameDetailsEvent
715
+ );
630
716
  const gameDetailsResult = await this.waitForEventToRespond(gameDetailsEvent);
631
717
  this.respondToMessage(message.id, gameDetailsResult.data);
632
718
  break;
633
719
  case "request-dl":
634
- let requestDLEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
720
+ let requestDLEvent = new EventResponse(
721
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
722
+ );
635
723
  if (this.eventEmitter.listenerCount("request-dl") === 0) {
636
- this.respondToMessage(message.id, { error: "No event listener for request-dl" });
724
+ this.respondToMessage(message.id, {
725
+ error: "No event listener for request-dl"
726
+ });
637
727
  break;
638
728
  }
639
- this.eventEmitter.emit("request-dl", message.args.appID, message.args.info, requestDLEvent);
729
+ this.eventEmitter.emit(
730
+ "request-dl",
731
+ message.args.appID,
732
+ message.args.info,
733
+ requestDLEvent
734
+ );
640
735
  const requestDLResult = await this.waitForEventToRespond(requestDLEvent);
641
736
  if (requestDLEvent.failed) {
642
- this.respondToMessage(message.id, { statusError: requestDLEvent.failed });
737
+ this.respondToMessage(message.id, {
738
+ statusError: requestDLEvent.failed
739
+ });
643
740
  break;
644
741
  }
645
742
  if (requestDLEvent.data === void 0 || requestDLEvent.data?.downloadType === "request") {
646
- throw new Error("Request DL event did not return a valid result. Please ensure that the event does not resolve with another `request` download type.");
743
+ throw new Error(
744
+ "Request DL event did not return a valid result. Please ensure that the event does not resolve with another `request` download type."
745
+ );
647
746
  }
648
747
  this.respondToMessage(message.id, requestDLResult.data);
649
748
  break;
749
+ case "catalog":
750
+ let catalogEvent = new EventResponse();
751
+ this.eventEmitter.emit("catalog", catalogEvent);
752
+ const catalogResult = await this.waitForEventToRespond(catalogEvent);
753
+ this.respondToMessage(message.id, catalogResult.data);
754
+ break;
650
755
  }
651
756
  });
652
757
  }
@@ -674,11 +779,13 @@ var OGIAddonWSListener = class {
674
779
  });
675
780
  }
676
781
  respondToMessage(messageID, response) {
677
- this.socket.send(JSON.stringify({
678
- event: "response",
679
- id: messageID,
680
- args: response
681
- }));
782
+ this.socket.send(
783
+ JSON.stringify({
784
+ event: "response",
785
+ id: messageID,
786
+ args: response
787
+ })
788
+ );
682
789
  console.log("dispatched response to " + messageID);
683
790
  }
684
791
  waitForResponseFromServer(messageID) {
@@ -701,11 +808,13 @@ var OGIAddonWSListener = class {
701
808
  }
702
809
  send(event, args) {
703
810
  const id = Math.random().toString(36).substring(7);
704
- this.socket.send(JSON.stringify({
705
- event,
706
- args,
707
- id
708
- }));
811
+ this.socket.send(
812
+ JSON.stringify({
813
+ event,
814
+ args,
815
+ id
816
+ })
817
+ );
709
818
  return id;
710
819
  }
711
820
  close() {