@stripchatdev/ext-helper 0.3.0 → 0.3.2

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.
@@ -1,8 +1,8 @@
1
1
  const O = (e) => !!e && typeof e == "object" && "protocol" in e && e.protocol === "platform_pubsub" && "version" in e && e.version === "1.0", I = (e) => e, P = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
2
- var f;
2
+ var m;
3
3
  (function(e) {
4
4
  e.Base32IncorrectEncoding = "B32_ENC_INVALID", e.DecodeTimeInvalidCharacter = "DEC_TIME_CHAR", e.DecodeTimeValueMalformed = "DEC_TIME_MALFORMED", e.EncodeTimeNegative = "ENC_TIME_NEG", e.EncodeTimeSizeExceeded = "ENC_TIME_SIZE_EXCEED", e.EncodeTimeValueMalformed = "ENC_TIME_MALFORMED", e.PRNGDetectFailure = "PRNG_DETECT", e.ULIDInvalid = "ULID_INVALID", e.Unexpected = "UNEXPECTED", e.UUIDInvalid = "UUID_INVALID";
5
- })(f || (f = {}));
5
+ })(m || (m = {}));
6
6
  class y extends Error {
7
7
  constructor(t, r) {
8
8
  super(`${r} (${t})`), this.name = "ULIDError", this.code = t;
@@ -13,7 +13,7 @@ function A(e) {
13
13
  return P.charAt(t);
14
14
  }
15
15
  function x(e) {
16
- const t = C(), r = t && (t.crypto || t.msCrypto) || null;
16
+ const t = D(), r = t && (t.crypto || t.msCrypto) || null;
17
17
  if (typeof (r == null ? void 0 : r.getRandomValues) == "function")
18
18
  return () => {
19
19
  const n = new Uint8Array(1);
@@ -21,12 +21,12 @@ function x(e) {
21
21
  };
22
22
  if (typeof (r == null ? void 0 : r.randomBytes) == "function")
23
23
  return () => r.randomBytes(1).readUInt8() / 255;
24
- throw new y(f.PRNGDetectFailure, "Failed to find a reliable PRNG");
24
+ throw new y(m.PRNGDetectFailure, "Failed to find a reliable PRNG");
25
25
  }
26
- function C() {
26
+ function D() {
27
27
  return j() ? self : typeof window < "u" ? window : typeof global < "u" ? global : typeof globalThis < "u" ? globalThis : null;
28
28
  }
29
- function D(e, t) {
29
+ function C(e, t) {
30
30
  let r = "";
31
31
  for (; e > 0; e--)
32
32
  r = A(t) + r;
@@ -34,13 +34,13 @@ function D(e, t) {
34
34
  }
35
35
  function F(e, t = 10) {
36
36
  if (isNaN(e))
37
- throw new y(f.EncodeTimeValueMalformed, `Time must be a number: ${e}`);
37
+ throw new y(m.EncodeTimeValueMalformed, `Time must be a number: ${e}`);
38
38
  if (e > 281474976710655)
39
- throw new y(f.EncodeTimeSizeExceeded, `Cannot encode a time larger than ${281474976710655}: ${e}`);
39
+ throw new y(m.EncodeTimeSizeExceeded, `Cannot encode a time larger than ${281474976710655}: ${e}`);
40
40
  if (e < 0)
41
- throw new y(f.EncodeTimeNegative, `Time must be positive: ${e}`);
41
+ throw new y(m.EncodeTimeNegative, `Time must be positive: ${e}`);
42
42
  if (Number.isInteger(e) === !1)
43
- throw new y(f.EncodeTimeValueMalformed, `Time must be an integer: ${e}`);
43
+ throw new y(m.EncodeTimeValueMalformed, `Time must be an integer: ${e}`);
44
44
  let r, n = "";
45
45
  for (let s = t; s > 0; s--)
46
46
  r = e % 32, n = P.charAt(r) + n, e = (e - r) / 32;
@@ -51,7 +51,7 @@ function j() {
51
51
  }
52
52
  function E(e, t) {
53
53
  const r = t || x(), n = !e || isNaN(e) ? Date.now() : e;
54
- return F(n, 10) + D(16, r);
54
+ return F(n, 10) + C(16, r);
55
55
  }
56
56
  const G = ({ seq: e, uniqId: t }) => (r) => ({
57
57
  ...{
@@ -69,17 +69,17 @@ const G = ({ seq: e, uniqId: t }) => (r) => ({
69
69
  class z {
70
70
  constructor(t) {
71
71
  this.eventHandlerMap = /* @__PURE__ */ new Map(), this.transportMessageHandler = (s) => {
72
- const { data: o, senderId: i } = s;
72
+ const { data: o, senderId: a } = s;
73
73
  if (O(o)) {
74
74
  if (o.type === "event") {
75
- const { eventName: a } = o, c = this.eventHandlerMap.get(a);
75
+ const { eventName: i } = o, c = this.eventHandlerMap.get(i);
76
76
  if (!c)
77
77
  return;
78
- c.forEach((h) => {
78
+ c.forEach((l) => {
79
79
  try {
80
- h(o.data, i);
81
- } catch (m) {
82
- console.error("[PubSubSubscriber] transportMessageHandler: failed to handle income message", m);
80
+ l(o.data, a);
81
+ } catch (f) {
82
+ console.error("[PubSubSubscriber] transportMessageHandler: failed to handle income message", f);
83
83
  }
84
84
  });
85
85
  return;
@@ -170,21 +170,21 @@ class Z {
170
170
  const { data: o } = s;
171
171
  if (U(o)) {
172
172
  if (o.type === "response" && o.status === "ok") {
173
- const i = this.pendingEntryMap.get(o.requestId);
174
- if (!i) {
173
+ const a = this.pendingEntryMap.get(o.requestId);
174
+ if (!a) {
175
175
  console.error("[RpcClient] transportMessageHandler: got success response without pending request", o);
176
176
  return;
177
177
  }
178
- this.pendingEntryMap.delete(o.requestId), i.resolve(o.result);
178
+ this.pendingEntryMap.delete(o.requestId), a.resolve(o.result);
179
179
  return;
180
180
  }
181
181
  if (o.type === "response" && o.status === "error") {
182
- const i = this.pendingEntryMap.get(o.requestId);
183
- if (!i) {
182
+ const a = this.pendingEntryMap.get(o.requestId);
183
+ if (!a) {
184
184
  console.error("[RpcClient] transportMessageHandler: got error response without pending request", o);
185
185
  return;
186
186
  }
187
- this.pendingEntryMap.delete(o.requestId), i.reject(new $(o.error));
187
+ this.pendingEntryMap.delete(o.requestId), a.reject(new $(o.error));
188
188
  return;
189
189
  }
190
190
  console.error("[RpcClient] transportMessageHandler: invalid message schema", o);
@@ -198,14 +198,14 @@ class Z {
198
198
  type: "request",
199
199
  method: t,
200
200
  params: r
201
- }), s = new Promise((o, i) => {
201
+ }), s = new Promise((o, a) => {
202
202
  this.pendingEntryMap.set(n.requestId, {
203
203
  method: t,
204
- resolve: (a) => {
205
- o(a);
204
+ resolve: (i) => {
205
+ o(i);
206
206
  },
207
- reject: (a) => {
208
- i(a);
207
+ reject: (i) => {
208
+ a(i);
209
209
  }
210
210
  });
211
211
  });
@@ -213,8 +213,8 @@ class Z {
213
213
  this.transport.send(this.serverId, n);
214
214
  } catch (o) {
215
215
  console.error("[RpcClient] makeRequest: failed to send rpc message", o);
216
- const i = this.pendingEntryMap.get(n.requestId);
217
- i && (this.pendingEntryMap.delete(n.requestId), i.reject(o));
216
+ const a = this.pendingEntryMap.get(n.requestId);
217
+ a && (this.pendingEntryMap.delete(n.requestId), a.reject(o));
218
218
  }
219
219
  return s;
220
220
  }
@@ -230,14 +230,14 @@ const Q = (e) => !!e && typeof e == "object" && "protocol" in e && e.protocol ==
230
230
  class ee {
231
231
  constructor(t) {
232
232
  this.peers = /* @__PURE__ */ new Map(), this.handlers = /* @__PURE__ */ new Set(), this.onMessage = (s) => {
233
- const o = (i) => {
234
- const { data: a, origin: c, source: h } = i;
235
- if (!h || !Q(a))
233
+ const o = (a) => {
234
+ const { data: i, origin: c, source: l } = a;
235
+ if (!l || !Q(i))
236
236
  return;
237
- const { recipientId: m } = a;
238
- if (!(m !== this.transportId || !this.findPeer(h, c)))
237
+ const { recipientId: f } = i;
238
+ if (!(f !== this.transportId || !this.findPeer(l, c)))
239
239
  try {
240
- s(a);
240
+ s(i);
241
241
  } catch (w) {
242
242
  console.error("[PostMessageTransport] onMessage: failed to call cb on message", w);
243
243
  }
@@ -329,10 +329,10 @@ const g = {
329
329
  };
330
330
  }
331
331
  return g;
332
- }, _ = (e) => {
332
+ }, L = (e) => {
333
333
  const t = [];
334
334
  if (e instanceof Error)
335
- t.push(e.message), "cause" in e && t.push(_(e.cause));
335
+ t.push(e.message), "cause" in e && t.push(L(e.cause));
336
336
  else
337
337
  try {
338
338
  const r = JSON.stringify(e);
@@ -365,28 +365,28 @@ const g = {
365
365
  /networkError when attempting to fetch resource/ig,
366
366
  /load failed/ig
367
367
  ], re = (e) => te.some((t) => (t.lastIndex = 0, t.test(e))), ne = (e) => {
368
- const t = _(e.error), r = typeof e.data == "object" && "message" in e.data && typeof e.data.message == "string" ? e.data.message : "";
368
+ const t = L(e.error), r = typeof e.data == "object" && "message" in e.data && typeof e.data.message == "string" ? e.data.message : "";
369
369
  return [t, r].filter((n) => !!n).join(":");
370
370
  }, se = (e) => e.data && typeof e.data == "object" && "filename" in e.data ? String(e.data.filename ?? "") : "", oe = (e) => {
371
371
  const t = ne(e), r = se(e);
372
372
  return r && /^(chrome|moz|safari)-extension:\/\//.test(r) ? !0 : !!t && re(t);
373
- }, ie = "get", ae = (e, t) => {
373
+ }, ae = "get", ie = (e, t) => {
374
374
  var s;
375
375
  let r, n;
376
376
  return e instanceof Request ? (r = e.url, n = e.method) : e instanceof URL ? r = e.toString() : r = e, {
377
- method: n || ((s = t == null ? void 0 : t.method) == null ? void 0 : s.toString()) || ie,
377
+ method: n || ((s = t == null ? void 0 : t.method) == null ? void 0 : s.toString()) || ae,
378
378
  url: r
379
379
  };
380
380
  }, ce = (e, t, r) => ({
381
381
  statusCode: r.status,
382
- ...ae(e, t)
382
+ ...ie(e, t)
383
383
  }), ue = (e) => {
384
384
  const t = window.fetch;
385
385
  Object.defineProperty(window, "fetch", {
386
386
  value: async (n, s) => {
387
387
  try {
388
- const o = new Error("synthetic error"), i = await t(n, s), a = i.clone(), c = ce(n, s, a);
389
- if (i.status >= 500) {
388
+ const o = new Error("synthetic error"), a = await t(n, s), i = a.clone(), c = ce(n, s, i);
389
+ if (a.status >= 500) {
390
390
  const d = new Error("fetch response error");
391
391
  d.stack = o.stack, e.report({
392
392
  kind: "fetchResponseError",
@@ -396,12 +396,12 @@ const g = {
396
396
  });
397
397
  }
398
398
  const {
399
- arrayBuffer: h,
400
- blob: m,
399
+ arrayBuffer: l,
400
+ blob: f,
401
401
  json: M,
402
402
  text: w
403
- } = i;
404
- return i.json = async function() {
403
+ } = a;
404
+ return a.json = async function() {
405
405
  try {
406
406
  return await M.call(this);
407
407
  } catch (d) {
@@ -415,7 +415,7 @@ const g = {
415
415
  }
416
416
  }), d;
417
417
  }
418
- }, i.text = async function() {
418
+ }, a.text = async function() {
419
419
  try {
420
420
  return await w.call(this);
421
421
  } catch (d) {
@@ -429,9 +429,9 @@ const g = {
429
429
  }
430
430
  }), d;
431
431
  }
432
- }, i.blob = async function() {
432
+ }, a.blob = async function() {
433
433
  try {
434
- return await m.call(this);
434
+ return await f.call(this);
435
435
  } catch (d) {
436
436
  throw e.report({
437
437
  type: "network",
@@ -443,9 +443,9 @@ const g = {
443
443
  }
444
444
  }), d;
445
445
  }
446
- }, i.arrayBuffer = async function() {
446
+ }, a.arrayBuffer = async function() {
447
447
  try {
448
- return await h.call(this);
448
+ return await l.call(this);
449
449
  } catch (d) {
450
450
  throw e.report({
451
451
  type: "network",
@@ -457,7 +457,7 @@ const g = {
457
457
  }
458
458
  }), d;
459
459
  }
460
- }, i;
460
+ }, a;
461
461
  } catch (o) {
462
462
  throw o instanceof Error && o.name === "AbortError", o;
463
463
  }
@@ -485,23 +485,23 @@ const g = {
485
485
  }
486
486
  });
487
487
  });
488
- }, L = Symbol("patchedXHLHttpRequest"), p = Symbol("requestInfo"), le = (e) => ({
488
+ }, _ = Symbol("patchedXHLHttpRequest"), h = Symbol("requestInfo"), le = (e) => ({
489
489
  statusCode: e.status,
490
- ...e[p]
491
- }), pe = (e) => (e[p] || (e[p] = {}), e[p]), he = (e) => {
492
- e[L] = !0;
493
- }, fe = (e) => e[L] === !0, me = (e) => {
490
+ ...e[h]
491
+ }), pe = (e) => (e[h] || (e[h] = {}), e[h]), he = (e) => {
492
+ e[_] = !0;
493
+ }, fe = (e) => e[_] === !0, me = (e) => {
494
494
  const t = XMLHttpRequest.prototype.send, r = XMLHttpRequest.prototype.open, n = function(...o) {
495
- const [i, a] = o;
496
- this[p] = {
497
- method: i,
498
- url: typeof a == "string" ? a : a.toString()
495
+ const [a, i] = o;
496
+ this[h] = {
497
+ method: a,
498
+ url: typeof i == "string" ? i : i.toString()
499
499
  }, fe(this) || (he(this), this.addEventListener("error", () => {
500
500
  const c = new Error("XMLHttpRequest network error");
501
501
  e.report({
502
502
  type: "network",
503
503
  kind: "xmlHttpRequestError",
504
- data: this[p],
504
+ data: this[h],
505
505
  error: c
506
506
  });
507
507
  }), this.addEventListener("timeout", () => {
@@ -509,7 +509,7 @@ const g = {
509
509
  e.report({
510
510
  type: "network",
511
511
  kind: "xmlHttpRequestTimeoutError",
512
- data: this[p],
512
+ data: this[h],
513
513
  error: c
514
514
  });
515
515
  }), this.addEventListener("load", () => {
@@ -530,20 +530,20 @@ const g = {
530
530
  type: "network",
531
531
  kind: "xmlHttpRequestOpenError",
532
532
  error: c,
533
- data: this[p]
533
+ data: this[h]
534
534
  }), c;
535
535
  }
536
536
  }, s = function(o) {
537
537
  try {
538
- const i = pe(this), a = new Error("XMLHttpRequest request initiator");
539
- i.requestStack = a.stack, t.call(this, o);
540
- } catch (i) {
538
+ const a = pe(this), i = new Error("XMLHttpRequest request initiator");
539
+ a.requestStack = i.stack, t.call(this, o);
540
+ } catch (a) {
541
541
  throw e.report({
542
542
  type: "network",
543
543
  kind: "xmlHttpRequestSendError",
544
- error: i,
545
- data: this[p]
546
- }), i;
544
+ error: a,
545
+ data: this[h]
546
+ }), a;
547
547
  }
548
548
  };
549
549
  Object.defineProperty(XMLHttpRequest.prototype, "open", {
@@ -581,25 +581,26 @@ class ye {
581
581
  constructor(t) {
582
582
  const {
583
583
  frameId: r,
584
- serverId: n,
585
- serverOrigin: s,
586
- serverSource: o,
584
+ lang: n,
585
+ serverId: s,
586
+ serverOrigin: o,
587
+ serverSource: a,
587
588
  theme: i
588
- } = t, a = {
589
- id: n,
590
- origin: s,
591
- source: o
592
- }, c = new ee({
589
+ } = t, c = {
590
+ id: s,
591
+ origin: o,
592
+ source: a
593
+ }, l = new ee({
593
594
  transportId: r
594
595
  });
595
- c.addPeer(a), this.rpcClient = new Z({
596
- transport: c,
597
- serverId: n
596
+ l.addPeer(c), this.rpcClient = new Z({
597
+ transport: l,
598
+ serverId: s
598
599
  }), this.subscriber = new z({
599
- transport: c,
600
- brokerId: a.id
601
- }), document.documentElement.dataset.theme = i, this.crashReporter = new ge((h) => {
602
- this.makeRequest("v1.system.report.crash", h);
600
+ transport: l,
601
+ brokerId: c.id
602
+ }), document.documentElement.dataset.theme = i, document.documentElement.lang = n, this.crashReporter = new ge((f) => {
603
+ this.makeRequest("v1.system.report.crash", f);
603
604
  });
604
605
  }
605
606
  makeRequest(t, r) {
@@ -614,20 +615,20 @@ class ye {
614
615
  bootstrap() {
615
616
  let t = { height: 0, width: 0 };
616
617
  const r = () => {
617
- const a = document.body;
618
+ const i = document.body;
618
619
  return Math.max(
619
- a.offsetHeight,
620
- a.scrollHeight
620
+ i.offsetHeight,
621
+ i.scrollHeight
621
622
  );
622
623
  }, n = () => {
623
- const a = document.body;
624
+ const i = document.body;
624
625
  return Math.max(
625
- a.offsetWidth,
626
- a.scrollWidth
626
+ i.offsetWidth,
627
+ i.scrollWidth
627
628
  );
628
629
  }, s = () => {
629
- const a = n(), c = r();
630
- (t.height !== c || t.width !== a) && (t = { height: c, width: a }, this.makeRequest("v1.system.resize.notify", { height: c, width: a }));
630
+ const i = n(), c = r();
631
+ (t.height !== c || t.width !== i) && (t = { height: c, width: i }, this.makeRequest("v1.system.resize.notify", { height: c, width: i }));
631
632
  };
632
633
  s(), new ResizeObserver(s).observe(document.body), new MutationObserver(s).observe(document.body, {
633
634
  childList: !0,
@@ -664,7 +665,7 @@ function Se(e) {
664
665
  const r = e instanceof SubmitEvent ? e.submitter : null, n = (r == null ? void 0 : r.getAttribute("formtarget")) || t.getAttribute("target") || ((s = document.querySelector("base[target]")) == null ? void 0 : s.getAttribute("target")) || "_self";
665
666
  R(n) && (e.preventDefault(), e.stopImmediatePropagation());
666
667
  }
667
- const l = () => {
668
+ const p = () => {
668
669
  }, u = (e, t, r) => {
669
670
  const n = e;
670
671
  if (!n || typeof n[t] != "function")
@@ -681,34 +682,36 @@ const l = () => {
681
682
  } catch {
682
683
  }
683
684
  }, Ne = () => {
684
- u(Window.prototype, "open", () => null), u(window, "open", () => null), u(Element.prototype, "scrollIntoView", l), u(
685
+ u(Window.prototype, "open", () => null), u(window, "open", () => null), u(Element.prototype, "scrollIntoView", p), u(
685
686
  Element.prototype,
686
687
  "scrollIntoViewIfNeeded",
687
- l
688
- ), u(HTMLElement.prototype, "focus", T), u(SVGElement.prototype, "focus", T), u(History.prototype, "back", l), u(History.prototype, "forward", l), u(History.prototype, "go", l), u(History.prototype, "pushState", l), u(History.prototype, "replaceState", l), u(
688
+ p
689
+ ), u(HTMLElement.prototype, "focus", T), u(SVGElement.prototype, "focus", T), u(History.prototype, "back", p), u(History.prototype, "forward", p), u(History.prototype, "go", p), u(History.prototype, "pushState", p), u(History.prototype, "replaceState", p), u(
689
690
  HTMLVideoElement.prototype,
690
691
  "requestPictureInPicture",
691
692
  () => Promise.resolve({})
692
- ), u(HTMLFormElement.prototype, "submit", Ie), u(HTMLFormElement.prototype, "requestSubmit", ve), typeof Location < "u" && (u(Location.prototype, "assign", l), u(Location.prototype, "replace", l), u(Location.prototype, "reload", l)), document.addEventListener("submit", Se, !0);
693
- }, H = (e) => typeof e == "object" && e !== null && !Array.isArray(e), Te = (e) => H(e) ? typeof e.code == "string" && typeof e.message == "string" && (e.details === void 0 || H(e.details)) : !1;
693
+ ), u(HTMLFormElement.prototype, "submit", Ie), u(HTMLFormElement.prototype, "requestSubmit", ve), typeof Location < "u" && (u(Location.prototype, "assign", p), u(Location.prototype, "replace", p), u(Location.prototype, "reload", p)), document.addEventListener("submit", Se, !0);
694
+ }, H = (e) => typeof e == "object" && e !== null && !Array.isArray(e), He = (e) => H(e) ? typeof e.code == "string" && typeof e.message == "string" && (e.details === void 0 || H(e.details)) : !1;
694
695
  let k = !1;
696
+ const Te = "en";
695
697
  typeof window < "u" && typeof document < "u" && Ne();
696
- const He = () => {
698
+ const ke = () => {
697
699
  if (k)
698
700
  throw new Error("ext helper already created, only one instance is allowed");
699
- const e = new URL(window.location.href), t = e.searchParams.get("origin") || "", r = e.searchParams.get("theme") || "dark", n = e.searchParams.get("frameId");
700
- if (!n)
701
+ const e = new URL(window.location.href), t = e.searchParams.get("origin") || "", r = e.searchParams.get("theme") || "dark", n = e.searchParams.get("lang") || Te, s = e.searchParams.get("frameId");
702
+ if (!s)
701
703
  throw new Error("failed to create ext helper, frameId is empty");
702
- const s = new ye({
704
+ const o = new ye({
703
705
  serverId: "server",
704
706
  serverOrigin: t || window.parent.origin,
705
707
  serverSource: window.parent,
706
- frameId: n,
707
- theme: r
708
+ frameId: s,
709
+ theme: r,
710
+ lang: n
708
711
  });
709
- return s.bootstrap(), k = !0, s;
712
+ return o.bootstrap(), k = !0, o;
710
713
  };
711
714
  export {
712
- He as createExtHelper,
713
- Te as isExtensionError
715
+ ke as createExtHelper,
716
+ He as isExtensionError
714
717
  };
@@ -119,6 +119,8 @@ export declare type TSlotStateSnapshot<State extends object> = {
119
119
  state: State | null;
120
120
  };
121
121
 
122
+ declare type TTheme = 'light' | 'dark';
123
+
122
124
  declare type TTransportPeer = {
123
125
  id: string;
124
126
  };
@@ -143,6 +145,8 @@ declare type TV1ActionResult = {
143
145
  code: number;
144
146
  };
145
147
 
148
+ declare type TV1AnalyticsTrackParams = TV1UiInteractionTrackParams;
149
+
146
150
  declare type TV1ChatEvents = {
147
151
  /** Triggered on every new message in a chat */
148
152
  'v1.chat.message.received': {
@@ -192,6 +196,20 @@ declare type TV1ChatMethods = {
192
196
  };
193
197
  result: null;
194
198
  };
199
+ /**
200
+ * Send a rich message to the chat with customizable colors.
201
+ *
202
+ * The message is sent locally on behalf of the extension. It is not sent to the server or broadcast — each user sees it only in their own local chat feed.
203
+ *
204
+ * Because the message is local, it is **not persisted**: it disappears from chat history when the page is reloaded.
205
+ *
206
+ * Required permission:
207
+ * - `richMessage`
208
+ */
209
+ 'v1.chat.richMessage.send': {
210
+ params: TV1RichMessage;
211
+ result: null;
212
+ };
195
213
  /** Use this method to send a message in the chat as a bot or model.
196
214
  * The message is sent locally to each user and looks like a normal chat message. The message is **not persisted** and will disappear from the chat after the page is reloaded.
197
215
  * */
@@ -324,6 +342,19 @@ declare type TV1ExtMethods = {
324
342
  params: null;
325
343
  result: TV1ExtContext;
326
344
  };
345
+ /**
346
+ * Returns the tag from which the user navigated to the model.
347
+ * `tag` is `null` when the source tag is unknown.
348
+ *
349
+ * Required permission:
350
+ * - `modelTag`
351
+ */
352
+ 'v1.ext.modelTag.get': {
353
+ params: null;
354
+ result: {
355
+ tag: TV1ExtModelTag | null;
356
+ };
357
+ };
327
358
  'v1.ext.movableOverlay.update': {
328
359
  params: {
329
360
  message?: string;
@@ -340,6 +371,8 @@ declare type TV1ExtMethods = {
340
371
  /** Opens Stripchat sign-up dialog for anonymous users. Use this when your extension requires a registered account to function */
341
372
  'v1.ext.signup.open': {
342
373
  params: {
374
+ /** Optional source string to identify the origin of the sign-up request. Internal use only */
375
+ source?: string;
343
376
  type: 'user';
344
377
  };
345
378
  result: null;
@@ -418,6 +451,21 @@ declare type TV1ExtModel = {
418
451
  username: string;
419
452
  };
420
453
 
454
+ /**
455
+ * Tag from which the user navigated to the model.
456
+ *
457
+ * Required permission:
458
+ * - `modelTag`
459
+ */
460
+ declare type TV1ExtModelTag = {
461
+ /** Tag identifier, for example `autoTagNew` */
462
+ id: string;
463
+ /** Primary tag the tag belongs to */
464
+ primaryTagId: 'girls' | 'men' | 'trans' | 'couples';
465
+ /** Tag URL path, for example `girls/new` */
466
+ url: string;
467
+ };
468
+
421
469
  declare type TV1ExtSettings = unknown;
422
470
 
423
471
  declare type TV1ExtUser = TV1ExtGuestUser | TV1ExtLoggedInUser;
@@ -593,6 +641,52 @@ declare type TV1PrivateMethods = {
593
641
  };
594
642
  };
595
643
 
644
+ declare type TV1RichMessage = {
645
+ /** The main action appearance. It opens the extension tab on click. If omitted, the default action is a link. */
646
+ action?: {
647
+ text?: string;
648
+ type: 'link' | 'button';
649
+ };
650
+ /** One of the predefined extension icons. If omitted, the icon from the manifest is used. */
651
+ icon?: 'sex-toy-1' | 'sex-toy-2' | 'spicy-pepper';
652
+ /**
653
+ * Rich message subtitle.
654
+ *
655
+ * Supports inline markup tags:
656
+ * - `{#primary}...{/primary}` — uses the primary text color.
657
+ * - `{#secondary}...{/secondary}` — uses the secondary text color.
658
+ * - `{#accent}...{/accent}` — highlights text with an accent color.
659
+ * - `{#bold}...{/bold}` — renders bold text.
660
+ *
661
+ * Example: `'won {#accent}Alice{/accent} in'`
662
+ */
663
+ subtitle: string;
664
+ /** Optional custom theme. If omitted, the default theme is used. */
665
+ theme?: {
666
+ [Property in TTheme]?: TV1RichMessageTheme;
667
+ };
668
+ /**
669
+ * Rich message title.
670
+ *
671
+ * Supports inline markup tags:
672
+ * - `{#primary}...{/primary}` — uses the primary text color.
673
+ * - `{#secondary}...{/secondary}` — uses the secondary text color.
674
+ * - `{#accent}...{/accent}` — highlights text with an accent color.
675
+ * - `{#bold}...{/bold}` — renders bold text.
676
+ *
677
+ * Example: `'won {#accent}Alice{/accent} in'`
678
+ */
679
+ title: string;
680
+ };
681
+
682
+ declare type TV1RichMessageTheme = {
683
+ /** Rich message background color. Use a hex color. */
684
+ background: string;
685
+ buttonText: 'white' | 'dark';
686
+ /** Main accent color of the rich message, used for the sidebar, highlights, links, and buttons. Use a hex color. */
687
+ main: string;
688
+ };
689
+
596
690
  declare type TV1SerializedError = {
597
691
  cause?: TV1SerializedError;
598
692
  message: string;
@@ -942,6 +1036,10 @@ declare type TV1StorageMethods = {
942
1036
  };
943
1037
 
944
1038
  declare type TV1SystemMethods = {
1039
+ 'v1.system.analytics.track': {
1040
+ params: TV1AnalyticsTrackParams;
1041
+ result: null;
1042
+ };
945
1043
  'v1.system.report.crash': {
946
1044
  params: {
947
1045
  data?: Record<string, unknown>;
@@ -1081,6 +1179,17 @@ declare type TV1TopUserEntry = {
1081
1179
 
1082
1180
  declare type TV1TopWindow = 'TOP_1D' | 'TOP_7D' | 'TOP_30D' | 'TOP_UNSPECIFIED';
1083
1181
 
1182
+ declare type TV1UiInteractionTrackParams = {
1183
+ data: {
1184
+ elementId: string;
1185
+ elementType: 'banner' | 'button' | 'tile' | 'popup' | 'extensionButton';
1186
+ interactionType: 'view' | 'click' | 'close' | 'dismiss';
1187
+ optionSelected?: string;
1188
+ pageSection?: string;
1189
+ };
1190
+ type: 'uiInteraction';
1191
+ };
1192
+
1084
1193
  /**
1085
1194
  * User activity league. Ordered from lowest to highest activity rank:
1086
1195
  * - `grey` — new or low-activity users (level 1–9)
@@ -53,6 +53,8 @@ declare type TMethods = TV1Methods;
53
53
  */
54
54
  declare type TMovableOverlayStatus = 'active' | 'inactive' | 'connecting' | 'error';
55
55
 
56
+ declare type TTheme = 'light' | 'dark';
57
+
56
58
  declare type TTransportPeer = {
57
59
  id: string;
58
60
  };
@@ -77,6 +79,8 @@ declare type TV1ActionResult = {
77
79
  code: number;
78
80
  };
79
81
 
82
+ declare type TV1AnalyticsTrackParams = TV1UiInteractionTrackParams;
83
+
80
84
  declare type TV1ChatEvents = {
81
85
  /** Triggered on every new message in a chat */
82
86
  'v1.chat.message.received': {
@@ -126,6 +130,20 @@ declare type TV1ChatMethods = {
126
130
  };
127
131
  result: null;
128
132
  };
133
+ /**
134
+ * Send a rich message to the chat with customizable colors.
135
+ *
136
+ * The message is sent locally on behalf of the extension. It is not sent to the server or broadcast — each user sees it only in their own local chat feed.
137
+ *
138
+ * Because the message is local, it is **not persisted**: it disappears from chat history when the page is reloaded.
139
+ *
140
+ * Required permission:
141
+ * - `richMessage`
142
+ */
143
+ 'v1.chat.richMessage.send': {
144
+ params: TV1RichMessage;
145
+ result: null;
146
+ };
129
147
  /** Use this method to send a message in the chat as a bot or model.
130
148
  * The message is sent locally to each user and looks like a normal chat message. The message is **not persisted** and will disappear from the chat after the page is reloaded.
131
149
  * */
@@ -258,6 +276,19 @@ declare type TV1ExtMethods = {
258
276
  params: null;
259
277
  result: TV1ExtContext;
260
278
  };
279
+ /**
280
+ * Returns the tag from which the user navigated to the model.
281
+ * `tag` is `null` when the source tag is unknown.
282
+ *
283
+ * Required permission:
284
+ * - `modelTag`
285
+ */
286
+ 'v1.ext.modelTag.get': {
287
+ params: null;
288
+ result: {
289
+ tag: TV1ExtModelTag | null;
290
+ };
291
+ };
261
292
  'v1.ext.movableOverlay.update': {
262
293
  params: {
263
294
  message?: string;
@@ -274,6 +305,8 @@ declare type TV1ExtMethods = {
274
305
  /** Opens Stripchat sign-up dialog for anonymous users. Use this when your extension requires a registered account to function */
275
306
  'v1.ext.signup.open': {
276
307
  params: {
308
+ /** Optional source string to identify the origin of the sign-up request. Internal use only */
309
+ source?: string;
277
310
  type: 'user';
278
311
  };
279
312
  result: null;
@@ -352,6 +385,21 @@ declare type TV1ExtModel = {
352
385
  username: string;
353
386
  };
354
387
 
388
+ /**
389
+ * Tag from which the user navigated to the model.
390
+ *
391
+ * Required permission:
392
+ * - `modelTag`
393
+ */
394
+ declare type TV1ExtModelTag = {
395
+ /** Tag identifier, for example `autoTagNew` */
396
+ id: string;
397
+ /** Primary tag the tag belongs to */
398
+ primaryTagId: 'girls' | 'men' | 'trans' | 'couples';
399
+ /** Tag URL path, for example `girls/new` */
400
+ url: string;
401
+ };
402
+
355
403
  declare type TV1ExtSettings = unknown;
356
404
 
357
405
  declare type TV1ExtUser = TV1ExtGuestUser | TV1ExtLoggedInUser;
@@ -527,6 +575,52 @@ declare type TV1PrivateMethods = {
527
575
  };
528
576
  };
529
577
 
578
+ declare type TV1RichMessage = {
579
+ /** The main action appearance. It opens the extension tab on click. If omitted, the default action is a link. */
580
+ action?: {
581
+ text?: string;
582
+ type: 'link' | 'button';
583
+ };
584
+ /** One of the predefined extension icons. If omitted, the icon from the manifest is used. */
585
+ icon?: 'sex-toy-1' | 'sex-toy-2' | 'spicy-pepper';
586
+ /**
587
+ * Rich message subtitle.
588
+ *
589
+ * Supports inline markup tags:
590
+ * - `{#primary}...{/primary}` — uses the primary text color.
591
+ * - `{#secondary}...{/secondary}` — uses the secondary text color.
592
+ * - `{#accent}...{/accent}` — highlights text with an accent color.
593
+ * - `{#bold}...{/bold}` — renders bold text.
594
+ *
595
+ * Example: `'won {#accent}Alice{/accent} in'`
596
+ */
597
+ subtitle: string;
598
+ /** Optional custom theme. If omitted, the default theme is used. */
599
+ theme?: {
600
+ [Property in TTheme]?: TV1RichMessageTheme;
601
+ };
602
+ /**
603
+ * Rich message title.
604
+ *
605
+ * Supports inline markup tags:
606
+ * - `{#primary}...{/primary}` — uses the primary text color.
607
+ * - `{#secondary}...{/secondary}` — uses the secondary text color.
608
+ * - `{#accent}...{/accent}` — highlights text with an accent color.
609
+ * - `{#bold}...{/bold}` — renders bold text.
610
+ *
611
+ * Example: `'won {#accent}Alice{/accent} in'`
612
+ */
613
+ title: string;
614
+ };
615
+
616
+ declare type TV1RichMessageTheme = {
617
+ /** Rich message background color. Use a hex color. */
618
+ background: string;
619
+ buttonText: 'white' | 'dark';
620
+ /** Main accent color of the rich message, used for the sidebar, highlights, links, and buttons. Use a hex color. */
621
+ main: string;
622
+ };
623
+
530
624
  declare type TV1SerializedError = {
531
625
  cause?: TV1SerializedError;
532
626
  message: string;
@@ -876,6 +970,10 @@ declare type TV1StorageMethods = {
876
970
  };
877
971
 
878
972
  declare type TV1SystemMethods = {
973
+ 'v1.system.analytics.track': {
974
+ params: TV1AnalyticsTrackParams;
975
+ result: null;
976
+ };
879
977
  'v1.system.report.crash': {
880
978
  params: {
881
979
  data?: Record<string, unknown>;
@@ -1015,6 +1113,17 @@ declare type TV1TopUserEntry = {
1015
1113
 
1016
1114
  declare type TV1TopWindow = 'TOP_1D' | 'TOP_7D' | 'TOP_30D' | 'TOP_UNSPECIFIED';
1017
1115
 
1116
+ declare type TV1UiInteractionTrackParams = {
1117
+ data: {
1118
+ elementId: string;
1119
+ elementType: 'banner' | 'button' | 'tile' | 'popup' | 'extensionButton';
1120
+ interactionType: 'view' | 'click' | 'close' | 'dismiss';
1121
+ optionSelected?: string;
1122
+ pageSection?: string;
1123
+ };
1124
+ type: 'uiInteraction';
1125
+ };
1126
+
1018
1127
  /**
1019
1128
  * User activity league. Ordered from lowest to highest activity rank:
1020
1129
  * - `grey` — new or low-activity users (level 1–9)
package/dist/index.d.ts CHANGED
@@ -57,6 +57,7 @@ declare type TExtHelper = {
57
57
 
58
58
  declare type TExtHelperProps = {
59
59
  frameId: string;
60
+ lang: string;
60
61
  serverId: string;
61
62
  serverOrigin: string;
62
63
  serverSource: Window;
@@ -119,6 +120,8 @@ export declare type TV1ActionResult = {
119
120
  code: number;
120
121
  };
121
122
 
123
+ export declare type TV1AnalyticsTrackParams = TV1UiInteractionTrackParams;
124
+
122
125
  declare type TV1ChatEvents = {
123
126
  /** Triggered on every new message in a chat */
124
127
  'v1.chat.message.received': {
@@ -168,6 +171,20 @@ declare type TV1ChatMethods = {
168
171
  };
169
172
  result: null;
170
173
  };
174
+ /**
175
+ * Send a rich message to the chat with customizable colors.
176
+ *
177
+ * The message is sent locally on behalf of the extension. It is not sent to the server or broadcast — each user sees it only in their own local chat feed.
178
+ *
179
+ * Because the message is local, it is **not persisted**: it disappears from chat history when the page is reloaded.
180
+ *
181
+ * Required permission:
182
+ * - `richMessage`
183
+ */
184
+ 'v1.chat.richMessage.send': {
185
+ params: TV1RichMessage;
186
+ result: null;
187
+ };
171
188
  /** Use this method to send a message in the chat as a bot or model.
172
189
  * The message is sent locally to each user and looks like a normal chat message. The message is **not persisted** and will disappear from the chat after the page is reloaded.
173
190
  * */
@@ -306,6 +323,19 @@ declare type TV1ExtMethods = {
306
323
  params: null;
307
324
  result: TV1ExtContext;
308
325
  };
326
+ /**
327
+ * Returns the tag from which the user navigated to the model.
328
+ * `tag` is `null` when the source tag is unknown.
329
+ *
330
+ * Required permission:
331
+ * - `modelTag`
332
+ */
333
+ 'v1.ext.modelTag.get': {
334
+ params: null;
335
+ result: {
336
+ tag: TV1ExtModelTag | null;
337
+ };
338
+ };
309
339
  'v1.ext.movableOverlay.update': {
310
340
  params: {
311
341
  message?: string;
@@ -322,6 +352,8 @@ declare type TV1ExtMethods = {
322
352
  /** Opens Stripchat sign-up dialog for anonymous users. Use this when your extension requires a registered account to function */
323
353
  'v1.ext.signup.open': {
324
354
  params: {
355
+ /** Optional source string to identify the origin of the sign-up request. Internal use only */
356
+ source?: string;
325
357
  type: 'user';
326
358
  };
327
359
  result: null;
@@ -400,6 +432,21 @@ export declare type TV1ExtModel = {
400
432
  username: string;
401
433
  };
402
434
 
435
+ /**
436
+ * Tag from which the user navigated to the model.
437
+ *
438
+ * Required permission:
439
+ * - `modelTag`
440
+ */
441
+ export declare type TV1ExtModelTag = {
442
+ /** Tag identifier, for example `autoTagNew` */
443
+ id: string;
444
+ /** Primary tag the tag belongs to */
445
+ primaryTagId: 'girls' | 'men' | 'trans' | 'couples';
446
+ /** Tag URL path, for example `girls/new` */
447
+ url: string;
448
+ };
449
+
403
450
  export declare type TV1ExtSettings = unknown;
404
451
 
405
452
  export declare type TV1ExtUser = TV1ExtGuestUser | TV1ExtLoggedInUser;
@@ -580,6 +627,52 @@ declare type TV1PrivateMethods = {
580
627
  };
581
628
  };
582
629
 
630
+ export declare type TV1RichMessage = {
631
+ /** The main action appearance. It opens the extension tab on click. If omitted, the default action is a link. */
632
+ action?: {
633
+ text?: string;
634
+ type: 'link' | 'button';
635
+ };
636
+ /** One of the predefined extension icons. If omitted, the icon from the manifest is used. */
637
+ icon?: 'sex-toy-1' | 'sex-toy-2' | 'spicy-pepper';
638
+ /**
639
+ * Rich message subtitle.
640
+ *
641
+ * Supports inline markup tags:
642
+ * - `{#primary}...{/primary}` — uses the primary text color.
643
+ * - `{#secondary}...{/secondary}` — uses the secondary text color.
644
+ * - `{#accent}...{/accent}` — highlights text with an accent color.
645
+ * - `{#bold}...{/bold}` — renders bold text.
646
+ *
647
+ * Example: `'won {#accent}Alice{/accent} in'`
648
+ */
649
+ subtitle: string;
650
+ /** Optional custom theme. If omitted, the default theme is used. */
651
+ theme?: {
652
+ [Property in TTheme]?: TV1RichMessageTheme;
653
+ };
654
+ /**
655
+ * Rich message title.
656
+ *
657
+ * Supports inline markup tags:
658
+ * - `{#primary}...{/primary}` — uses the primary text color.
659
+ * - `{#secondary}...{/secondary}` — uses the secondary text color.
660
+ * - `{#accent}...{/accent}` — highlights text with an accent color.
661
+ * - `{#bold}...{/bold}` — renders bold text.
662
+ *
663
+ * Example: `'won {#accent}Alice{/accent} in'`
664
+ */
665
+ title: string;
666
+ };
667
+
668
+ export declare type TV1RichMessageTheme = {
669
+ /** Rich message background color. Use a hex color. */
670
+ background: string;
671
+ buttonText: 'white' | 'dark';
672
+ /** Main accent color of the rich message, used for the sidebar, highlights, links, and buttons. Use a hex color. */
673
+ main: string;
674
+ };
675
+
583
676
  declare type TV1SerializedError = {
584
677
  cause?: TV1SerializedError;
585
678
  message: string;
@@ -937,6 +1030,10 @@ export declare type TV1StorageStringSetError = TV1ExtensionError<TV1StorageStrin
937
1030
  export declare type TV1StorageStringSetErrorCode = 'ERR_CODE_UNSPECIFIED' | 'ERR_STORAGE_VALUE_SIZE_LIMIT_EXCEEDED';
938
1031
 
939
1032
  declare type TV1SystemMethods = {
1033
+ 'v1.system.analytics.track': {
1034
+ params: TV1AnalyticsTrackParams;
1035
+ result: null;
1036
+ };
940
1037
  'v1.system.report.crash': {
941
1038
  params: {
942
1039
  data?: Record<string, unknown>;
@@ -1076,6 +1173,17 @@ export declare type TV1TopUserEntry = {
1076
1173
 
1077
1174
  export declare type TV1TopWindow = 'TOP_1D' | 'TOP_7D' | 'TOP_30D' | 'TOP_UNSPECIFIED';
1078
1175
 
1176
+ export declare type TV1UiInteractionTrackParams = {
1177
+ data: {
1178
+ elementId: string;
1179
+ elementType: 'banner' | 'button' | 'tile' | 'popup' | 'extensionButton';
1180
+ interactionType: 'view' | 'click' | 'close' | 'dismiss';
1181
+ optionSelected?: string;
1182
+ pageSection?: string;
1183
+ };
1184
+ type: 'uiInteraction';
1185
+ };
1186
+
1079
1187
  /**
1080
1188
  * User activity league. Ordered from lowest to highest activity rank:
1081
1189
  * - `grey` — new or low-activity users (level 1–9)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stripchatdev/ext-helper",
3
3
  "private": false,
4
- "version": "0.3.0",
4
+ "version": "0.3.2",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "module": "./dist/ext-helper.js",