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.cjs CHANGED
@@ -54,7 +54,7 @@ var ConfigurationBuilder = class {
54
54
  /**
55
55
  * 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.
56
56
  * @param option { (option: NumberOption) => NumberOption }
57
- * @returns
57
+ * @returns
58
58
  */
59
59
  addNumberOption(option) {
60
60
  let newOption = new NumberOption();
@@ -65,7 +65,7 @@ var ConfigurationBuilder = class {
65
65
  /**
66
66
  * 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.
67
67
  * @param option { (option: StringOption) => StringOption }
68
- */
68
+ */
69
69
  addStringOption(option) {
70
70
  let newOption = new StringOption();
71
71
  newOption = option(newOption);
@@ -75,7 +75,7 @@ var ConfigurationBuilder = class {
75
75
  /**
76
76
  * 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.
77
77
  * @param option { (option: BooleanOption) => BooleanOption }
78
- */
78
+ */
79
79
  addBooleanOption(option) {
80
80
  let newOption = new BooleanOption();
81
81
  newOption = option(newOption);
@@ -114,9 +114,9 @@ var ConfigurationOption = class {
114
114
  return this;
115
115
  }
116
116
  /**
117
- * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**
118
- * @param displayName {string} The display name of the option.
119
- * @returns
117
+ * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**
118
+ * @param displayName {string} The display name of the option.
119
+ * @returns
120
120
  */
121
121
  setDisplayName(displayName) {
122
122
  this.displayName = displayName;
@@ -124,8 +124,8 @@ var ConfigurationOption = class {
124
124
  }
125
125
  /**
126
126
  * Set the description of the option. This is to show the user a brief description of what this option does. **REQUIRED**
127
- * @param description {string} The description of the option.
128
- * @returns
127
+ * @param description {string} The description of the option.
128
+ * @returns
129
129
  */
130
130
  setDescription(description) {
131
131
  this.description = description;
@@ -147,7 +147,7 @@ var StringOption = class extends ConfigurationOption {
147
147
  inputType = "text";
148
148
  type = "string";
149
149
  /**
150
- * 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.
150
+ * 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.
151
151
  * @param allowedValues {string[]} An array of allowed values for the string. If the array is empty, any value is allowed.
152
152
  */
153
153
  setAllowedValues(allowedValues) {
@@ -163,15 +163,15 @@ var StringOption = class extends ConfigurationOption {
163
163
  return this;
164
164
  }
165
165
  /**
166
- * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.
167
- * @param minTextLength {number} The minimum text length for the string.
166
+ * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.
167
+ * @param minTextLength {number} The minimum text length for the string.
168
168
  */
169
169
  setMinTextLength(minTextLength) {
170
170
  this.minTextLength = minTextLength;
171
171
  return this;
172
172
  }
173
173
  /**
174
- * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.
174
+ * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.
175
175
  * @param maxTextLength {number} The maximum text length for the string.
176
176
  */
177
177
  setMaxTextLength(maxTextLength) {
@@ -179,8 +179,8 @@ var StringOption = class extends ConfigurationOption {
179
179
  return this;
180
180
  }
181
181
  /**
182
- * Set the input type for the string. This will change how the client renders the input.
183
- * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.
182
+ * Set the input type for the string. This will change how the client renders the input.
183
+ * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.
184
184
  */
185
185
  setInputType(inputType) {
186
186
  this.inputType = inputType;
@@ -193,9 +193,15 @@ var StringOption = class extends ConfigurationOption {
193
193
  if (this.allowedValues.length === 0 && input.length !== 0)
194
194
  return [true, ""];
195
195
  if (input.length < this.minTextLength || input.length > this.maxTextLength) {
196
- return [false, "Input is not within the text length " + this.minTextLength + " and " + this.maxTextLength + " characters (currently " + input.length + " characters)"];
196
+ return [
197
+ false,
198
+ "Input is not within the text length " + this.minTextLength + " and " + this.maxTextLength + " characters (currently " + input.length + " characters)"
199
+ ];
197
200
  }
198
- return [this.allowedValues.includes(input), "Input is not an allowed value"];
201
+ return [
202
+ this.allowedValues.includes(input),
203
+ "Input is not an allowed value"
204
+ ];
199
205
  }
200
206
  };
201
207
  var NumberOption = class extends ConfigurationOption {
@@ -213,8 +219,8 @@ var NumberOption = class extends ConfigurationOption {
213
219
  return this;
214
220
  }
215
221
  /**
216
- * Set the input type for the number. This will change how the client renders the input.
217
- * @param type {'range' | 'number'} The input type for the number.
222
+ * Set the input type for the number. This will change how the client renders the input.
223
+ * @param type {'range' | 'number'} The input type for the number.
218
224
  */
219
225
  setInputType(type) {
220
226
  this.inputType = type;
@@ -241,7 +247,10 @@ var NumberOption = class extends ConfigurationOption {
241
247
  return [false, "Input is not a number"];
242
248
  }
243
249
  if (Number(input) < this.min || Number(input) > this.max) {
244
- return [false, "Input is not within the range of " + this.min + " and " + this.max];
250
+ return [
251
+ false,
252
+ "Input is not within the range of " + this.min + " and " + this.max
253
+ ];
245
254
  }
246
255
  return [true, ""];
247
256
  }
@@ -285,20 +294,26 @@ var Configuration = class {
285
294
  const erroredKeys = /* @__PURE__ */ new Map();
286
295
  for (const key in this.storedConfigTemplate) {
287
296
  if (this.definiteConfig[key] === null || this.definiteConfig[key] === void 0) {
288
- console.warn("Option " + key + " is not defined. Using default value Value: " + this.definiteConfig[key]);
297
+ console.warn(
298
+ "Option " + key + " is not defined. Using default value Value: " + this.definiteConfig[key]
299
+ );
289
300
  this.definiteConfig[key] = this.storedConfigTemplate[key].defaultValue;
290
301
  }
291
302
  if (this.storedConfigTemplate[key].type !== typeof this.definiteConfig[key]) {
292
303
  throw new Error("Option " + key + " is not of the correct type");
293
304
  }
294
- const result = this.storedConfigTemplate[key].validate(this.definiteConfig[key]);
305
+ const result = this.storedConfigTemplate[key].validate(
306
+ this.definiteConfig[key]
307
+ );
295
308
  if (!result[0]) {
296
309
  erroredKeys.set(key, result[1]);
297
310
  }
298
311
  }
299
312
  for (const key in this.definiteConfig) {
300
313
  if (!this.storedConfigTemplate[key]) {
301
- throw new Error("Option " + key + " is not defined in the configuration template");
314
+ throw new Error(
315
+ "Option " + key + " is not defined in the configuration template"
316
+ );
302
317
  }
303
318
  }
304
319
  if (erroredKeys.size > 0) {
@@ -354,7 +369,7 @@ var EventResponse = class {
354
369
  }
355
370
  }
356
371
  /**
357
- * 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.**
372
+ * 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.**
358
373
  * @param data {T}
359
374
  */
360
375
  resolve(data) {
@@ -362,7 +377,7 @@ var EventResponse = class {
362
377
  this.data = data;
363
378
  }
364
379
  /**
365
- * 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.**
380
+ * 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.**
366
381
  */
367
382
  complete() {
368
383
  this.resolved = true;
@@ -372,7 +387,7 @@ var EventResponse = class {
372
387
  this.failed = message;
373
388
  }
374
389
  /**
375
- * Logs a message to the event. This is useful for debugging and logging information to the user.
390
+ * Logs a message to the event. This is useful for debugging and logging information to the user.
376
391
  * @param message {string}
377
392
  */
378
393
  log(message) {
@@ -403,7 +418,7 @@ var package_default = {
403
418
  module: "./build/main.js",
404
419
  type: "module",
405
420
  main: "./build/main.cjs",
406
- version: "1.2.2",
421
+ version: "1.3.1",
407
422
  exports: {
408
423
  ".": {
409
424
  import: {
@@ -446,6 +461,7 @@ var package_default = {
446
461
  devDependencies: {
447
462
  "@types/node": "^20.14.12",
448
463
  "@types/ws": "^8.4.0",
464
+ prettier: "^3.6.0",
449
465
  tsup: "^8.2.3",
450
466
  typescript: "^5.0.0"
451
467
  }
@@ -459,35 +475,51 @@ var OGIAddon = class {
459
475
  addonWSListener;
460
476
  addonInfo;
461
477
  config = new Configuration({});
478
+ eventsAvailable = [];
479
+ registeredConnectEvent = false;
462
480
  constructor(addonInfo) {
463
481
  this.addonInfo = addonInfo;
464
482
  this.addonWSListener = new OGIAddonWSListener(this, this.eventEmitter);
465
483
  }
466
484
  /**
467
- * Register an event listener for the addon. (See EventListenerTypes)
485
+ * Register an event listener for the addon. (See EventListenerTypes)
468
486
  * @param event {OGIAddonEvent}
469
- * @param listener {EventListenerTypes[OGIAddonEvent]}
487
+ * @param listener {EventListenerTypes[OGIAddonEvent]}
470
488
  */
471
489
  on(event, listener) {
472
490
  this.eventEmitter.on(event, listener);
491
+ this.eventsAvailable.push(event);
492
+ if (!this.registeredConnectEvent) {
493
+ this.addonWSListener.eventEmitter.once("connect", () => {
494
+ this.addonWSListener.send("flag", {
495
+ flag: "events-available",
496
+ value: this.eventsAvailable
497
+ });
498
+ });
499
+ this.registeredConnectEvent = true;
500
+ }
473
501
  }
474
502
  emit(event, ...args) {
475
503
  this.eventEmitter.emit(event, ...args);
476
504
  }
477
505
  /**
478
- * Notify the client using a notification. Provide the type of notification, the message, and an ID.
506
+ * Notify the client using a notification. Provide the type of notification, the message, and an ID.
479
507
  * @param notification {Notification}
480
508
  */
481
509
  notify(notification) {
482
510
  this.addonWSListener.send("notification", [notification]);
483
511
  }
484
512
  /**
485
- * Search for items in the OGI Steam-Synced Library. Query can either be a Steam AppID or a Steam Game Name.
486
- * @param query {string}
487
- * @param event {EventResponse<BasicLibraryInfo[]>}
513
+ * Get the app details for a given appID and storefront.
514
+ * @param appID {number}
515
+ * @param storefront {string}
516
+ * @returns {Promise<StoreData>}
488
517
  */
489
- async steamSearch(query, strict = false) {
490
- const id = this.addonWSListener.send("steam-search", { query, strict });
518
+ async getAppDetails(appID, storefront) {
519
+ const id = this.addonWSListener.send("get-app-details", {
520
+ appID,
521
+ storefront
522
+ });
491
523
  return await this.addonWSListener.waitForResponseFromServer(id);
492
524
  }
493
525
  /**
@@ -501,7 +533,13 @@ var OGIAddon = class {
501
533
  const progress = 0;
502
534
  const logs = [];
503
535
  const task = new CustomTask(this.addonWSListener, id, progress, logs);
504
- this.addonWSListener.send("task-update", { id, progress, logs, finished: false, failed: void 0 });
536
+ this.addonWSListener.send("task-update", {
537
+ id,
538
+ progress,
539
+ logs,
540
+ finished: false,
541
+ failed: void 0
542
+ });
505
543
  return task;
506
544
  }
507
545
  };
@@ -535,12 +573,21 @@ var CustomTask = class {
535
573
  this.update();
536
574
  }
537
575
  update() {
538
- this.ws.send("task-update", { id: this.id, progress: this.progress, logs: this.logs, finished: this.finished, failed: this.failed });
576
+ this.ws.send("task-update", {
577
+ id: this.id,
578
+ progress: this.progress,
579
+ logs: this.logs,
580
+ finished: this.finished,
581
+ failed: this.failed
582
+ });
539
583
  }
540
584
  };
541
585
  var SearchTool = class {
542
586
  fuse;
543
- constructor(items, keys, options = { threshold: 0.3, includeScore: true }) {
587
+ constructor(items, keys, options = {
588
+ threshold: 0.3,
589
+ includeScore: true
590
+ }) {
544
591
  this.fuse = new import_fuse.default(items, {
545
592
  keys,
546
593
  ...options
@@ -559,7 +606,9 @@ var OGIAddonWSListener = class {
559
606
  addon;
560
607
  constructor(ogiAddon, eventEmitter) {
561
608
  if (process.argv[process.argv.length - 1].split("=")[0] !== "--addonSecret") {
562
- throw new Error("No secret provided. This usually happens because the addon was not started by the OGI Addon Server.");
609
+ throw new Error(
610
+ "No secret provided. This usually happens because the addon was not started by the OGI Addon Server."
611
+ );
563
612
  }
564
613
  this.addon = ogiAddon;
565
614
  this.eventEmitter = eventEmitter;
@@ -580,7 +629,9 @@ var OGIAddonWSListener = class {
580
629
  });
581
630
  this.socket.on("error", (error) => {
582
631
  if (error.message.includes("Failed to connect")) {
583
- throw new Error("OGI Addon Server is not running/is unreachable. Please start the server and try again.");
632
+ throw new Error(
633
+ "OGI Addon Server is not running/is unreachable. Please start the server and try again."
634
+ );
584
635
  }
585
636
  console.error("An error occurred:", error);
586
637
  });
@@ -603,15 +654,17 @@ var OGIAddonWSListener = class {
603
654
  if (!socket) {
604
655
  return {};
605
656
  }
606
- socket.send(JSON.stringify({
607
- event: "input-asked",
608
- args: {
609
- config,
610
- name,
611
- description
612
- },
613
- id
614
- }));
657
+ socket.send(
658
+ JSON.stringify({
659
+ event: "input-asked",
660
+ args: {
661
+ config,
662
+ name,
663
+ description
664
+ },
665
+ id
666
+ })
667
+ );
615
668
  return await this.waitForResponseFromServer(id);
616
669
  }
617
670
  registerMessageReceiver() {
@@ -621,20 +674,39 @@ var OGIAddonWSListener = class {
621
674
  case "config-update":
622
675
  const result = this.addon.config.updateConfig(message.args);
623
676
  if (!result[0]) {
624
- this.respondToMessage(message.id, { success: false, error: result[1] });
677
+ this.respondToMessage(message.id, {
678
+ success: false,
679
+ error: result[1]
680
+ });
625
681
  } else {
626
682
  this.respondToMessage(message.id, { success: true });
627
683
  }
628
684
  break;
629
685
  case "search":
630
- let searchResultEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
686
+ let searchResultEvent = new EventResponse(
687
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
688
+ );
631
689
  this.eventEmitter.emit("search", message.args, searchResultEvent);
632
690
  const searchResult = await this.waitForEventToRespond(searchResultEvent);
633
691
  this.respondToMessage(message.id, searchResult.data);
634
692
  break;
635
693
  case "setup":
636
- let setupEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
637
- 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);
694
+ let setupEvent = new EventResponse(
695
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
696
+ );
697
+ this.eventEmitter.emit(
698
+ "setup",
699
+ {
700
+ path: message.args.path,
701
+ appID: message.args.appID,
702
+ storefront: message.args.storefront,
703
+ type: message.args.type,
704
+ name: message.args.name,
705
+ usedRealDebrid: message.args.usedRealDebrid,
706
+ multiPartFiles: message.args.multiPartFiles
707
+ },
708
+ setupEvent
709
+ );
638
710
  const interval = setInterval(() => {
639
711
  if (setupEvent.resolved) {
640
712
  clearInterval(interval);
@@ -651,42 +723,75 @@ var OGIAddonWSListener = class {
651
723
  this.respondToMessage(message.id, setupResult.data);
652
724
  break;
653
725
  case "library-search":
654
- let librarySearchEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
726
+ let librarySearchEvent = new EventResponse(
727
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
728
+ );
655
729
  if (this.eventEmitter.listenerCount("game-details") === 0) {
656
730
  this.respondToMessage(message.id, []);
657
731
  break;
658
732
  }
659
- this.eventEmitter.emit("library-search", message.args, librarySearchEvent);
733
+ this.eventEmitter.emit(
734
+ "library-search",
735
+ message.args,
736
+ librarySearchEvent
737
+ );
660
738
  const librarySearchResult = await this.waitForEventToRespond(librarySearchEvent);
661
739
  this.respondToMessage(message.id, librarySearchResult.data);
662
740
  break;
663
741
  case "game-details":
664
- let gameDetailsEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
742
+ let gameDetailsEvent = new EventResponse(
743
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
744
+ );
665
745
  if (this.eventEmitter.listenerCount("game-details") === 0) {
666
- this.respondToMessage(message.id, { error: "No event listener for game-details" });
746
+ this.respondToMessage(message.id, {
747
+ error: "No event listener for game-details"
748
+ });
667
749
  break;
668
750
  }
669
- this.eventEmitter.emit("game-details", message.args, gameDetailsEvent);
751
+ this.eventEmitter.emit(
752
+ "game-details",
753
+ message.args,
754
+ gameDetailsEvent
755
+ );
670
756
  const gameDetailsResult = await this.waitForEventToRespond(gameDetailsEvent);
671
757
  this.respondToMessage(message.id, gameDetailsResult.data);
672
758
  break;
673
759
  case "request-dl":
674
- let requestDLEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
760
+ let requestDLEvent = new EventResponse(
761
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
762
+ );
675
763
  if (this.eventEmitter.listenerCount("request-dl") === 0) {
676
- this.respondToMessage(message.id, { error: "No event listener for request-dl" });
764
+ this.respondToMessage(message.id, {
765
+ error: "No event listener for request-dl"
766
+ });
677
767
  break;
678
768
  }
679
- this.eventEmitter.emit("request-dl", message.args.appID, message.args.info, requestDLEvent);
769
+ this.eventEmitter.emit(
770
+ "request-dl",
771
+ message.args.appID,
772
+ message.args.info,
773
+ requestDLEvent
774
+ );
680
775
  const requestDLResult = await this.waitForEventToRespond(requestDLEvent);
681
776
  if (requestDLEvent.failed) {
682
- this.respondToMessage(message.id, { statusError: requestDLEvent.failed });
777
+ this.respondToMessage(message.id, {
778
+ statusError: requestDLEvent.failed
779
+ });
683
780
  break;
684
781
  }
685
782
  if (requestDLEvent.data === void 0 || requestDLEvent.data?.downloadType === "request") {
686
- 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.");
783
+ throw new Error(
784
+ "Request DL event did not return a valid result. Please ensure that the event does not resolve with another `request` download type."
785
+ );
687
786
  }
688
787
  this.respondToMessage(message.id, requestDLResult.data);
689
788
  break;
789
+ case "catalog":
790
+ let catalogEvent = new EventResponse();
791
+ this.eventEmitter.emit("catalog", catalogEvent);
792
+ const catalogResult = await this.waitForEventToRespond(catalogEvent);
793
+ this.respondToMessage(message.id, catalogResult.data);
794
+ break;
690
795
  }
691
796
  });
692
797
  }
@@ -714,11 +819,13 @@ var OGIAddonWSListener = class {
714
819
  });
715
820
  }
716
821
  respondToMessage(messageID, response) {
717
- this.socket.send(JSON.stringify({
718
- event: "response",
719
- id: messageID,
720
- args: response
721
- }));
822
+ this.socket.send(
823
+ JSON.stringify({
824
+ event: "response",
825
+ id: messageID,
826
+ args: response
827
+ })
828
+ );
722
829
  console.log("dispatched response to " + messageID);
723
830
  }
724
831
  waitForResponseFromServer(messageID) {
@@ -741,11 +848,13 @@ var OGIAddonWSListener = class {
741
848
  }
742
849
  send(event, args) {
743
850
  const id = Math.random().toString(36).substring(7);
744
- this.socket.send(JSON.stringify({
745
- event,
746
- args,
747
- id
748
- }));
851
+ this.socket.send(
852
+ JSON.stringify({
853
+ event,
854
+ args,
855
+ id
856
+ })
857
+ );
749
858
  return id;
750
859
  }
751
860
  close() {