ogi-addon 1.2.2 → 1.3.0

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.0",
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
  }
@@ -420,34 +436,45 @@ var OGIAddon = class {
420
436
  addonInfo;
421
437
  config = new Configuration({});
422
438
  constructor(addonInfo) {
423
- this.addonInfo = addonInfo;
439
+ this.addonInfo = { storeFrontServerCapable: false, ...addonInfo };
424
440
  this.addonWSListener = new OGIAddonWSListener(this, this.eventEmitter);
425
441
  }
426
442
  /**
427
- * Register an event listener for the addon. (See EventListenerTypes)
443
+ * Register an event listener for the addon. (See EventListenerTypes)
428
444
  * @param event {OGIAddonEvent}
429
- * @param listener {EventListenerTypes[OGIAddonEvent]}
445
+ * @param listener {EventListenerTypes[OGIAddonEvent]}
430
446
  */
431
447
  on(event, listener) {
432
448
  this.eventEmitter.on(event, listener);
449
+ if (event === "game-details") {
450
+ this.addonInfo.storeFrontServerCapable = true;
451
+ this.addonWSListener.send("flag", {
452
+ flag: "storeFrontServerCapable",
453
+ value: this.addonInfo.storeFrontServerCapable
454
+ });
455
+ }
433
456
  }
434
457
  emit(event, ...args) {
435
458
  this.eventEmitter.emit(event, ...args);
436
459
  }
437
460
  /**
438
- * Notify the client using a notification. Provide the type of notification, the message, and an ID.
461
+ * Notify the client using a notification. Provide the type of notification, the message, and an ID.
439
462
  * @param notification {Notification}
440
463
  */
441
464
  notify(notification) {
442
465
  this.addonWSListener.send("notification", [notification]);
443
466
  }
444
467
  /**
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[]>}
468
+ * Get the app details for a given appID and storefront.
469
+ * @param appID {number}
470
+ * @param storefront {string}
471
+ * @returns {Promise<StoreData>}
448
472
  */
449
- async steamSearch(query, strict = false) {
450
- const id = this.addonWSListener.send("steam-search", { query, strict });
473
+ async getAppDetails(appID, storefront) {
474
+ const id = this.addonWSListener.send("get-app-details", {
475
+ appID,
476
+ storefront
477
+ });
451
478
  return await this.addonWSListener.waitForResponseFromServer(id);
452
479
  }
453
480
  /**
@@ -461,7 +488,13 @@ var OGIAddon = class {
461
488
  const progress = 0;
462
489
  const logs = [];
463
490
  const task = new CustomTask(this.addonWSListener, id, progress, logs);
464
- this.addonWSListener.send("task-update", { id, progress, logs, finished: false, failed: void 0 });
491
+ this.addonWSListener.send("task-update", {
492
+ id,
493
+ progress,
494
+ logs,
495
+ finished: false,
496
+ failed: void 0
497
+ });
465
498
  return task;
466
499
  }
467
500
  };
@@ -495,12 +528,21 @@ var CustomTask = class {
495
528
  this.update();
496
529
  }
497
530
  update() {
498
- this.ws.send("task-update", { id: this.id, progress: this.progress, logs: this.logs, finished: this.finished, failed: this.failed });
531
+ this.ws.send("task-update", {
532
+ id: this.id,
533
+ progress: this.progress,
534
+ logs: this.logs,
535
+ finished: this.finished,
536
+ failed: this.failed
537
+ });
499
538
  }
500
539
  };
501
540
  var SearchTool = class {
502
541
  fuse;
503
- constructor(items, keys, options = { threshold: 0.3, includeScore: true }) {
542
+ constructor(items, keys, options = {
543
+ threshold: 0.3,
544
+ includeScore: true
545
+ }) {
504
546
  this.fuse = new Fuse(items, {
505
547
  keys,
506
548
  ...options
@@ -519,7 +561,9 @@ var OGIAddonWSListener = class {
519
561
  addon;
520
562
  constructor(ogiAddon, eventEmitter) {
521
563
  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.");
564
+ throw new Error(
565
+ "No secret provided. This usually happens because the addon was not started by the OGI Addon Server."
566
+ );
523
567
  }
524
568
  this.addon = ogiAddon;
525
569
  this.eventEmitter = eventEmitter;
@@ -540,7 +584,9 @@ var OGIAddonWSListener = class {
540
584
  });
541
585
  this.socket.on("error", (error) => {
542
586
  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.");
587
+ throw new Error(
588
+ "OGI Addon Server is not running/is unreachable. Please start the server and try again."
589
+ );
544
590
  }
545
591
  console.error("An error occurred:", error);
546
592
  });
@@ -563,15 +609,17 @@ var OGIAddonWSListener = class {
563
609
  if (!socket) {
564
610
  return {};
565
611
  }
566
- socket.send(JSON.stringify({
567
- event: "input-asked",
568
- args: {
569
- config,
570
- name,
571
- description
572
- },
573
- id
574
- }));
612
+ socket.send(
613
+ JSON.stringify({
614
+ event: "input-asked",
615
+ args: {
616
+ config,
617
+ name,
618
+ description
619
+ },
620
+ id
621
+ })
622
+ );
575
623
  return await this.waitForResponseFromServer(id);
576
624
  }
577
625
  registerMessageReceiver() {
@@ -581,20 +629,39 @@ var OGIAddonWSListener = class {
581
629
  case "config-update":
582
630
  const result = this.addon.config.updateConfig(message.args);
583
631
  if (!result[0]) {
584
- this.respondToMessage(message.id, { success: false, error: result[1] });
632
+ this.respondToMessage(message.id, {
633
+ success: false,
634
+ error: result[1]
635
+ });
585
636
  } else {
586
637
  this.respondToMessage(message.id, { success: true });
587
638
  }
588
639
  break;
589
640
  case "search":
590
- let searchResultEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
641
+ let searchResultEvent = new EventResponse(
642
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
643
+ );
591
644
  this.eventEmitter.emit("search", message.args, searchResultEvent);
592
645
  const searchResult = await this.waitForEventToRespond(searchResultEvent);
593
646
  this.respondToMessage(message.id, searchResult.data);
594
647
  break;
595
648
  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);
649
+ let setupEvent = new EventResponse(
650
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
651
+ );
652
+ this.eventEmitter.emit(
653
+ "setup",
654
+ {
655
+ path: message.args.path,
656
+ appID: message.args.appID,
657
+ storefront: message.args.storefront,
658
+ type: message.args.type,
659
+ name: message.args.name,
660
+ usedRealDebrid: message.args.usedRealDebrid,
661
+ multiPartFiles: message.args.multiPartFiles
662
+ },
663
+ setupEvent
664
+ );
598
665
  const interval = setInterval(() => {
599
666
  if (setupEvent.resolved) {
600
667
  clearInterval(interval);
@@ -611,42 +678,75 @@ var OGIAddonWSListener = class {
611
678
  this.respondToMessage(message.id, setupResult.data);
612
679
  break;
613
680
  case "library-search":
614
- let librarySearchEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
681
+ let librarySearchEvent = new EventResponse(
682
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
683
+ );
615
684
  if (this.eventEmitter.listenerCount("game-details") === 0) {
616
685
  this.respondToMessage(message.id, []);
617
686
  break;
618
687
  }
619
- this.eventEmitter.emit("library-search", message.args, librarySearchEvent);
688
+ this.eventEmitter.emit(
689
+ "library-search",
690
+ message.args,
691
+ librarySearchEvent
692
+ );
620
693
  const librarySearchResult = await this.waitForEventToRespond(librarySearchEvent);
621
694
  this.respondToMessage(message.id, librarySearchResult.data);
622
695
  break;
623
696
  case "game-details":
624
- let gameDetailsEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
697
+ let gameDetailsEvent = new EventResponse(
698
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
699
+ );
625
700
  if (this.eventEmitter.listenerCount("game-details") === 0) {
626
- this.respondToMessage(message.id, { error: "No event listener for game-details" });
701
+ this.respondToMessage(message.id, {
702
+ error: "No event listener for game-details"
703
+ });
627
704
  break;
628
705
  }
629
- this.eventEmitter.emit("game-details", message.args, gameDetailsEvent);
706
+ this.eventEmitter.emit(
707
+ "game-details",
708
+ message.args,
709
+ gameDetailsEvent
710
+ );
630
711
  const gameDetailsResult = await this.waitForEventToRespond(gameDetailsEvent);
631
712
  this.respondToMessage(message.id, gameDetailsResult.data);
632
713
  break;
633
714
  case "request-dl":
634
- let requestDLEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
715
+ let requestDLEvent = new EventResponse(
716
+ (screen, name, description) => this.userInputAsked(screen, name, description, this.socket)
717
+ );
635
718
  if (this.eventEmitter.listenerCount("request-dl") === 0) {
636
- this.respondToMessage(message.id, { error: "No event listener for request-dl" });
719
+ this.respondToMessage(message.id, {
720
+ error: "No event listener for request-dl"
721
+ });
637
722
  break;
638
723
  }
639
- this.eventEmitter.emit("request-dl", message.args.appID, message.args.info, requestDLEvent);
724
+ this.eventEmitter.emit(
725
+ "request-dl",
726
+ message.args.appID,
727
+ message.args.info,
728
+ requestDLEvent
729
+ );
640
730
  const requestDLResult = await this.waitForEventToRespond(requestDLEvent);
641
731
  if (requestDLEvent.failed) {
642
- this.respondToMessage(message.id, { statusError: requestDLEvent.failed });
732
+ this.respondToMessage(message.id, {
733
+ statusError: requestDLEvent.failed
734
+ });
643
735
  break;
644
736
  }
645
737
  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.");
738
+ throw new Error(
739
+ "Request DL event did not return a valid result. Please ensure that the event does not resolve with another `request` download type."
740
+ );
647
741
  }
648
742
  this.respondToMessage(message.id, requestDLResult.data);
649
743
  break;
744
+ case "catalog":
745
+ let catalogEvent = new EventResponse();
746
+ this.eventEmitter.emit("catalog", catalogEvent);
747
+ const catalogResult = await this.waitForEventToRespond(catalogEvent);
748
+ this.respondToMessage(message.id, catalogResult.data);
749
+ break;
650
750
  }
651
751
  });
652
752
  }
@@ -674,11 +774,13 @@ var OGIAddonWSListener = class {
674
774
  });
675
775
  }
676
776
  respondToMessage(messageID, response) {
677
- this.socket.send(JSON.stringify({
678
- event: "response",
679
- id: messageID,
680
- args: response
681
- }));
777
+ this.socket.send(
778
+ JSON.stringify({
779
+ event: "response",
780
+ id: messageID,
781
+ args: response
782
+ })
783
+ );
682
784
  console.log("dispatched response to " + messageID);
683
785
  }
684
786
  waitForResponseFromServer(messageID) {
@@ -701,11 +803,13 @@ var OGIAddonWSListener = class {
701
803
  }
702
804
  send(event, args) {
703
805
  const id = Math.random().toString(36).substring(7);
704
- this.socket.send(JSON.stringify({
705
- event,
706
- args,
707
- id
708
- }));
806
+ this.socket.send(
807
+ JSON.stringify({
808
+ event,
809
+ args,
810
+ id
811
+ })
812
+ );
709
813
  return id;
710
814
  }
711
815
  close() {