@stripchatdev/ext-helper 0.1.43 → 0.1.45

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.
@@ -0,0 +1,977 @@
1
+ declare type IV1IntIncrementFailureReason = 'INT_INCREMENT_FAILURE_REASON_UNSPECIFIED' | 'INT_INCREMENT_FAILURE_REASON_NONE' | 'INT_INCREMENT_FAILURE_REASON_VALIDATION_DENIED';
2
+
3
+ declare type TAnyApiEventData<D = unknown> = D;
4
+
5
+ declare type TAnyApiEventName = string;
6
+
7
+ declare type TAnyApiMethodMeta<P = unknown, R = unknown> = {
8
+ params: P;
9
+ result: R;
10
+ };
11
+
12
+ declare type TAnyApiMethodName = string;
13
+
14
+ declare type TAnyApiSchema<Events extends Record<TAnyApiEventName, TAnyApiEventData> = Record<TAnyApiEventName, TAnyApiEventData>, Methods extends Record<TAnyApiMethodName, TAnyApiMethodMeta> = Record<TAnyApiMethodName, TAnyApiMethodMeta>> = {
15
+ events: Events;
16
+ methods: Methods;
17
+ };
18
+
19
+ declare type TAnyPubSubHandler<D = unknown> = (data: D, peerId: TTransportPeer['id']) => void;
20
+
21
+ declare type TApiContract = TApiSchema;
22
+
23
+ declare type TApiSchema = TAnyApiSchema<TEvents, TMethods>;
24
+
25
+ /** Options for connecting a visual slot to shared background state. */
26
+ export declare type TCreateSlotStateClientProps = {
27
+ /** Shared name for the state. */
28
+ channel: string;
29
+ /** Extension helper used for slot communication. */
30
+ extHelper: TExtHelper;
31
+ };
32
+
33
+ declare type TEvents = TV1Events;
34
+
35
+ declare type TExtHelper = {
36
+ bootstrap(): void;
37
+ makeRequest<M extends Extract<keyof TApiContract['methods'], string>>(method: M, params: TApiContract['methods'][M]['params']): Promise<TApiContract['methods'][M]['result']>;
38
+ subscribe<E extends Extract<keyof TApiContract['events'], string>>(eventName: E, handler: TAnyPubSubHandler<TApiContract['events'][E]>): void;
39
+ unsubscribe<E extends Extract<keyof TApiContract['events'], string>>(eventName: E, handler?: TAnyPubSubHandler<TApiContract['events'][E]>): void;
40
+ };
41
+
42
+ /** Unique identifier for a guest user **/
43
+ declare type TGuestHash = string;
44
+
45
+ declare type TMethods = TV1Methods;
46
+
47
+ /**
48
+ * Status of the movable overlay.
49
+ * `active` - pulsing green
50
+ * `inactive` - orange
51
+ * `connecting` - green
52
+ * `error` - red
53
+ */
54
+ declare type TMovableOverlayStatus = 'active' | 'inactive' | 'connecting' | 'error';
55
+
56
+ declare type TTransportPeer = {
57
+ id: string;
58
+ };
59
+
60
+ declare type TUnknownDictionary = Record<string, unknown>;
61
+
62
+ declare type TUserId = number;
63
+
64
+ declare type TV1ActionParamValue = string | number | boolean | null | undefined | TV1ActionParamValue[] | {
65
+ [key: string]: TV1ActionParamValue;
66
+ };
67
+
68
+ declare type TV1ActionRequestParams = {
69
+ actionName: string;
70
+ params: Record<string, TV1ActionParamValue>;
71
+ };
72
+
73
+ declare type TV1ActionResult = {
74
+ body: unknown;
75
+ code: number;
76
+ };
77
+
78
+ declare type TV1ChatEvents = {
79
+ /** Triggered on every new message in a chat */
80
+ 'v1.chat.message.received': {
81
+ /** Text of the message */
82
+ messageText: string;
83
+ /** User who sent the message **/
84
+ sender: TV1ExtUser;
85
+ /** Whether message was sent in public or private chat **/
86
+ type: 'private' | 'public';
87
+ };
88
+ };
89
+
90
+ declare type TV1ChatMethods = {
91
+ /**
92
+ * This method should be used to notify a user in the chat about an event related to the extension, for example, showing the result of a game. Therefore, it should be used only after `v1.payment.tokens.spend.succeeded` event.
93
+ *
94
+ * The message is sent locally to each user on behalf of the extension. The message is not sent to the server
95
+ * and is not broadcasted — each user sees it injected into their own local chat feed.
96
+ *
97
+ * Because the message is local only, it is **not persisted**: it will disappear from the chat
98
+ * history after the page is reloaded.
99
+ *
100
+ * **Note:** A clickable link to the extension is always appended at the end of every message sent via this method.
101
+ * Clicking it opens the extension that sent the message.
102
+ * This behavior is mandatory and cannot be disabled.
103
+ */
104
+ 'v1.chat.message.send': {
105
+ params: {
106
+ /** Whether the username should be hidden. Always respect user's anonimity and use data received in `v1.payment.tokens.spend.succeeded'. */
107
+ isAnonymous: boolean;
108
+ /**
109
+ * Chat message text.
110
+ *
111
+ * Supports inline markup tags:
112
+ * - `{#accent}…{/accent}` — highlights text with an accent color.
113
+ * - `{#fade}…{/fade}` — renders text in a dimmed/secondary style.
114
+ *
115
+ * Example: `'won {#accent}Alice{/accent} in'`
116
+ */
117
+ message: string;
118
+ user: TV1ExtUser | null;
119
+ };
120
+ result: null;
121
+ };
122
+ /** Use this method to send a message in the chat as a bot or model.
123
+ * 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.
124
+ * */
125
+ 'v1.chatbot.message.send': {
126
+ params: {
127
+ /** Sender of the message.
128
+ * If `bot`, the message will be sent with the name of the extension
129
+ * If `model`, the message will be sent with the name of the current model
130
+ * */
131
+ from: 'bot' | 'model';
132
+ /** Text of the message.
133
+ *
134
+ *
135
+ * The message can contain {username} placeholder, which will be replaced with the name of the user receiving the message.
136
+ * If the user is anonymous, the placeholder will be replaced with empty string.
137
+ * If the user is guest, the placeholder will be replaced with "Guest".
138
+ *
139
+ * Example usage: "Hello, {username}! Welcome to the chat!"
140
+ * */
141
+ message: string;
142
+ };
143
+ result: null;
144
+ };
145
+ };
146
+
147
+ declare type TV1Events = TV1ExtEvents & TV1PaymentEvents & TV1ModelEvents & TV1SessionEvents & TV1TipEvents & TV1ChatEvents & TV1GoalEvents;
148
+
149
+ declare type TV1ExtContext = {
150
+ model?: TV1ExtModel;
151
+ /** Unique identifier for the extension. */
152
+ slug?: string;
153
+ user?: TV1ExtUser;
154
+ };
155
+
156
+ declare type TV1ExtEvents = {
157
+ 'v1.ext.activity.available': null;
158
+ 'v1.ext.activity.busy': null;
159
+ 'v1.ext.context.updated': {
160
+ context: TV1ExtContext;
161
+ };
162
+ /**
163
+ * Fired whenever the viewer counts for the room change.
164
+ * Emitted only for show types: `public`, `groupShow`, `ticketShow`.
165
+ */
166
+ 'v1.ext.viewers.updated': {
167
+ viewers: TV1ExtViewers;
168
+ };
169
+ 'v1.ext.whispered': TV1WhisperData;
170
+ 'v1.ext.whispered.local': TV1WhisperData;
171
+ };
172
+
173
+ /** Guest user (not logged in). */
174
+ declare type TV1ExtGuestUser = {
175
+ /** Unique identifier for a guest user. */
176
+ guestHash: TGuestHash;
177
+ /** User is a guest (not logged in). */
178
+ isGuest: true;
179
+ };
180
+
181
+ /** Logged-in user. */
182
+ declare type TV1ExtLoggedInUser = {
183
+ /** User's fan club data. Contains information regarding user's subscription to the model's fan club. */
184
+ fanClub: TV1UsersFanClub;
185
+ /** User previously purchased tokens. */
186
+ hasPaidBefore: boolean;
187
+ /** User has tokens. */
188
+ hasTokens: boolean;
189
+ /** User currently has Ultimate membership. */
190
+ hasUltimateSubscription: boolean;
191
+ /** User ID. */
192
+ id: TUserId;
193
+ /** User is logged in. */
194
+ isGuest: false;
195
+ /** User is invisible. Do not expose any data of invisible users. */
196
+ isInvisible: boolean;
197
+ /** User is the highest tipper in the room over past 12 hours. */
198
+ isKing: boolean;
199
+ /** User is a knight of the model. */
200
+ isKnight: boolean;
201
+ /**
202
+ * User has a model account.
203
+ *
204
+ * This can be true for another model visiting the stream. To check whether the
205
+ * current user is the broadcaster, compare `context.user.id`
206
+ * and `context.model.id`.
207
+ */
208
+ isModel: boolean;
209
+ /**
210
+ * Current show/session state for this user.
211
+ *
212
+ * - `public` — public broadcast context
213
+ * - `private` — private show context
214
+ * - `exclusivePrivate` — exclusive private show context
215
+ * - `groupShow` — group show context
216
+ * - `ticketShow` — ticket show context
217
+ * - `off` — offline
218
+ * - `spy` — spying on a private show
219
+ */
220
+ status: TV1UserStatus;
221
+ /** User username. */
222
+ username: string;
223
+ /** User activity ranking data when available. */
224
+ userRanking?: TV1UserRanking;
225
+ };
226
+
227
+ declare type TV1ExtMethods = {
228
+ 'v1.ext.actions.call': {
229
+ params: TV1ActionRequestParams;
230
+ result: TV1ActionResult;
231
+ };
232
+ 'v1.ext.activity.request': {
233
+ params: {
234
+ durationMs: number;
235
+ };
236
+ result: {
237
+ activityId: string;
238
+ };
239
+ };
240
+ 'v1.ext.activity.status': {
241
+ params: null;
242
+ result: {
243
+ status: 'available' | 'busy';
244
+ };
245
+ };
246
+ 'v1.ext.context.get': {
247
+ params: null;
248
+ result: TV1ExtContext;
249
+ };
250
+ 'v1.ext.movableOverlay.update': {
251
+ params: {
252
+ message?: string;
253
+ status?: TMovableOverlayStatus;
254
+ };
255
+ result: null;
256
+ };
257
+ 'v1.ext.settings.get': {
258
+ params: null;
259
+ result: {
260
+ settings: TV1ExtSettings;
261
+ };
262
+ };
263
+ /** Opens Stripchat sign-up dialog for anonymous users. Use this when your extension requires a registered account to function */
264
+ 'v1.ext.signup.open': {
265
+ params: {
266
+ type: 'user';
267
+ };
268
+ result: null;
269
+ };
270
+ /**
271
+ * Returns the current viewer counts for the room.
272
+ * Supported only for show types: `public`, `groupShow`, `ticketShow`.
273
+ * Returns `null` for other show types.
274
+ */
275
+ 'v1.ext.viewers.get': {
276
+ params: null;
277
+ result: TV1ExtViewers | null;
278
+ };
279
+ /** Broadcasts a message through the server to all clients in the room that have this extension loaded. Every slot iframe of every user receives the corresponding `v1.ext.whispered` event */
280
+ 'v1.ext.whisper': {
281
+ params: {
282
+ /** Any JSON-serializable object to send to every frame.
283
+ * Never send any sensetive data through this field, such as username or user id.
284
+ * */
285
+ data: TV1WhisperData;
286
+ /** @deprecated
287
+ * Use `paymentHash` instead
288
+ *
289
+ * Payment data returned by the `payment.tokens.spend.succeeded` event.
290
+ * Required for users in public shows. Use it only once for the request it authorizes. Do not store or reuse it.
291
+ * */
292
+ paymentData?: TV1PaymentData;
293
+ /** Payment hash returned by the `payment.tokens.spend.succeeded` event.
294
+ * Payment hash is used for authentication. Required for users in public shows. Use it only once for the request it authorizes. Do not store or reuse it.
295
+ * */
296
+ paymentHash?: TV1PaymentHash;
297
+ };
298
+ result: null;
299
+ };
300
+ /** Sends a message to every frame of the current user */
301
+ 'v1.ext.whisper.local': {
302
+ params: {
303
+ data: TV1WhisperData;
304
+ };
305
+ result: null;
306
+ };
307
+ };
308
+
309
+ declare type TV1ExtModel = {
310
+ /** Model's avatar url */
311
+ avatarUrlThumb: string;
312
+ /** @deprecated use isExclusivePrivateEnabled instead. This property will be removed soon */
313
+ doP2p: boolean;
314
+ /** @deprecated use isPrivateEnabled instead. This property will be removed soon */
315
+ doPrivate: boolean;
316
+ /** Broadcasting gender. Could be one of the male, female, tranny or group */
317
+ gender: TV1Genders;
318
+ id: TUserId;
319
+ /** Is exclusive private mode enabled on the stream */
320
+ isExclusivePrivateEnabled: boolean;
321
+ /** Is non nude model */
322
+ isNonNude: boolean;
323
+ /** Is private mode enabled on the stream */
324
+ isPrivateEnabled: boolean;
325
+ /** Is spy mode enabled on the stream */
326
+ isSpyEnabled: boolean;
327
+ /** Model's name from her profile. If not set, an empty string will be returned */
328
+ name: string;
329
+ /** Status of the show. Possible values:
330
+ *
331
+ * - `idle` - model is online but not streaming
332
+ * - `public` - model is broadcasting public show
333
+ * - `private` - model is in private show
334
+ * - `exclusivePrivate` - model is in exclusive private show
335
+ * - `off` - model is offline
336
+ * - `groupShow` - model is in group show that is not a ticket show
337
+ * - `ticketShow` - model is in ticket show
338
+ * */
339
+ status: TV1ModelStatus;
340
+ /** Model's username */
341
+ username: string;
342
+ };
343
+
344
+ declare type TV1ExtSettings = unknown;
345
+
346
+ declare type TV1ExtUser = TV1ExtGuestUser | TV1ExtLoggedInUser;
347
+
348
+ /** Viewer counts for the current room. */
349
+ declare type TV1ExtViewers = {
350
+ /** Number of guest (unauthenticated) viewers. */
351
+ guests: number;
352
+ /** Total number of viewers in the room. */
353
+ total: number;
354
+ /** Number of viewers who hold tokens. */
355
+ withTokens: number;
356
+ };
357
+
358
+ declare type TV1FanClubMethods = {
359
+ /**
360
+ * Opens the fan club subscription modal for the current model.
361
+ * Read `context.user.fanClub` from the extension context to verify the user is eligible before calling.
362
+ * This field is available only for logged-in users (`context.user.isGuest === false`).
363
+ * Pass `null` for params to open the modal with the `soldier` tab selected by default.
364
+ */
365
+ 'v1.fanClub.request': {
366
+ params: {
367
+ /** Which tier tab to show in the modal. */
368
+ tier: TV1FanClubTier;
369
+ } | null;
370
+ result: null;
371
+ };
372
+ };
373
+
374
+ /**
375
+ * Fan club subscription tier. Ordered from lowest to highest:
376
+ * - `soldier` — first tier with basic benefits
377
+ * - `lord` — second tier with more benefits than `soldier`
378
+ * - `prince` — third tier with the most benefits
379
+ */
380
+ declare type TV1FanClubTier = 'soldier' | 'lord' | 'prince';
381
+
382
+ declare type TV1Genders = 'male' | 'female' | 'group' | 'tranny';
383
+
384
+ /** Regular goal data */
385
+ declare type TV1GoalData = {
386
+ /** Goal description */
387
+ description: string;
388
+ /** Whether the goal is fully completed */
389
+ isCompleted: boolean;
390
+ /** Amount of tokens already collected */
391
+ tokensCollected: number;
392
+ /** Target amount in tokens */
393
+ tokensTarget: number;
394
+ };
395
+
396
+ declare type TV1GoalEvents = {
397
+ /** Fired when any field of the active goal changes (description, isCompleted, tokensTarget, or tokensCollected), or the active goal is removed. */
398
+ 'v1.goal.updated': {
399
+ goal: TV1GoalData | null;
400
+ };
401
+ };
402
+
403
+ declare type TV1GoalMethods = {
404
+ /** Get the current active goal. Returns null if no goal is active. */
405
+ 'v1.goal.get': {
406
+ params: null;
407
+ result: {
408
+ goal: TV1GoalData | null;
409
+ };
410
+ };
411
+ };
412
+
413
+ declare type TV1Methods = TV1ExtMethods & TV1SystemMethods & TV1PaymentMethods & TV1ModelMethods & TV1ChatMethods & TV1PrivateMethods & TV1MonitoringMethods & TV1SessionMethods & TV1StorageMethods & TV1TipMethods & TV1GoalMethods & TV1FanClubMethods;
414
+
415
+ declare type TV1ModelEvents = {
416
+ 'v1.model.ext.settings.set.requested': null;
417
+ };
418
+
419
+ declare type TV1ModelMethods = {
420
+ 'v1.model.ext.settings.get': {
421
+ params: null;
422
+ result: {
423
+ settings: TV1ExtSettings;
424
+ };
425
+ };
426
+ 'v1.model.ext.settings.set': {
427
+ params: {
428
+ isError: boolean;
429
+ settings: TV1ExtSettings;
430
+ };
431
+ result: null;
432
+ };
433
+ };
434
+
435
+ declare type TV1ModelStatus = Exclude<(typeof V1_SHOW_STATUSES)[keyof typeof V1_SHOW_STATUSES], 'spy'>;
436
+
437
+ declare type TV1MonitoringMethods = {
438
+ 'v1.monitoring.report.error': {
439
+ params: {
440
+ data: unknown;
441
+ message: string;
442
+ };
443
+ result: null;
444
+ };
445
+ 'v1.monitoring.report.log': {
446
+ params: {
447
+ data: unknown;
448
+ message: string;
449
+ };
450
+ result: null;
451
+ };
452
+ };
453
+
454
+ /** Payment data returned after a successful token spend. Use it only once for the request it authorizes. Do not store or reuse it. */
455
+ declare type TV1PaymentData = {
456
+ /** The amount of tokens spent */
457
+ amount: string;
458
+ /** Payment token used for authentication */
459
+ paymentToken: string;
460
+ /** Transaction identifier */
461
+ transactionId: string;
462
+ /** User's ID */
463
+ userId: string;
464
+ };
465
+
466
+ declare type TV1PaymentEvents = {
467
+ /**
468
+ * Received when tokens are successfully spent
469
+ * Contains payment data returned after a successful token spend. Use it only once for the request it authorizes. Do not store or reuse it.
470
+ */
471
+ 'v1.payment.tokens.spend.succeeded': {
472
+ /** Was the tip anonymous. Use this field in `v1.chat.message.send` */
473
+ isAnonymous: boolean;
474
+ /** @deprecated
475
+ * Use `paymentHash` instead.
476
+ *
477
+ * Payment data returned after a successful token spend. Use it only once for the request it authorizes. Do not store or reuse it. */
478
+ paymentData: TV1PaymentData;
479
+ /**
480
+ * Payment hash used for authentication. Required for users in public shows. Use it only once for the request it authorizes. Do not store or reuse it.
481
+ */
482
+ paymentHash: TV1PaymentHash;
483
+ /** Custom data passed in `payment.tokens.spend` method */
484
+ tokensSpendData: TV1TokenSpendData;
485
+ };
486
+ };
487
+
488
+ /** Payment hash used for authentication. Do not store or reuse it. Use it only once for the request it authorizes. */
489
+ declare type TV1PaymentHash = string;
490
+
491
+ declare type TV1PaymentMethods = {
492
+ /** Requests a confirmation modal to spend tokens */
493
+ 'v1.payment.tokens.spend': {
494
+ params: {
495
+ /** Amount of tokens to spend */
496
+ tokensAmount: number;
497
+ /** Custom data which will be passed back in the `v1.payment.tokens.spend.succeeded` event */
498
+ tokensSpendData: TV1TokenSpendData;
499
+ };
500
+ result: null;
501
+ };
502
+ /** Opens the token top-up (purchase) modal directly, sending the user straight to buying tokens — without
503
+ * the spend-confirmation step of `v1.payment.tokens.spend`. Use it for an explicit "Buy tokens" CTA. */
504
+ 'v1.payment.tokens.topup': {
505
+ params: null;
506
+ result: null;
507
+ };
508
+ };
509
+
510
+ declare type TV1PrivateMethods = {
511
+ 'v1.private.request': {
512
+ params: null;
513
+ result: null;
514
+ };
515
+ };
516
+
517
+ declare type TV1SerializedError = {
518
+ cause?: TV1SerializedError;
519
+ message: string;
520
+ name: string;
521
+ stack?: string;
522
+ };
523
+
524
+ declare type TV1Session = TV1SessionSelf | TV1SessionOther;
525
+
526
+ declare type TV1SessionActionType = 'join' | 'finish';
527
+
528
+ declare type TV1SessionEvents = {
529
+ 'v1.session.updated': {
530
+ data: TV1SessionUpdate;
531
+ };
532
+ 'v1.session.whispered.model': TV1SessionWhisperData;
533
+ };
534
+
535
+ declare type TV1SessionMethods = {
536
+ 'v1.session.finish.model': {
537
+ params: null;
538
+ result: null;
539
+ };
540
+ 'v1.session.get': {
541
+ params: null;
542
+ result: {
543
+ session: TV1Session | null;
544
+ };
545
+ };
546
+ 'v1.session.join.model': {
547
+ params: {
548
+ ttl: string;
549
+ };
550
+ result: null;
551
+ };
552
+ 'v1.session.join.user': {
553
+ params: {
554
+ /** @deprecated
555
+ * Use `paymentHash` instead.
556
+ *
557
+ * Payment data returned by the `payment.tokens.spend.succeeded` event. Use it only once for the request it authorizes. Do not store or reuse it. */
558
+ payment?: TV1PaymentData;
559
+ /**
560
+ * Payment hash returned by the `payment.tokens.spend.succeeded` event.
561
+ * Use it only once for the request it authorizes. Do not store or reuse it.
562
+ */
563
+ paymentHash: TV1PaymentHash;
564
+ /** Session lifetime in seconds (minimum 1). */
565
+ ttl: string;
566
+ };
567
+ result: null;
568
+ };
569
+ 'v1.session.whisper.user': {
570
+ params: {
571
+ data: TV1SessionWhisperData;
572
+ };
573
+ result: null;
574
+ };
575
+ };
576
+
577
+ declare type TV1SessionOther = {
578
+ /** The session exists but belongs to a different extension */
579
+ owner: 'other';
580
+ };
581
+
582
+ declare type TV1SessionSelf = {
583
+ meta: {
584
+ /** Platform session id */
585
+ sessionId: string;
586
+ /** Remaining lifetime in seconds */
587
+ ttlSec: number;
588
+ };
589
+ /** The session exists and belongs to this extension */
590
+ owner: 'self';
591
+ };
592
+
593
+ declare type TV1SessionUpdate = {
594
+ action: TV1SessionActionType;
595
+ session: TV1Session | null;
596
+ userId: TUserId;
597
+ };
598
+
599
+ declare type TV1SessionWhisperData = TUnknownDictionary;
600
+
601
+ declare type TV1StorageMethods = {
602
+ 'v1.storage.int.get': {
603
+ params: {
604
+ key: string;
605
+ };
606
+ result: {
607
+ /** `false` when the key has never been set (value will be 0). */
608
+ exists?: boolean;
609
+ /** @format int64 */
610
+ value: string;
611
+ };
612
+ };
613
+ /**
614
+ * Add `delta` to an integer counter. Negative delta subtracts.
615
+ * When the key is configured with a payment policy, pass `paymentContext`
616
+ * so the server can validate the transaction before applying the change.
617
+ */
618
+ 'v1.storage.int.increment': {
619
+ params: {
620
+ /** Amount to add (may be negative). Must not be zero. */
621
+ delta: string;
622
+ key: string;
623
+ /** Opaque payload forwarded to server-side payment/policy validation. */
624
+ paymentContext?: string;
625
+ };
626
+ result: {
627
+ failureReason?: IV1IntIncrementFailureReason;
628
+ /** New counter value after the increment (present when `success` is true). */
629
+ success: boolean;
630
+ value?: string;
631
+ };
632
+ };
633
+ /** Reset an integer counter to 0. */
634
+ 'v1.storage.int.reset': {
635
+ params: {
636
+ key: string;
637
+ };
638
+ result: {
639
+ success: boolean;
640
+ /** Stored value after reset; always 0 when `success` is true. */
641
+ value?: string;
642
+ };
643
+ };
644
+ 'v1.storage.mutex.getState': {
645
+ params: {
646
+ mutexName: string;
647
+ };
648
+ result: {
649
+ /** `true` if the mutex is currently locked. */
650
+ held: boolean;
651
+ };
652
+ };
653
+ 'v1.storage.mutex.lock': {
654
+ params: {
655
+ mutexName: string;
656
+ /** Auto-release after this many seconds. Omit or 0 = hold until explicit unlock. */
657
+ /** @format int64 */
658
+ ttl?: string;
659
+ };
660
+ result: {
661
+ success: boolean;
662
+ };
663
+ };
664
+ 'v1.storage.mutex.unlock': {
665
+ params: {
666
+ mutexName: string;
667
+ };
668
+ result: {
669
+ success: boolean;
670
+ };
671
+ };
672
+ 'v1.storage.string.append': {
673
+ params: {
674
+ key: string;
675
+ /** Auto-delete the key after this many seconds. Omit or 0 = no expiry. */
676
+ /** @format int64 */
677
+ ttl?: string;
678
+ value: string;
679
+ };
680
+ result: {
681
+ success: boolean;
682
+ };
683
+ };
684
+ 'v1.storage.string.get': {
685
+ params: {
686
+ /**
687
+ * When `true`, read the single extension-wide value shared across every room and viewer
688
+ * instead of the value scoped to the current room and viewer. Use for shared data seeded
689
+ * on the server. Defaults to `false` (per-room read).
690
+ */
691
+ all?: boolean;
692
+ key: string;
693
+ };
694
+ result: {
695
+ /** `false` when the key has never been set (value will be `''` empty string). */
696
+ exists: boolean;
697
+ /**
698
+ * Server time (UTC, RFC3339) at which the response was generated. Use this instead of the device
699
+ * clock for time-window logic — a skewed local clock won't desync the extension. Optional so a host
700
+ * that doesn't yet surface it still validates (newer hosts always include it).
701
+ */
702
+ time?: string;
703
+ /** Stored string value. Empty string if the key was never set. */
704
+ value: string;
705
+ };
706
+ };
707
+ 'v1.storage.string.set': {
708
+ params: {
709
+ key: string;
710
+ /** Auto-delete the key after this many seconds. Omit or 0 = no expiry. */
711
+ /** @format int64 */
712
+ ttl?: string;
713
+ value: string;
714
+ };
715
+ result: {
716
+ success: boolean;
717
+ };
718
+ };
719
+ /**
720
+ * Read a top counter: total sum in the window, last incrementer,
721
+ * top-N users by total, and per-day breakdown.
722
+ */
723
+ 'v1.storage.top.get': {
724
+ params: {
725
+ key: string;
726
+ /** Sliding time horizon for summing increments. */
727
+ top: TV1TopWindow;
728
+ /** How many users to return in `topUsers`. 0 = default 10; max 100. */
729
+ topN?: number;
730
+ };
731
+ result: {
732
+ topUsers?: TV1TopUserEntry[];
733
+ };
734
+ };
735
+ /** Append an increment to a top counter for the current model session. */
736
+ 'v1.storage.top.increment': {
737
+ params: {
738
+ /**
739
+ * Positive amount to add.
740
+ * @format int64
741
+ */
742
+ amount: string;
743
+ key: string;
744
+ /** An optional string saved for this increment from that user's latest event. */
745
+ meta?: string;
746
+ /**
747
+ * User id credited for this increment (appears in `top/get` top_users).
748
+ * @format int64
749
+ */
750
+ userId: string;
751
+ };
752
+ result: {
753
+ /** An optional string saved for this increment from that user's latest event. */
754
+ meta?: string;
755
+ success: boolean;
756
+ /** Echo of request `userId`; `windowStats` apply to this user. */
757
+ /** @format int64 */
758
+ userId?: string;
759
+ /** One entry per standard horizon (1d, 7d, 30d) with that user's total in each window after the increment. */
760
+ windowStats?: TV1TopIncrementWindowStat[];
761
+ };
762
+ };
763
+ /** Clear all increments for a top counter key. */
764
+ 'v1.storage.top.reset': {
765
+ params: {
766
+ key: string;
767
+ };
768
+ result: {
769
+ success: boolean;
770
+ };
771
+ };
772
+ };
773
+
774
+ declare type TV1SystemMethods = {
775
+ 'v1.system.report.crash': {
776
+ params: {
777
+ data?: Record<string, unknown>;
778
+ error?: TV1SerializedError;
779
+ kind: string;
780
+ type: 'network' | 'runtime';
781
+ };
782
+ result: null;
783
+ };
784
+ 'v1.system.resize.notify': {
785
+ params: {
786
+ height: number;
787
+ width: number;
788
+ };
789
+ result: null;
790
+ };
791
+ };
792
+
793
+ /** Tokens spend tip data */
794
+ declare type TV1TipData = {
795
+ /** Amount of tokens spent */
796
+ amount: number;
797
+ /** Tip id */
798
+ id: string;
799
+ /** Is anonymous tip or not */
800
+ isAnonymous: boolean;
801
+ /** Is tip sent from the current user or not */
802
+ isFromTheCurrentUser: boolean;
803
+ /** Is tip sent from the current extension or not */
804
+ isOriginalSource: boolean;
805
+ /** Message that was sent with the tip. Empty string if no message was sent */
806
+ message?: string;
807
+ /** Source of the tip. Could be one of the following:
808
+ *
809
+ * `console` - tip was sent using / command
810
+ * `tipMenu` - tip was sent using tip menu
811
+ * `goal` - tip was sent via goal button
812
+ * `epicGoal` - tip was sent to epic goal
813
+ * `fullscreen` - tip was sent from the fullscreen view
814
+ * `interactiveToy` - tip was sent from the interactive toy
815
+ * `privateChat` - tip was sent from the private chat, in any type of show
816
+ * `publicChat` - tip was sent using publich chat, either in public or group show.
817
+ * `extension` - tip was sent from one of the extensions
818
+ * `sendTipButton` - tip was sent using send tip button
819
+ * `feed` - tip was sent from the feed
820
+ * */
821
+ source: TV1TipSource;
822
+ /** Message visibility: `public` — visible to everyone in the room; `private` — visible only to the model. */
823
+ type: 'private' | 'public';
824
+ /** User who sent the tip. Can be null in case of anonymous tip */
825
+ user?: TV1ExtUser | null;
826
+ };
827
+
828
+ declare type TV1TipEvents = {
829
+ /** Fired when the tip menu has been updated.*/
830
+ 'v1.tipMenu.updated': {
831
+ /** The current tip menu data. */
832
+ tipMenu: TV1TipMenu;
833
+ };
834
+ /** Fired on every tip in chat for both model and user. Doesn't fire on private tips during public shows */
835
+ 'v1.tokens.spent': {
836
+ tipData: TV1TipData;
837
+ };
838
+ };
839
+
840
+ /** Tip menu data */
841
+ declare type TV1TipMenu = {
842
+ /** Whether tip menu is enabled or not. If it's disabled, the `items` array will be empty. */
843
+ isEnabled: boolean;
844
+ /** The list of tip menu items sorted by the model. */
845
+ items: TV1TipMenuItem[];
846
+ };
847
+
848
+ /** Tip menu item defined by the model. */
849
+ declare type TV1TipMenuItem = {
850
+ /** Activity name */
851
+ activity: string;
852
+ /** Price of the activity for the current user applying all discounts.
853
+ * Discounts can be applied based on the user's fan club memberhip.
854
+ * */
855
+ price: number;
856
+ };
857
+
858
+ declare type TV1TipMethods = {
859
+ /** Get the current tip menu. Tip menu data might change during the broadcast, so subscribe to `v1.tipMenu.updated` to listen to these changes. */
860
+ 'v1.tipMenu.get': {
861
+ params: null;
862
+ result: {
863
+ /** The current tip menu data. */
864
+ tipMenu: TV1TipMenu;
865
+ };
866
+ };
867
+ };
868
+
869
+ /** Source of the tip. Could be one of the following:
870
+ *
871
+ * `console` - tip was sent using / command
872
+ * `tipMenu` - tip was sent using tip menu
873
+ * `goal` - tip was sent via goal button
874
+ * `epicGoal` - tip was sent to epic goal
875
+ * `fullscreen` - tip was sent from the fullscreen view
876
+ * `interactiveToy` - tip was sent from the interactive toy
877
+ * `privateChat` - tip was sent from the private chat, in any type of show
878
+ * `publicChat` - tip was sent using publich chat, either in public or group show.
879
+ * `extension` - tip was sent from one of the extensions
880
+ * `sendTipButton` - tip was sent using send tip button
881
+ * `feed` - tip was sent from the feed
882
+ */
883
+ declare type TV1TipSource = 'console' | 'tipMenu' | 'goal' | 'epicGoal' | 'fullscreen' | 'interactiveToy' | 'publicChat' | 'privateChat' | 'extension' | 'sendTipButton' | 'feed';
884
+
885
+ /** Custom data that you can pass when requesting token spend. You will receive it on successful payment */
886
+ declare type TV1TokenSpendData = TUnknownDictionary;
887
+
888
+ /**
889
+ * Per-window statistics for a user after a top counter increment.
890
+ * One entry per standard horizon (1d, 7d, 30d).
891
+ */
892
+ declare type TV1TopIncrementWindowStat = {
893
+ /** User's summed total within this window after the increment. */
894
+ value: string;
895
+ /** Sliding time horizon (1d, 7d, or 30d). */
896
+ window: TV1TopWindow;
897
+ };
898
+
899
+ declare type TV1TopUserEntry = {
900
+ /** An optional string saved for this increment from that user's latest event */
901
+ meta?: string;
902
+ /** Sum of increment amounts within the sliding window for this user. */
903
+ total: string;
904
+ /** User ID recorded as incrementer. */
905
+ userId: string;
906
+ };
907
+
908
+ declare type TV1TopWindow = 'TOP_1D' | 'TOP_7D' | 'TOP_30D' | 'TOP_UNSPECIFIED';
909
+
910
+ /**
911
+ * User activity league. Ordered from lowest to highest activity rank:
912
+ * - `grey` — new or low-activity users (level 1–9)
913
+ * - `bronze` — early active users (level 10–19)
914
+ * - `silver` — regularly active users (level 20–34)
915
+ * - `gold` — highly active users (level 35–54)
916
+ * - `diamond` — very highly active users (level 55–79)
917
+ * - `royal` — elite activity users (level 80–99)
918
+ * - `legend` — top activity users (level 100)
919
+ */
920
+ declare type TV1UserLeague = 'grey' | 'bronze' | 'silver' | 'gold' | 'diamond' | 'royal' | 'legend';
921
+
922
+ /** User activity ranking system */
923
+ declare type TV1UserRanking = {
924
+ /** League representation of the user's activity level. Could be `grey`, `bronze`, `silver`, `gold`, `diamond`, `royal` or `legend`. */
925
+ league: TV1UserLeague;
926
+ /** Activity level from 1 to 100. */
927
+ level: number;
928
+ };
929
+
930
+ declare type TV1UsersFanClub = TV1UsersFanClubSubscribed | TV1UsersFanClubNotSubscribed;
931
+
932
+ declare type TV1UsersFanClubNotSubscribed = {
933
+ /** Whether user is subscribed to the model's fan club or not */
934
+ isSubscribed: false;
935
+ };
936
+
937
+ declare type TV1UsersFanClubSubscribed = {
938
+ /** Whether user is subscribed to the model's fan club or not */
939
+ isSubscribed: true;
940
+ /** The tier of the fan club subscription. Could be `soldier`, `lord` or `prince`. Higher tiers provide more benefits. */
941
+ tier: TV1FanClubTier;
942
+ };
943
+
944
+ declare type TV1UserStatus = Exclude<(typeof V1_SHOW_STATUSES)[keyof typeof V1_SHOW_STATUSES], 'idle'>;
945
+
946
+ declare type TV1WhisperData = TUnknownDictionary;
947
+
948
+ /**
949
+ * React hook for shared state owned by a background slot.
950
+ *
951
+ * Use the same `channel` as `createSlotStateHost`. The returned `state` is
952
+ * `null` until the initial state is available. Call `setState()` with a shallow
953
+ * partial update; the returned state reflects the background slot's state.
954
+ *
955
+ * @typeParam State - Shape of the shared state.
956
+ * @param channel - Shared state name.
957
+ * @param extHelper - Extension helper used for slot communication.
958
+ * @returns The current state, loading status, and `setState` function.
959
+ */
960
+ export declare const useSlotState: <State extends object>({ channel, extHelper, }: TCreateSlotStateClientProps) => {
961
+ isLoading: boolean;
962
+ setState: (newState: Partial<State>) => Promise<void>;
963
+ state: State | null;
964
+ };
965
+
966
+ declare const V1_SHOW_STATUSES: {
967
+ readonly STATUS_TICKET_SHOW: "ticketShow";
968
+ readonly STATUS_GROUP_SHOW: "groupShow";
969
+ readonly STATUS_OFF: "off";
970
+ readonly STATUS_PRIVATE: "private";
971
+ readonly STATUS_EXCLUSIVE_PRIVATE: "exclusivePrivate";
972
+ readonly STATUS_PUBLIC: "public";
973
+ readonly STATUS_IDLE: "idle";
974
+ readonly STATUS_SPY: "spy";
975
+ };
976
+
977
+ export { }