vantiv.io 1.0.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +864 -0
  3. package/index.js +13 -0
  4. package/package.json +28 -0
  5. package/src/classes/Actions/Awaiter.js +202 -0
  6. package/src/classes/Actions/Channel.js +73 -0
  7. package/src/classes/Actions/Direct.js +263 -0
  8. package/src/classes/Actions/Inventory.js +156 -0
  9. package/src/classes/Actions/Music.js +278 -0
  10. package/src/classes/Actions/Player.js +377 -0
  11. package/src/classes/Actions/Public.js +66 -0
  12. package/src/classes/Actions/Room.js +333 -0
  13. package/src/classes/Actions/Utils.js +29 -0
  14. package/src/classes/Actions/lib/AudioStreaming.js +447 -0
  15. package/src/classes/Caches/MovementCache.js +357 -0
  16. package/src/classes/Handlers/AxiosErrorHandler.js +68 -0
  17. package/src/classes/Handlers/ErrorHandler.js +65 -0
  18. package/src/classes/Handlers/EventHandlers.js +259 -0
  19. package/src/classes/Handlers/WebSocketHandlers.js +54 -0
  20. package/src/classes/Managers/ChannelManager.js +303 -0
  21. package/src/classes/Managers/DanceFloorManagers.js +509 -0
  22. package/src/classes/Managers/Helpers/CleanupManager.js +130 -0
  23. package/src/classes/Managers/Helpers/LoggerManager.js +171 -0
  24. package/src/classes/Managers/Helpers/MetricsManager.js +83 -0
  25. package/src/classes/Managers/Networking/ConnectionManager.js +259 -0
  26. package/src/classes/Managers/Networking/CooldownManager.js +516 -0
  27. package/src/classes/Managers/Networking/EventsManager.js +64 -0
  28. package/src/classes/Managers/Networking/KeepAliveManager.js +109 -0
  29. package/src/classes/Managers/Networking/MessageHandler.js +110 -0
  30. package/src/classes/Managers/Networking/Request.js +329 -0
  31. package/src/classes/Managers/PermissionManager.js +288 -0
  32. package/src/classes/WebApi/Category/Grab.js +98 -0
  33. package/src/classes/WebApi/Category/Item.js +347 -0
  34. package/src/classes/WebApi/Category/Post.js +154 -0
  35. package/src/classes/WebApi/Category/Room.js +137 -0
  36. package/src/classes/WebApi/Category/User.js +88 -0
  37. package/src/classes/WebApi/webapi.js +52 -0
  38. package/src/constants/TypesConstants.js +89 -0
  39. package/src/constants/WebSocketConstants.js +80 -0
  40. package/src/core/Highrise.js +123 -0
  41. package/src/core/HighriseWebsocket.js +228 -0
  42. package/src/utils/ConvertSvgToPng.js +51 -0
  43. package/src/utils/ModelPool.js +160 -0
  44. package/src/utils/Models.js +128 -0
  45. package/src/utils/versionCheck.js +27 -0
  46. package/src/validators/ConfigValidator.js +205 -0
  47. package/src/validators/ConnectionValidator.js +65 -0
  48. package/typings/index.d.ts +3820 -0
@@ -0,0 +1,3820 @@
1
+ /// <reference lib="dom" />
2
+
3
+ type Facing = "FrontRight" | "FrontLeft" | "BackRight" | "BackLeft"
4
+ type Reactions = 'clap' | 'heart' | 'thumbs' | 'wave' | 'wink'
5
+ type PaymentMethods = "bot_wallet_only" | "bot_wallet_priority" | "user_wallet_only"
6
+ type EventType =
7
+ | 'SessionMetadata'
8
+ | 'ChatEvent'
9
+ | 'WhisperEvent'
10
+ | 'UserMovedEvent'
11
+ | 'UserJoinedEvent'
12
+ | 'UserLeftEvent'
13
+ | 'MessageEvent'
14
+ | 'TipReactionEvent'
15
+ | 'RoomModeratedEvent'
16
+ | 'ChannelEvent'
17
+
18
+ type Goldbars = 1 | 5 | 10 | 50 | 100 | 500 | 1000 | 5000 | 10000
19
+ type ItemCategory =
20
+ | "bag"
21
+ | "blush"
22
+ | "body"
23
+ | "dress"
24
+ | "earrings"
25
+ | "emote"
26
+ | "eye"
27
+ | "eyebrow"
28
+ | "face_hair"
29
+ | "fishing_rod"
30
+ | "freckle"
31
+ | "glasses"
32
+ | "gloves"
33
+ | "hair_back"
34
+ | "hair_front"
35
+ | "handbag"
36
+ | "hat"
37
+ | "jacket"
38
+ | "lashes"
39
+ | "mole"
40
+ | "mouth"
41
+ | "necklace"
42
+ | "nose"
43
+ | "pants"
44
+ | "shirt"
45
+ | "shoes"
46
+ | "shorts"
47
+ | "skirt"
48
+ | "watch"
49
+ | "fullsuit"
50
+ | "sock"
51
+ | "tattoo"
52
+ | "rod"
53
+ | "aura";
54
+
55
+ type Rarity =
56
+ | "common"
57
+ | "uncommon"
58
+ | "rare"
59
+ | "epic"
60
+ | "legendary"
61
+ | "none_";
62
+
63
+ type ChannelListenerCallback = (message: ChannelMessage) => void | Promise<void>;
64
+
65
+ type RoomInviteOptions = {
66
+ room_id: string;
67
+ world_id?: never;
68
+ };
69
+
70
+ type WorldInviteOptions = {
71
+ world_id: string;
72
+ room_id?: never;
73
+ };
74
+
75
+ type CooldownMetadata = Record<string, any>;
76
+
77
+ type InviteOptions = RoomInviteOptions | WorldInviteOptions;
78
+
79
+ /**
80
+ * Chat event filter function
81
+ * @param user - The user who sent the message
82
+ * @param message - The message content
83
+ * @returns boolean indicating if the event matches the filter
84
+ */
85
+ type ChatFilter = (user: User, message: string) => boolean;
86
+
87
+ /**
88
+ * Whisper event filter function
89
+ * @param user - The user who sent the whisper
90
+ * @param message - The whisper content
91
+ * @returns boolean indicating if the event matches the filter
92
+ */
93
+ type WhisperFilter = (user: User, message: string) => boolean;
94
+
95
+ /**
96
+ * Direct message event filter function
97
+ * @param user - The user who sent the direct message
98
+ * @param message - The message content
99
+ * @param conversation - The conversation information
100
+ * @returns boolean indicating if the event matches the filter
101
+ */
102
+ type DirectFilter = (user: User, message: string, conversation: Conversation) => boolean;
103
+
104
+ /**
105
+ * Tip event filter function
106
+ * @param sender - The user who sent the tip
107
+ * @param receiver - The user who received the tip
108
+ * @param currency - The tip currency information
109
+ * @returns boolean indicating if the event matches the filter
110
+ */
111
+ type TipFilter = (sender: Sender, receiver: Receiver, currency: Currency) => boolean;
112
+
113
+ /**
114
+ * Movement event filter function
115
+ * @param user - The user who moved
116
+ * @param position - The new position of the user
117
+ * @param anchor - The anchor position if user is sitting, null if standing
118
+ * @returns boolean indicating if the movement matches the filter
119
+ */
120
+ type MovementFilter = (user: User, position: Position, anchor: AnchorPosition | null) => boolean;
121
+
122
+
123
+ interface User {
124
+ id: string;
125
+ username: string;
126
+ }
127
+
128
+ interface Sender extends User { }
129
+ interface Receiver extends User { }
130
+
131
+ interface Position {
132
+ x: number;
133
+ y: number;
134
+ z: number;
135
+ facing: string;
136
+ }
137
+
138
+ interface AnchorPosition {
139
+ entity_id: string;
140
+ anchor_ix: number;
141
+ }
142
+
143
+ interface WalletResponse {
144
+ gold: number;
145
+ boost_tokens: number;
146
+ voice_tokens: number;
147
+ }
148
+
149
+ interface PermissionStats {
150
+ webapiSyncs: number;
151
+ fileSaves: number;
152
+ lastSync: number;
153
+ lastSave: number;
154
+ roles: number;
155
+ users: number;
156
+ webapiModerators: number;
157
+ webapiDesigners: number;
158
+ }
159
+
160
+ interface RoleObjectStructure {
161
+ [roleName: string]: string[]
162
+ }
163
+
164
+ interface GetRoomPrivilegeResponse {
165
+ moderator: boolean;
166
+ designer: boolean;
167
+ }
168
+
169
+ interface GetConversationsResponse {
170
+ id: string;
171
+ did_join: boolean;
172
+ unread_count: number;
173
+ last_message: string;
174
+ muted: boolean;
175
+ member_ids: string[];
176
+ name: string | null;
177
+ owner_id: string | null
178
+ }
179
+
180
+ interface Currency {
181
+ type: string;
182
+ amount: number
183
+ }
184
+
185
+ interface GetMessagesResponse {
186
+ message_id: string,
187
+ conversation_id: string,
188
+ createdAt: Date,
189
+ content: string,
190
+ sender_id: string,
191
+ category: string
192
+ }
193
+
194
+ interface ReadyEventMetadata {
195
+ connection_id: string
196
+ rate_limits: {
197
+ client: [number, number],
198
+ socials: [number, number]
199
+ }
200
+ }
201
+
202
+ interface ModerationAction {
203
+ type: string;
204
+ duration: number
205
+ }
206
+
207
+ interface BotInformation {
208
+ user: User;
209
+ room: {
210
+ id: string;
211
+ name: string;
212
+ owner_id: string;
213
+ };
214
+ }
215
+
216
+ interface ReadyEvent {
217
+ bot_id: string;
218
+ room: {
219
+ owner_id: string;
220
+ room_name: string;
221
+ }
222
+ metadata: ReadyEventMetadata
223
+ }
224
+
225
+ interface MetricData {
226
+ uptime: string;
227
+ connected: boolean;
228
+ room: string;
229
+ messages: number;
230
+ events: number;
231
+ errors: number;
232
+ cache: {
233
+ users: number;
234
+ memory: string;
235
+ active: number;
236
+ changes: number;
237
+ };
238
+ pendingReq: {
239
+ fireForget: number;
240
+ reqRes: number;
241
+ };
242
+ }
243
+
244
+ interface LoggerOptions {
245
+ showTimestamp?: boolean;
246
+ showMethodName?: boolean;
247
+ colors?: boolean;
248
+ }
249
+
250
+ interface Conversation {
251
+ id: `1_on_1:${string}:${string}`
252
+ is_new_conversation: boolean;
253
+ }
254
+
255
+ interface Outfit {
256
+ type: string;
257
+ amount: number;
258
+ id: string;
259
+ account_bound: boolean;
260
+ active_palette: number | null;
261
+ }
262
+
263
+ interface GetInventoryResponse extends Outfit { }
264
+
265
+ interface GetUserOutfitResponse extends Outfit { }
266
+
267
+ interface getUserAvatarResponse {
268
+ success: boolean,
269
+ width: number,
270
+ height: number,
271
+ size: number
272
+ }
273
+
274
+ interface ValidVoiceCheck {
275
+ secondsLeft: number,
276
+ autoSpeakersId: string[],
277
+ users: object
278
+ }
279
+
280
+ interface InvalidVoiceCheck {
281
+ message: string
282
+ }
283
+
284
+ interface CooldownInfo {
285
+ expiresAt: number;
286
+ duration: number;
287
+ metadata: CooldownMetadata;
288
+ remainingMs: number;
289
+ remainingSeconds: number;
290
+ progress: number;
291
+ }
292
+
293
+ interface GlobalCooldownInfo {
294
+ expiresAt: number;
295
+ duration: number;
296
+ setAt: number;
297
+ remainingMs: number;
298
+ }
299
+
300
+ interface GroupConfig {
301
+ defaultDuration: number;
302
+ maxConcurrent: number;
303
+ perUserLimit: number | null;
304
+ [key: string]: any;
305
+ }
306
+
307
+ interface CheckGroupResult {
308
+ allowed: boolean;
309
+ reason?: 'max_concurrent' | 'user_limit' | 'user_cooldown';
310
+ duration?: number;
311
+ remainingMs?: number;
312
+ remainingSeconds?: number;
313
+ message?: string;
314
+ }
315
+
316
+ interface StartGroupResult {
317
+ success: boolean;
318
+ actionId?: string;
319
+ startedAt?: number;
320
+ duration?: number;
321
+ allowed?: boolean;
322
+ reason?: 'max_concurrent' | 'user_limit' | 'user_cooldown';
323
+ message?: string;
324
+ remainingMs?: number;
325
+ }
326
+
327
+ interface AttemptResult {
328
+ success: boolean;
329
+ onCooldown: boolean;
330
+ executed?: boolean;
331
+ result?: any;
332
+ error?: Error;
333
+ cooldownSet?: boolean;
334
+ durationMs?: number;
335
+ remainingMs?: number;
336
+ remainingSeconds?: number;
337
+ data?: CooldownMetadata;
338
+ }
339
+
340
+ interface UserCooldown {
341
+ key: string;
342
+ remainingMs: number;
343
+ expiresAt: number;
344
+ metadata: CooldownMetadata;
345
+ }
346
+
347
+ interface CooldownMemoryUsage {
348
+ cooldowns: string;
349
+ globals: string;
350
+ groups: string;
351
+ total: string;
352
+ }
353
+
354
+ interface GroupStats {
355
+ active: number;
356
+ totalUsage: number;
357
+ config: GroupConfig;
358
+ }
359
+
360
+ interface CooldownManagerStats {
361
+ totalChecks: number;
362
+ blockedActions: number;
363
+ successfulActions: number;
364
+ averageCooldownTime: number;
365
+ activeCooldowns: number;
366
+ activeGlobals: number;
367
+ groups: Record<string, GroupStats>;
368
+ memoryUsage: CooldownMemoryUsage;
369
+ }
370
+
371
+ interface EventMap {
372
+ UserLeft: [user: User]
373
+ Ready: [session: ReadyEvent]
374
+ Chat: [user: User, message: string]
375
+ Whisper: [user: User, message: string]
376
+ UserJoined: [user: User, position: Position]
377
+ Voice: [users: VoiceUser[], secondsLeft: number, ended: boolean]
378
+ Channel: [senderId: string, message: string, tags: string[]]
379
+ Tip: [sender: Sender, receiver: Receiver, currency: Currency]
380
+ Direct: [user: User, message: string, conversation: Conversation]
381
+ Moderation: [moderator: User, target: User, action: ModerationAction]
382
+ Movement: [user: User, position: Position | null, anchor: AnchorPosition | null]
383
+ }
384
+
385
+
386
+
387
+ interface CachedUser {
388
+ position: Position;
389
+ anchor: AnchorPosition | null;
390
+ lastSeen: number;
391
+ username: string;
392
+ }
393
+
394
+ interface CachedPosition extends Position {
395
+ lastUpdated: number;
396
+ }
397
+
398
+ interface SpatialUser {
399
+ user: User;
400
+ position: CachedPosition;
401
+ anchor: {
402
+ entity_id: string;
403
+ anchor_ix: number;
404
+ } | null;
405
+ lastSeen: number;
406
+ }
407
+
408
+ interface VoiceUser {
409
+ user: User,
410
+ /**
411
+ * Either "muted" or "voice"
412
+ */
413
+ status: string
414
+ }
415
+
416
+ interface SpatialUserWithDistance extends SpatialUser {
417
+ distance: number;
418
+ }
419
+
420
+ interface RectangleCorners {
421
+ c1: { x: number; z: number };
422
+ c2: { x: number; z: number };
423
+ c3: { x: number; z: number };
424
+ c4: { x: number; z: number };
425
+ }
426
+
427
+ interface WebApiUser {
428
+ id: string;
429
+ username: string;
430
+ bio: string;
431
+ joinedAt: string;
432
+ lastOnline: string;
433
+ followers: number;
434
+ following: number;
435
+ friends: number;
436
+ currentRoom: string;
437
+ country: string;
438
+ crew: string;
439
+ voiceEnabled: boolean;
440
+ discordConnected: boolean;
441
+ avatar: string;
442
+ icon: string;
443
+ }
444
+
445
+ interface BasicRoom {
446
+ id: string;
447
+ name: string;
448
+ description: string | null;
449
+ category: string;
450
+ createdAt: string | null;
451
+ accessPolicy: string;
452
+ ownerId: string;
453
+ languages: string[];
454
+ isHomeRoom: boolean;
455
+ designerIds: string[];
456
+ moderatorIds: string[];
457
+ }
458
+
459
+ interface DetailedRoom extends BasicRoom {
460
+ connectedUsers: number;
461
+ thumbnail: string;
462
+ banner: string;
463
+ crewId: string;
464
+ bots: any[];
465
+ }
466
+
467
+ interface RoomsListResponse {
468
+ rooms: BasicRoom[];
469
+ pagination: {
470
+ total: number;
471
+ firstId: string;
472
+ lastId: string;
473
+ hasMore: boolean;
474
+ };
475
+ }
476
+
477
+ interface PostBody {
478
+ text: string;
479
+ inventory: PostInventory | null;
480
+ }
481
+
482
+ interface PostInventory {
483
+ items: PostItem[];
484
+ }
485
+
486
+ interface PostItem {
487
+ itemId: string;
488
+ activePalette: number | null;
489
+ accountBound: boolean;
490
+ }
491
+
492
+ interface PostComment {
493
+ id: string;
494
+ content: string;
495
+ postId: string;
496
+ authorId: string;
497
+ authorName: string;
498
+ likes: number;
499
+ }
500
+
501
+ interface PostListItem {
502
+ id: string;
503
+ authorId: string | null;
504
+ createdAt: string | null;
505
+ type: string | null;
506
+ visibility: string;
507
+ stats: {
508
+ comments: number;
509
+ likes: number;
510
+ reposts: number;
511
+ };
512
+ content: {
513
+ text: string;
514
+ hasBody: boolean;
515
+ caption: string | null;
516
+ };
517
+ fileKey: string | null;
518
+ featuredUserIds: string[];
519
+ inventory: PostInventory | null;
520
+ body: PostBody | null;
521
+ }
522
+
523
+ interface Post extends PostListItem {
524
+ comments: PostComment[];
525
+ }
526
+
527
+ interface PostsListResponse {
528
+ posts: PostListItem[];
529
+ pagination: {
530
+ total: number;
531
+ firstId: string;
532
+ lastId: string;
533
+ hasMore: boolean;
534
+ };
535
+ }
536
+
537
+ interface Affiliation {
538
+ id: string;
539
+ title: string;
540
+ type: string;
541
+ eventType: string | null;
542
+ }
543
+
544
+ interface OutfitItem {
545
+ itemId: string;
546
+ name: string;
547
+ rarity: string;
548
+ activePalette: number;
549
+ parts: number;
550
+ colors: OutfitItemColors | null;
551
+ linkedColors: string;
552
+ }
553
+
554
+ interface Seller {
555
+ userId: string;
556
+ username: string;
557
+ outfit: OutfitItem[];
558
+ lastConnectedAt: any | null;
559
+ }
560
+
561
+
562
+ interface StorefrontListings {
563
+ sellers: Seller[];
564
+ pages: number;
565
+ total: number;
566
+ }
567
+
568
+ interface OutfitItemColors {
569
+ linkedColors: string;
570
+ }
571
+
572
+ interface SkinPart {
573
+ bone: string;
574
+ slot: string;
575
+ imageFile: string;
576
+ attachmentName: string | null;
577
+ hasRemoteRenderLayer: boolean | null;
578
+ }
579
+
580
+ interface Item {
581
+ id: string;
582
+ name: string;
583
+ category: any | null;
584
+ colorLinkedCategories: any | null;
585
+ colorPalettes: any | null;
586
+ createdAt: any | null;
587
+ description: string | null;
588
+ pricing: {
589
+ gems: number | null;
590
+ pops: number | null;
591
+ };
592
+ properties: {
593
+ isPurchasable: boolean;
594
+ isTradable: boolean;
595
+ };
596
+ images: {
597
+ main: string | null;
598
+ icon: string | null;
599
+ };
600
+ links: {
601
+ linkIds: string[];
602
+ inspiredBy: any | null;
603
+ };
604
+ skinParts: {
605
+ front: SkinPart[];
606
+ back: SkinPart[];
607
+ };
608
+ metadata: {
609
+ dependentColors: any | null;
610
+ releaseDate: any | null;
611
+ keywords: any | null;
612
+ };
613
+ }
614
+
615
+ interface ItemsSearchResponse {
616
+ items: Item[];
617
+ pagination: {
618
+ total: number;
619
+ hasMore: boolean;
620
+ skip: number;
621
+ };
622
+ }
623
+
624
+ interface ItemDetail extends Item {
625
+ acquisition: {
626
+ cost: number | null;
627
+ amount: number | null;
628
+ currency: string | null;
629
+ };
630
+ metadata: {
631
+ dependentColors: any[];
632
+ releaseDate: any | null;
633
+ keywords: any | null;
634
+ };
635
+ relatedItems: {
636
+ items: Array<{
637
+ id: string;
638
+ name: string;
639
+ }>;
640
+ } | null;
641
+ affiliations: Affiliation[];
642
+ storefrontListings: StorefrontListings | null;
643
+ }
644
+
645
+ interface ItemsListResponse {
646
+ items: Item[];
647
+ pagination: {
648
+ total: number;
649
+ firstId: string;
650
+ lastId: string;
651
+ hasMore: boolean;
652
+ };
653
+ }
654
+
655
+ interface Grab {
656
+ id: string;
657
+ title: string;
658
+ description: string;
659
+ bannerImgUrl: string;
660
+ startsAt: any | null;
661
+ expiresAt: any | null;
662
+ rewards: GrabReward[];
663
+ costs: GrabCost[];
664
+ kompuRewards: GrabReward[];
665
+ limitedTimeKompu: LimitedKompu | null;
666
+ progressReward: ProgressReward | null;
667
+ }
668
+
669
+ interface GrabReward {
670
+ amount: number;
671
+ rewardId: string;
672
+ itemId: string | null;
673
+ accountBound: boolean;
674
+ metadata: any | null;
675
+ nfiMetadata: any | null;
676
+ itemNumber: number;
677
+ stackId: string;
678
+ nfiTemplateMetadata: any | null;
679
+ totalAmount: number | null;
680
+ bannerItem: boolean;
681
+ primaryImgUrl: string | null;
682
+ secondaryImgUrl: string | null;
683
+ isTradable: boolean;
684
+ }
685
+
686
+ interface GrabCost {
687
+ amount: number;
688
+ rewardId: string;
689
+ itemId: string | null;
690
+ accountBound: boolean;
691
+ metadata: any | null;
692
+ nfiMetadata: any | null;
693
+ itemNumber: number;
694
+ stackId: string;
695
+ nfiTemplateMetadata: any | null;
696
+ totalAmount: number | null;
697
+ bannerItem: boolean;
698
+ }
699
+
700
+ interface LimitedKompu {
701
+ expiresAt: any | null;
702
+ rewards: GrabReward[];
703
+ }
704
+
705
+ interface ProgressReward {
706
+ rewardsAt: number;
707
+ rewards: GrabReward[];
708
+ }
709
+
710
+ interface ItemsSearchParams {
711
+ /**
712
+ * Maximum number of items to return (default: 20, max: 100, min: 1)
713
+ */
714
+ limit?: number;
715
+
716
+ /**
717
+ * Number of items to skip (for pagination), default: 0
718
+ */
719
+ skip?: number;
720
+
721
+ /**
722
+ * Search query for item names
723
+ * @example
724
+ * 'Fiery Creature Eyes'
725
+ */
726
+ query?: string;
727
+ }
728
+
729
+ interface RoomsParams {
730
+ /**
731
+ * Maximum number of rooms to return (default: 20, max: 100, min: 1)
732
+ */
733
+ limit?: number;
734
+
735
+ /**
736
+ * Sort order for the results
737
+ * - `asc`: Oldest rooms first
738
+ * - `desc`: Newest rooms first (default)
739
+ */
740
+ sort_order?: 'asc' | 'desc';
741
+
742
+ /**
743
+ * Filter rooms by owner user ID
744
+ * @example '68a7dd5eecae68acca580f41'
745
+ */
746
+ owner_id?: string;
747
+
748
+ /**
749
+ * Filter rooms by name (partial match)
750
+ */
751
+ room_name?: string;
752
+
753
+ /**
754
+ * Pagination cursor - get rooms created after this room ID
755
+ * Used for forward pagination
756
+ * @example '692505a6bf18ebcc157260ec'
757
+ */
758
+ starts_after?: string;
759
+
760
+ /**
761
+ * Pagination cursor - get rooms created before this room ID
762
+ * Used for backward pagination
763
+ * @example '68a7dd5eecae68acca580f41'
764
+ */
765
+ ends_before?: string;
766
+ }
767
+
768
+ interface PostsParams {
769
+ /**
770
+ * Maximum number of posts to return (default: 20, max: 100, min: 1)
771
+ */
772
+ limit?: number;
773
+
774
+ /**
775
+ * Sort order for the results
776
+ * - `asc`: Oldest posts first
777
+ * - `desc`: Newest posts first (default)
778
+ */
779
+ sort_order?: 'asc' | 'desc';
780
+
781
+ /**
782
+ * Filter posts by author user ID
783
+ * @example '68a7dd5eecae68acca580f41'
784
+ */
785
+ author_id?: string;
786
+
787
+ /**
788
+ * Pagination cursor - get posts created after this post ID
789
+ * Used for forward pagination
790
+ * @example 'post_123456'
791
+ */
792
+ starts_after?: string;
793
+
794
+ /**
795
+ * Pagination cursor - get posts created before this post ID
796
+ * Used for backward pagination
797
+ * @example 'post_789012'
798
+ */
799
+ ends_before?: string;
800
+ }
801
+
802
+ interface ItemsParams {
803
+ /**
804
+ * Maximum number of items to return (default: 20, max: 100, min: 1)
805
+ */
806
+ limit?: number;
807
+
808
+ /**
809
+ * Sort order for the results
810
+ * - `asc`: Oldest items first
811
+ * - `desc`: Newest items first (default)
812
+ */
813
+ sort_order?: 'asc' | 'desc';
814
+
815
+ /**
816
+ * Filter items by rarity
817
+ * @example Rarity.RARE
818
+ * @example Rarity.EPIC
819
+ */
820
+ rarity?: Rarity;
821
+
822
+ /**
823
+ * Filter items by name (partial match)
824
+ * @example
825
+ * 'Fiery Creature Eyes'
826
+ */
827
+ item_name?: string;
828
+
829
+ /**
830
+ * Filter items by category
831
+ * @example ItemCategory.SHIRT
832
+ * @example ItemCategory.HAT
833
+ */
834
+ category?: ItemCategory;
835
+
836
+ /**
837
+ * Pagination cursor - get items created after this item ID
838
+ * Used for forward pagination
839
+ * @example 'item_123456'
840
+ */
841
+ starts_after?: string;
842
+
843
+ /**
844
+ * Pagination cursor - get items created before this item ID
845
+ * Used for backward pagination
846
+ * @example 'item_789012'
847
+ */
848
+ ends_before?: string;
849
+ }
850
+
851
+ interface DanceEmote {
852
+ id: string;
853
+ name: string;
854
+ duration: number;
855
+ }
856
+
857
+ interface DancingPlayer {
858
+ id: string;
859
+ username: string;
860
+ position: any;
861
+ timeoutId: NodeJS.Timeout
862
+ emoteIndex: number;
863
+ }
864
+
865
+ interface DanceFloorCorners {
866
+ x: number;
867
+ y: number;
868
+ z: number;
869
+ x1: number;
870
+ z1: number;
871
+ y1: number;
872
+ }
873
+
874
+ interface DanceFloorConfig {
875
+ id: string;
876
+ corners: DanceFloorCorners;
877
+ emotes: DanceEmote[];
878
+ players: DancingPlayer[];
879
+ filePath?: string;
880
+ hasWatcher?: boolean
881
+ }
882
+
883
+ /**
884
+ * Represents a hidden channel message
885
+ * Used for bot-to-bot communication within the same room
886
+ */
887
+ interface ChannelMessage {
888
+ /**
889
+ * Unique identifier for the message (UUID v4)
890
+ * @example "123e4567-e89b-12d3-a456-426614174000"
891
+ */
892
+ id: string;
893
+
894
+ /**
895
+ * The actual message content
896
+ * Can be any string data (JSON, plain text, etc.)
897
+ * @example "{\"username\":\"Player1\",\"action\":\"kicked\",\"reason\":\"spamming\"}"
898
+ * @example "Game started! Round 1"
899
+ */
900
+ message: string;
901
+
902
+ /**
903
+ * Normalized tags for categorization and filtering
904
+ * Tags are sorted alphabetically and in lowercase
905
+ * @example ["game", "start", "room-123"]
906
+ * @example ["moderation", "kick", "chat"]
907
+ */
908
+ tags: string[];
909
+
910
+ /**
911
+ * Unix timestamp in milliseconds when the message was stored locally
912
+ * @example 1703000000000
913
+ */
914
+ timestamp: number;
915
+
916
+ /**
917
+ * ID of the bot/user who sent the message
918
+ * @example "68a7dd5eecae68acca580f41"
919
+ */
920
+ senderId: string;
921
+
922
+ /**
923
+ * Whether this message was sent by the current bot instance
924
+ * - `true`: Message was sent by this bot
925
+ * - `false`: Message was received from another bot
926
+ */
927
+ sent: boolean;
928
+ }
929
+
930
+ /**
931
+ * Filter criteria for querying channel messages
932
+ */
933
+ interface ChannelFilter {
934
+ /**
935
+ * Tags to filter messages by
936
+ * All specified tags must be present in the message
937
+ * @example ["game", "start"] - Only messages with BOTH "game" AND "start" tags
938
+ * @example ["moderation"] - Only messages with "moderation" tag
939
+ */
940
+ tags?: string | string[];
941
+
942
+ /**
943
+ * Start timestamp in milliseconds (inclusive)
944
+ * Only messages with timestamp >= since will be returned
945
+ * @default 0 (no lower bound)
946
+ * @example Date.now() - 3600000 // Last hour
947
+ */
948
+ since?: number;
949
+
950
+ /**
951
+ * End timestamp in milliseconds (inclusive)
952
+ * Only messages with timestamp <= until will be returned
953
+ * @default Date.now() (current time)
954
+ * @example Date.now() - 60000 // Up to 1 minute ago
955
+ */
956
+ until?: number;
957
+
958
+ /**
959
+ * Maximum number of messages to return
960
+ * @default 50
961
+ * @minimum 1
962
+ * @maximum 1000
963
+ * @example 10 - Return only 10 most recent messages
964
+ */
965
+ limit?: number;
966
+ }
967
+
968
+ /**
969
+ * Statistics about the channel system
970
+ */
971
+ interface ChannelStats {
972
+ /**
973
+ * Total number of messages currently stored in history
974
+ * Older messages are automatically removed (max 500)
975
+ * @example 127
976
+ */
977
+ totalMessages: number;
978
+
979
+ /**
980
+ * Number of active listeners/subscriptions
981
+ * @example 3
982
+ */
983
+ listeners: number;
984
+ }
985
+
986
+ declare class RoleManager {
987
+ /**
988
+ * Create a new custom role
989
+ * @param roleName - Name of the role (any string)
990
+ * @returns True if created, false if already exists
991
+ */
992
+ createRole(roleName: string): boolean;
993
+
994
+ /**
995
+ * Add user to a role
996
+ * @param roleName - Role to add to
997
+ * @param userId - User ID to add
998
+ * @returns True if added, false if already in role
999
+ */
1000
+ addToRole(roleName: string, userId: string): boolean;
1001
+
1002
+ /**
1003
+ * Remove user from a role
1004
+ * @param roleName - Role to remove from
1005
+ * @param userId - User ID to remove
1006
+ * @returns True if removed, false if not in role
1007
+ */
1008
+ removeFromRole(roleName: string, userId: string): boolean;
1009
+
1010
+ /**
1011
+ * Check if user is in a role
1012
+ * @param roleName - Role to check
1013
+ * @param userId - User ID to check
1014
+ * @returns True if user has the role
1015
+ */
1016
+ hasRole(roleName: string, userId: string): boolean;
1017
+
1018
+ /**
1019
+ * Check if user is in any of the given roles
1020
+ * @param roleNames - Array of roles to check
1021
+ * @param userId - User ID to check
1022
+ * @returns True if user has any of the roles
1023
+ */
1024
+ hasAnyRole(roleNames: string[], userId: string): boolean;
1025
+
1026
+ /**
1027
+ * Get all roles a user is in
1028
+ * @param userId - User ID to check
1029
+ * @returns Array of role names
1030
+ */
1031
+ getUserRoles(userId: string): string[];
1032
+
1033
+ /**
1034
+ * Get all users in a role
1035
+ * @param roleName - Role to get users from
1036
+ * @returns Array of user IDs
1037
+ */
1038
+ getUsersInRole(roleName: string): string[];
1039
+
1040
+ /**
1041
+ * Get all role names
1042
+ * @returns Array of all role names
1043
+ */
1044
+ getAllRoles(): string[];
1045
+
1046
+ /**
1047
+ * Delete a role completely
1048
+ * @param roleName - Role to delete
1049
+ * @returns True if deleted
1050
+ */
1051
+ deleteRole(roleName: string): boolean;
1052
+
1053
+ /**
1054
+ * Rename a role
1055
+ * @param oldName - Current role name
1056
+ * @param newName - New role name
1057
+ * @returns True if renamed
1058
+ */
1059
+ renameRole(oldName: string, newName: string): boolean;
1060
+
1061
+ /**
1062
+ * Check if user is owner (has 'owner' role)
1063
+ * @param userId - User ID to check
1064
+ * @returns True if user is owner
1065
+ */
1066
+ isOwner(userId: string): boolean;
1067
+
1068
+ /**
1069
+ * Check if user is moderator (has 'moderator' role or from Web API)
1070
+ * @param userId - User ID to check
1071
+ * @returns True if user is moderator
1072
+ */
1073
+ isModerator(userId: string): boolean;
1074
+
1075
+ /**
1076
+ * Check if user is designer (has 'designer' role or from Web API)
1077
+ * @param userId - User ID to check
1078
+ * @returns True if user is designer
1079
+ */
1080
+ isDesigner(userId: string): boolean;
1081
+
1082
+ /**
1083
+ * Get all moderators (combined from role + Web API)
1084
+ * @returns Array of all moderator user IDs
1085
+ */
1086
+ getAllModerators(): string[];
1087
+
1088
+ /**
1089
+ * Get all designers (combined from role + Web API)
1090
+ * @returns Array of all designer user IDs
1091
+ */
1092
+ getAllDesigners(): string[];
1093
+
1094
+ /**
1095
+ * Force immediate sync with Web API and save to file
1096
+ * @returns Promise that resolves when sync is complete
1097
+ */
1098
+ forceSync(): Promise<void>;
1099
+
1100
+ /**
1101
+ * Export roles as JSON object
1102
+ * @returns Object with role names as keys and user ID arrays as values
1103
+ */
1104
+ exportToObject(): RoleObjectStructure;
1105
+
1106
+ /**
1107
+ * Import roles from JSON object
1108
+ * @param obj - Object with role names as keys and user ID arrays as values
1109
+ * @returns True if imported successfully
1110
+ */
1111
+ importFromObject(obj: RoleObjectStructure): boolean;
1112
+
1113
+ /**
1114
+ * Clear all roles and Web API data
1115
+ */
1116
+ clearAll(): void;
1117
+
1118
+ /**
1119
+ * Get sync statistics
1120
+ */
1121
+ getStats(): PermissionStats;
1122
+ }
1123
+
1124
+ declare class CooldownManager {
1125
+ /**
1126
+ * The manager handles individual cooldowns, global cooldowns (affecting all users),
1127
+ * and group-based cooldowns with rate limiting capabilities.
1128
+ *
1129
+ * @example
1130
+ * const cooldown = new CooldownManager();
1131
+ * cooldown.startAutoCleanup(); // Optional: auto-clean expired cooldowns
1132
+ */
1133
+ constructor();
1134
+
1135
+ /**
1136
+ * Sets a cooldown for a specific key. If the key is already on cooldown,
1137
+ * returns false and doesn't override the existing cooldown.
1138
+ *
1139
+ * @param key - Unique identifier for the cooldown. Common patterns:
1140
+ * - `user:{userId}:{command}` for user-specific command cooldowns
1141
+ * - `item:{itemId}:{userId}` for item usage cooldowns
1142
+ * - `action:{action}:{target}` for specific action cooldowns
1143
+ * @param durationMs - Cooldown duration in milliseconds
1144
+ * @param metadata - Optional metadata to store with the cooldown for later retrieval
1145
+ * @returns `true` if cooldown was set successfully, `false` if key was already on cooldown
1146
+ *
1147
+ * @example
1148
+ * // Create a variable for the bot cooldown
1149
+ * const cooldown = bot.utils.cooldown
1150
+ *
1151
+ * // Set a 5-second cooldown for a user's dance command
1152
+ * const wasSet = cooldown.set(`user:${userId}:!dance`, 5000, {
1153
+ * command: 'dance',
1154
+ * timestamp: Date.now()
1155
+ * });
1156
+ *
1157
+ * @example
1158
+ * // Prevent item spam - 30 seconds between using the same item
1159
+ * cooldown.set(`item:teleport_scroll:${userId}`, 30000, {
1160
+ * itemName: 'Teleport Scroll',
1161
+ * usageCount: 1
1162
+ * });
1163
+ */
1164
+ set(key: string, durationMs: number, metadata?: CooldownMetadata): boolean;
1165
+
1166
+ /**
1167
+ * Checks if a key is currently on cooldown. Automatically cleans up
1168
+ * expired cooldowns unless disabled.
1169
+ *
1170
+ * @param key - The key to check for active cooldown
1171
+ * @param autoCleanup - If `true` (default), automatically removes expired cooldowns
1172
+ * @returns Cooldown information object if active, `null` if not on cooldown or expired
1173
+ *
1174
+ * @example
1175
+ * // Create a variable for the bot cooldown
1176
+ * const cooldown = bot.utils.cooldown
1177
+ *
1178
+ * const cooldownInfo = cooldown.check(`user:${userId}:!dance`);
1179
+ * if (cooldownInfo) {
1180
+ * // Still on cooldown
1181
+ * console.log(`Wait ${cooldownInfo.remainingSeconds} more seconds`);
1182
+ * console.log(`Progress: ${(cooldownInfo.progress * 100).toFixed(1)}% complete`);
1183
+ * }
1184
+ *
1185
+ * @example
1186
+ * // Manual cleanup control
1187
+ * const cooldownInfo = cooldown.check(key, false); // Don't auto-clean
1188
+ * if (cooldownInfo && cooldownInfo.remainingMs < 100) {
1189
+ * // Almost expired, handle special case
1190
+ * }
1191
+ */
1192
+ check(key: string, autoCleanup?: boolean): CooldownInfo | null;
1193
+
1194
+ /**
1195
+ * Gets the remaining time in milliseconds for a cooldown.
1196
+ * Returns 0 if the key is not on cooldown.
1197
+ *
1198
+ * @param key - The key to check
1199
+ * @returns Milliseconds remaining until cooldown expires, or 0 if no active cooldown
1200
+ *
1201
+ * @example
1202
+ * // Create a variable for the bot cooldown
1203
+ * const cooldown = bot.utils.cooldown
1204
+ *
1205
+ * const remaining = cooldown.getRemaining(`user:${userId}:!dance`);
1206
+ * if (remaining > 0) {
1207
+ * // Format and display to user
1208
+ * const seconds = Math.ceil(remaining / 1000);
1209
+ * bot.whisper.send(userId, `Please wait ${seconds} seconds`);
1210
+ * }
1211
+ */
1212
+ getRemaining(key: string): number;
1213
+
1214
+ /**
1215
+ * Attempts to execute an action if not on cooldown. If the key is not on cooldown,
1216
+ * sets the cooldown and optionally executes the callback. If on cooldown,
1217
+ * returns information about the remaining time without executing the callback.
1218
+ *
1219
+ * @param key - The key to check and set cooldown for
1220
+ * @param durationMs - Cooldown duration to set if successful
1221
+ * @param callback - Optional function to execute if not on cooldown
1222
+ * @returns Result object containing success status, remaining time (if on cooldown),
1223
+ * or execution result (if callback was executed)
1224
+ *
1225
+ * @example
1226
+ * // Create a variable for the bot cooldown
1227
+ * const cooldown = bot.utils.cooldown
1228
+ *
1229
+ * // Basic usage with callback
1230
+ * const result = cooldown.attempt(`user:${userId}:!dance`, 3000, () => {
1231
+ * // This only executes if not on cooldown
1232
+ * bot.player.emote('dance', userId);
1233
+ * return 'dance_started';
1234
+ * });
1235
+ *
1236
+ * if (!result.success) {
1237
+ * // On cooldown - inform user
1238
+ * bot.whisper.send(userId, `Wait ${result.remainingSeconds} seconds`);
1239
+ * } else if (result.executed) {
1240
+ * // Callback was executed
1241
+ * console.log('Result:', result.result);
1242
+ * }
1243
+ *
1244
+ * @example
1245
+ * // Without callback (just checks and sets)
1246
+ * const result = cooldown.attempt(`user:${userId}:action`, 5000);
1247
+ * if (result.success) {
1248
+ * // Not on cooldown, cooldown was set
1249
+ * // Proceed with action...
1250
+ * }
1251
+ */
1252
+ attempt(key: string, durationMs: number, callback?: (() => any) | null): AttemptResult;
1253
+
1254
+ /**
1255
+ * Removes an active cooldown for a specific key.
1256
+ *
1257
+ * @param key - The key to remove cooldown for
1258
+ * @returns `true` if cooldown existed and was removed, `false` if no cooldown existed
1259
+ *
1260
+ * @example
1261
+ * // Create a variable for the bot cooldown
1262
+ * const cooldown = bot.utils.cooldown
1263
+ *
1264
+ * // Admin override - remove user's cooldown
1265
+ * if (isAdmin(adminId)) {
1266
+ * const removed = cooldown.remove(`user:${targetUserId}:!dance`);
1267
+ * if (removed) {
1268
+ * bot.whisper.send(targetUserId, 'Your cooldown was cleared by admin');
1269
+ * }
1270
+ * }
1271
+ *
1272
+ * @example
1273
+ * // Error recovery - remove stuck cooldown
1274
+ * if (errorOccurred) {
1275
+ * cooldown.remove(`user:${userId}:!purchase`);
1276
+ * // Allow user to retry
1277
+ * }
1278
+ */
1279
+ remove(key: string): boolean;
1280
+
1281
+ /**
1282
+ * Clears all cooldowns, or only those matching a prefix.
1283
+ *
1284
+ * @param prefix - Optional prefix to filter keys. If provided, only clears
1285
+ * cooldowns whose keys start with this prefix.
1286
+ * @returns Number of cooldowns that were cleared
1287
+ *
1288
+ * @example
1289
+ * // Create a variable for the bot cooldown
1290
+ * const cooldown = bot.utils.cooldown
1291
+ *
1292
+ * // Clear all cooldowns (server reset)
1293
+ * const clearedAll = cooldown.clear();
1294
+ * console.log(`Cleared ${clearedAll} cooldowns`);
1295
+ *
1296
+ * @example
1297
+ * // Clear only user-related cooldowns
1298
+ * const clearedUsers = cooldown.clear('user:');
1299
+ *
1300
+ * @example
1301
+ * // Clear cooldowns for specific user
1302
+ * const clearedUser = cooldown.clear(`user:${userId}:`);
1303
+ *
1304
+ * @example
1305
+ * // Clear daily cooldowns
1306
+ * const clearedDaily = cooldown.clear('daily:');
1307
+ */
1308
+ clear(prefix?: string | null): number;
1309
+
1310
+ /**
1311
+ * Sets a global cooldown that affects all users. Useful for system-wide
1312
+ * events, maintenance, or world events.
1313
+ *
1314
+ * @param action - Unique identifier for the global action
1315
+ * @param durationMs - Duration in milliseconds
1316
+ * @returns `true` if global cooldown was set, `false` if already active
1317
+ *
1318
+ * @example
1319
+ * // System maintenance
1320
+ * cooldown.setGlobal('maintenance', 300000); // 5 minutes
1321
+ *
1322
+ * @example
1323
+ * // World boss spawn cooldown
1324
+ * cooldown.setGlobal('world_boss_spawn', 3600000); // 1 hour
1325
+ *
1326
+ * @example
1327
+ * // Limited-time event
1328
+ * cooldown.setGlobal('halloween_event', 604800000); // 7 days
1329
+ */
1330
+ setGlobal(action: string, durationMs: number): boolean;
1331
+
1332
+ /**
1333
+ * Checks if a global cooldown is currently active.
1334
+ *
1335
+ * @param action - The global action identifier
1336
+ * @returns Global cooldown information if active, `null` if not active
1337
+ *
1338
+ * @example
1339
+ * // Create a variable for the bot cooldown
1340
+ * const cooldown = bot.utils.cooldown
1341
+ *
1342
+ * // Check if system is in maintenance
1343
+ * const maintenance = cooldown.checkGlobal('maintenance');
1344
+ * if (maintenance) {
1345
+ * bot.message.send(`🛠️ Maintenance in progress for ${cooldown.formatTime(maintenance.remainingMs)}`);
1346
+ * return;
1347
+ * }
1348
+ *
1349
+ * @example
1350
+ * // Check world boss availability
1351
+ * const bossCooldown = cooldown.checkGlobal('world_boss_spawn');
1352
+ * if (bossCooldown) {
1353
+ * const timeStr = cooldown.formatTime(bossCooldown.remainingMs);
1354
+ * bot.message.send(`The world boss will respawn in ${timeStr}`);
1355
+ * } else {
1356
+ * // Spawn boss logic
1357
+ * }
1358
+ */
1359
+ checkGlobal(action: string): GlobalCooldownInfo | null;
1360
+
1361
+ /**
1362
+ * Creates a cooldown group for managing limited resources with
1363
+ * configurable concurrency and per-user limits.
1364
+ *
1365
+ * @param groupName - Unique name for the group
1366
+ * @param config - Configuration object for the group
1367
+ *
1368
+ * @example
1369
+ * // Create a variable for the bot cooldown
1370
+ * const cooldown = bot.utils.cooldown
1371
+ *
1372
+ * // Create a teleporter with max 3 concurrent users, 10s cooldown per user
1373
+ * cooldown.createGroup('main_teleporter', {
1374
+ * defaultDuration: 10000,
1375
+ * maxConcurrent: 3,
1376
+ * perUserLimit: 1
1377
+ * });
1378
+ *
1379
+ * @example
1380
+ * // Game table - only 1 game at a time, 5 minute games
1381
+ * cooldown.createGroup('poker_table', {
1382
+ * defaultDuration: 300000,
1383
+ * maxConcurrent: 1,
1384
+ * perUserLimit: 1
1385
+ * });
1386
+ *
1387
+ * @example
1388
+ * // Fishing spot - many can fish, but limited lines per user
1389
+ * cooldown.createGroup('fishing_spot', {
1390
+ * defaultDuration: 30000,
1391
+ * maxConcurrent: 10,
1392
+ * perUserLimit: 3
1393
+ * });
1394
+ */
1395
+ createGroup(groupName: string, config?: Partial<GroupConfig>): void;
1396
+
1397
+ /**
1398
+ * Checks if a user can perform an action in a group, considering
1399
+ * max concurrent limits and per-user limits.
1400
+ *
1401
+ * @param groupName - The group to check
1402
+ * @param userId - Optional user ID to check per-user limits
1403
+ * @returns Object indicating if action is allowed and reason if not
1404
+ *
1405
+ * @example
1406
+ * // Create a variable for the bot cooldown
1407
+ * const cooldown = bot.utils.cooldown
1408
+ *
1409
+ * // Check if user can teleport
1410
+ * const check = cooldown.checkGroup('main_teleporter', userId);
1411
+ * if (!check.allowed) {
1412
+ * switch (check.reason) {
1413
+ * case 'max_concurrent':
1414
+ * return 'Teleporter is busy! Wait for others to finish.';
1415
+ * case 'user_limit':
1416
+ * return 'You are already teleporting!';
1417
+ * case 'user_cooldown':
1418
+ * return `You just teleported! Wait ${check.remainingSeconds}s`;
1419
+ * }
1420
+ * }
1421
+ *
1422
+ * @example
1423
+ * // Check resource availability without user context
1424
+ * const resourceCheck = cooldown.checkGroup('mining_vein');
1425
+ * if (!resourceCheck.allowed && resourceCheck.reason === 'max_concurrent') {
1426
+ * return 'This mining vein is fully occupied!';
1427
+ * }
1428
+ */
1429
+ checkGroup(groupName: string, userId?: string | null): CheckGroupResult;
1430
+
1431
+ /**
1432
+ * Starts an action in a group, consuming a slot and setting user cooldown.
1433
+ * Returns detailed result including unique action ID for later ending.
1434
+ *
1435
+ * @param groupName - The group to start action in
1436
+ * @param actionId - Unique identifier for this specific action instance
1437
+ * @param userId - Optional user ID for per-user tracking
1438
+ * @returns Detailed result with success status and action information
1439
+ *
1440
+ * @example
1441
+ * // Create a variable for the bot cooldown
1442
+ * const cooldown = bot.utils.cooldown
1443
+ *
1444
+ * // Start a teleport action
1445
+ * const actionId = `teleport:${Date.now()}:${userId}`;
1446
+ * const result = cooldown.startGroupAction('main_teleporter', actionId, userId);
1447
+ *
1448
+ * if (!result.success) {
1449
+ * return result.message; // "Teleporter is busy!" etc.
1450
+ * }
1451
+ *
1452
+ * // Store actionId for later cleanup
1453
+ * currentTeleports.set(userId, {
1454
+ * actionId: result.actionId,
1455
+ * startedAt: result.startedAt
1456
+ * });
1457
+ *
1458
+ * // When teleport completes
1459
+ * cooldown.endGroupAction('main_teleporter', result.actionId);
1460
+ *
1461
+ * @example
1462
+ * // Start a game session
1463
+ * const gameId = `chess:${Date.now()}:${player1}:${player2}`;
1464
+ * const gameResult = cooldown.startGroupAction('chess_table', gameId, player1);
1465
+ * // Note: Only first player consumes per-user limit
1466
+ */
1467
+ startGroupAction(groupName: string, actionId: string, userId?: string | null): StartGroupResult;
1468
+
1469
+ /**
1470
+ * Ends an action in a group, freeing up the slot for others.
1471
+ *
1472
+ * @param groupName - The group containing the action
1473
+ * @param actionId - The unique action ID to end
1474
+ * @returns `true` if action existed and was ended, `false` if not found
1475
+ *
1476
+ * @example
1477
+ * // Create a variable for the bot cooldown
1478
+ * const cooldown = bot.utils.cooldown
1479
+ *
1480
+ * // When teleport completes
1481
+ * const actionId = currentTeleports.get(userId)?.actionId;
1482
+ * if (actionId) {
1483
+ * const ended = cooldown.endGroupAction('main_teleporter', actionId);
1484
+ * if (ended) {
1485
+ * currentTeleports.delete(userId);
1486
+ * bot.whisper.send(userId, 'Teleport complete!');
1487
+ * }
1488
+ * }
1489
+ *
1490
+ * @example
1491
+ * // Game completion
1492
+ * function endGame(gameId: string) {
1493
+ * cooldown.endGroupAction('poker_table', gameId);
1494
+ * // Also remove user cooldowns if needed
1495
+ * cooldown.remove(`poker_cooldown:${player1}`);
1496
+ * cooldown.remove(`poker_cooldown:${player2}`);
1497
+ * }
1498
+ */
1499
+ endGroupAction(groupName: string, actionId: string): boolean;
1500
+
1501
+ /**
1502
+ * Gets all active cooldowns for a specific user. Useful for displaying
1503
+ * user's current restrictions or detecting potential abuse.
1504
+ *
1505
+ * @param userId - The user ID to get cooldowns for
1506
+ * @returns Array of active cooldown objects for the user
1507
+ *
1508
+ * @example
1509
+ * // Create a variable for the bot cooldown
1510
+ * const cooldown = bot.utils.cooldown
1511
+ *
1512
+ * // Display user's active cooldowns
1513
+ * const userCooldowns = cooldown.getUserCooldowns(userId);
1514
+ * if (userCooldowns.length > 0) {
1515
+ * const cooldownList = userCooldowns.map(c =>
1516
+ * `${c.metadata.command || 'Action'}: ${Math.ceil(c.remainingMs/1000)}s`
1517
+ * ).join('\n');
1518
+ * bot.whisper.send(userId, `Your active cooldowns:\n${cooldownList}`);
1519
+ * }
1520
+ *
1521
+ * @example
1522
+ * // Detect potential abusers
1523
+ * const userCooldowns = cooldown.getUserCooldowns(userId);
1524
+ * if (userCooldowns.length > 15) {
1525
+ * bot.utils.logger.warn('High cooldown count', { userId, count: userCooldowns.length });
1526
+ * // Consider temporary restriction
1527
+ * }
1528
+ *
1529
+ * @example
1530
+ * // Admin view of user restrictions
1531
+ * function getUserStatus(userId: string) {
1532
+ * const cooldowns = cooldown.getUserCooldowns(userId);
1533
+ * return {
1534
+ * userId,
1535
+ * activeRestrictions: cooldowns.length,
1536
+ * restrictions: cooldowns.map(c => ({
1537
+ * type: c.key.split(':')[1],
1538
+ * remaining: cooldown.formatTime(c.remainingMs),
1539
+ * reason: c.metadata.reason
1540
+ * }))
1541
+ * };
1542
+ * }
1543
+ */
1544
+ getUserCooldowns(userId: string): UserCooldown[];
1545
+
1546
+ /**
1547
+ * Gets comprehensive usage statistics and current state of the cooldown manager.
1548
+ * Useful for monitoring, debugging, and performance analysis.
1549
+ *
1550
+ * @returns Statistics object containing usage metrics, current counts, and memory estimates
1551
+ *
1552
+ * @example
1553
+ * // Create a variable for the bot cooldown
1554
+ * const cooldown = bot.utils.cooldown
1555
+ *
1556
+ * // Periodic monitoring
1557
+ * setInterval(() => {
1558
+ * const stats = cooldown.getStats();
1559
+ * const successRate = (stats.successfulActions / stats.totalChecks * 100).toFixed(1);
1560
+ *
1561
+ * console.log(`
1562
+ * Cooldown Stats:
1563
+ * - Success Rate: ${successRate}%
1564
+ * - Active Cooldowns: ${stats.activeCooldowns}
1565
+ * - Memory Usage: ${stats.memoryUsage.total}
1566
+ * - Blocked Actions: ${stats.blockedActions}
1567
+ * `);
1568
+ *
1569
+ * // Check group status
1570
+ * for (const [groupName, groupStats] of Object.entries(stats.groups)) {
1571
+ * console.log(`${groupName}: ${groupStats.active}/${groupStats.config.maxConcurrent} active`);
1572
+ * }
1573
+ * }, 60000); // Log every minute
1574
+ *
1575
+ * @example
1576
+ * // Dashboard endpoint
1577
+ * function getSystemStatus() {
1578
+ * const stats = cooldown.getStats();
1579
+ * return {
1580
+ * uptime: Date.now() - startTime,
1581
+ * cooldownStats: stats,
1582
+ * health: stats.activeCooldowns < 1000 ? 'healthy' : 'warning'
1583
+ * };
1584
+ * }
1585
+ *
1586
+ * @example
1587
+ * // Debugging high memory usage
1588
+ * if (memoryIsHigh()) {
1589
+ * const stats = cooldown.getStats();
1590
+ * console.log('Memory breakdown:', stats.memoryUsage);
1591
+ * // Clear old cooldowns if memory is high
1592
+ * if (stats.activeCooldowns > 500) {
1593
+ * cooldown.clear('old:'); // Assuming you prefix old cooldowns
1594
+ * }
1595
+ * }
1596
+ */
1597
+ getStats(): CooldownManagerStats;
1598
+
1599
+ /**
1600
+ * Starts automatic background cleanup of expired cooldowns.
1601
+ * Recommended for long-running applications to prevent memory buildup.
1602
+ *
1603
+ * @param intervalMs - Cleanup interval in milliseconds (default: 60000 = 1 minute)
1604
+ * @returns The interval ID that can be used to stop cleanup
1605
+ *
1606
+ * @example
1607
+ * // Create a variable for the bot cooldown
1608
+ * const cooldown = bot.utils.cooldown
1609
+ *
1610
+ * // Start with default 1-minute interval
1611
+ * cooldown.startAutoCleanup();
1612
+ *
1613
+ * @example
1614
+ * // More frequent cleanup for high-traffic bots
1615
+ * cooldown.startAutoCleanup(30000); // Every 30 seconds
1616
+ *
1617
+ * @example
1618
+ * // Store interval for management
1619
+ * const cleanupInterval = cooldown.startAutoCleanup(60000);
1620
+ *
1621
+ * // Later, if needed
1622
+ * clearInterval(cleanupInterval);
1623
+ * // Or use stopAutoCleanup()
1624
+ */
1625
+ startAutoCleanup(intervalMs?: number): NodeJS.Timeout;
1626
+
1627
+ /**
1628
+ * Stops the automatic cleanup interval if it's running.
1629
+ *
1630
+ * @example
1631
+ * // Create a variable for the bot cooldown
1632
+ * const cooldown = bot.utils.cooldown
1633
+ *
1634
+ * // Graceful shutdown
1635
+ * function shutdown() {
1636
+ * cooldown.stopAutoCleanup();
1637
+ * cooldown.destroy();
1638
+ * process.exit(0);
1639
+ * }
1640
+ *
1641
+ * @example
1642
+ * // Temporary pause
1643
+ * cooldown.stopAutoCleanup();
1644
+ * // Do some maintenance...
1645
+ * cooldown.startAutoCleanup(); // Resume
1646
+ */
1647
+ stopAutoCleanup(): void;
1648
+
1649
+ /**
1650
+ * Completely destroys all cooldown data and stops auto-cleanup.
1651
+ * Resets the manager to its initial empty state.
1652
+ *
1653
+ * @example
1654
+ * // Create a variable for the bot cooldown
1655
+ * const cooldown = bot.utils.cooldown
1656
+ *
1657
+ * // Server reset
1658
+ * function resetServer() {
1659
+ * cooldown.destroy();
1660
+ * console.log('All cooldowns cleared');
1661
+ * // Reinitialize if needed
1662
+ * cooldown.startAutoCleanup();
1663
+ * }
1664
+ *
1665
+ * @example
1666
+ * // Testing - clean between tests
1667
+ * beforeEach(() => {
1668
+ * cooldown.destroy();
1669
+ * });
1670
+ *
1671
+ * @example
1672
+ * // Memory management
1673
+ * if (memoryPressure > 0.9) { // 90% memory usage
1674
+ * cooldown.destroy();
1675
+ * // Recreate essential groups
1676
+ * cooldown.createGroup('essential_teleporter', {...});
1677
+ * }
1678
+ */
1679
+ destroy(): void;
1680
+
1681
+ /**
1682
+ * Static utility method to format milliseconds into a human-readable string.
1683
+ * Automatically selects appropriate time units (ms, seconds, minutes, hours, days).
1684
+ *
1685
+ * @param ms - Milliseconds to format
1686
+ * @returns Formatted time string (e.g., "2m 5s", "1h 30m", "500ms")
1687
+ *
1688
+ * @example
1689
+ * // Create a variable for the bot cooldown
1690
+ * const cooldown = bot.utils.cooldown
1691
+ *
1692
+ * // Display remaining time to users
1693
+ * const remaining = cooldown.getRemaining(`user:${userId}:!command`);
1694
+ * if (remaining > 0) {
1695
+ * const timeStr = cooldown.formatTime(remaining);
1696
+ * bot.whisper.send(userId, `Please wait ${timeStr}`);
1697
+ * }
1698
+ *
1699
+ * @example
1700
+ * // Different formatting examples
1701
+ * cooldown.formatTime(500); // "500ms"
1702
+ * cooldown.formatTime(1500); // "2s" (rounded up)
1703
+ * cooldown.formatTime(65000); // "1m 5s"
1704
+ * cooldown.formatTime(90000); // "1m 30s"
1705
+ * cooldown.formatTime(7200000); // "2h"
1706
+ * cooldown.formatTime(172800000); // "2d"
1707
+ * cooldown.formatTime(0); // "0s"
1708
+ *
1709
+ * @example
1710
+ * // Use in game timers
1711
+ * function displayBossTimer(remainingMs: number) {
1712
+ * const timeStr = cooldown.formatTime(remainingMs);
1713
+ * bot.message.send(`Boss respawns in ${timeStr}`);
1714
+ * }
1715
+ */
1716
+ static formatTime(ms: number): string;
1717
+ }
1718
+
1719
+ /**
1720
+ * Hidden channel system for bot-to-bot communication
1721
+ * Messages are broadcast to all bots in the same room
1722
+ */
1723
+ declare class Channel {
1724
+ /**
1725
+ * Send a message to the hidden channel
1726
+ * All bots in the room will receive this message
1727
+ *
1728
+ * @param message - The message content to send
1729
+ * @param tags - Tags for categorizing and filtering the message
1730
+ * @returns Promise resolving to true if sent successfully, false otherwise
1731
+ *
1732
+ * @example
1733
+ * ```typescript
1734
+ * // Send a JSON message with tags
1735
+ * const success = await bot.channel.send(
1736
+ * JSON.stringify({ username: 'Player1', score: 100 }),
1737
+ * ['game', 'score-update']
1738
+ * );
1739
+ *
1740
+ * // Send a plain text message
1741
+ * await bot.channel.send('Game starting in 10 seconds', ['game', 'countdown']);
1742
+ *
1743
+ * // Send without tags (global broadcast)
1744
+ * await bot.channel.send('System restarting');
1745
+ * ```
1746
+ */
1747
+ send(message: string, tags?: string[]): Promise<boolean>;
1748
+
1749
+ /**
1750
+ * Listen for messages with specific tags
1751
+ * The callback receives the full ChannelMessage object
1752
+ *
1753
+ * @param tags - Tag(s) to listen for. All tags must be present in message.
1754
+ * @param callback - Function called when matching message arrives
1755
+ * @returns Listener ID for unsubscribing, or null on error
1756
+ *
1757
+ * @example
1758
+ * ```typescript
1759
+ * // Listen for moderation events
1760
+ * const listenerId = bot.channel.on(['moderation', 'kick'], (data) => {
1761
+ * const event = JSON.parse(data.message);
1762
+ * console.log(`${event.username} was kicked by ${data.senderId}`);
1763
+ * });
1764
+ *
1765
+ * // Listen for game start with multiple tags
1766
+ * bot.channel.on(['game', 'tic-tac-toe', 'start'], (data) => {
1767
+ * console.log(`Game starting: ${data.message}`);
1768
+ * startGame();
1769
+ * });
1770
+ *
1771
+ * // Listen for any message with a specific tag
1772
+ * bot.channel.on('system', (data) => {
1773
+ * console.log(`System message: ${data.message}`);
1774
+ * });
1775
+ * ```
1776
+ */
1777
+ on(tags: string | string[], callback: ChannelListenerCallback): string | null;
1778
+
1779
+ /**
1780
+ * Listen once for messages with specific tags
1781
+ * Automatically unsubscribes after first matching message
1782
+ *
1783
+ * @param tags - Tag(s) to listen for
1784
+ * @param callback - Function called when matching message arrives
1785
+ * @returns Listener ID for manual unsubscription, or null on error
1786
+ *
1787
+ * @example
1788
+ * ```typescript
1789
+ * // Wait for shutdown signal
1790
+ * bot.channel.once(['system', 'shutdown'], (data) => {
1791
+ * console.log('Received shutdown command');
1792
+ * bot.disconnect();
1793
+ * });
1794
+ *
1795
+ * // Wait for game initialization
1796
+ * bot.channel.once(['game', 'init-complete'], (data) => {
1797
+ * console.log('Game initialized, starting...');
1798
+ * });
1799
+ * ```
1800
+ */
1801
+ once(tags: string | string[], callback: ChannelListenerCallback): string | null;
1802
+
1803
+ /**
1804
+ * Remove a specific listener
1805
+ *
1806
+ * @param listenerId - ID returned by on() or once()
1807
+ * @returns true if listener was removed, false if not found
1808
+ *
1809
+ * @example
1810
+ * ```typescript
1811
+ * // Store listener ID when subscribing
1812
+ * const listenerId = bot.channel.on(['game'], handler);
1813
+ *
1814
+ * // Later, remove the listener
1815
+ * const removed = bot.channel.off(listenerId);
1816
+ * console.log(`Listener removed: ${removed}`);
1817
+ * ```
1818
+ */
1819
+ off(listenerId: string): boolean;
1820
+
1821
+ /**
1822
+ * Remove all listeners for specific tags
1823
+ *
1824
+ * @param tags - Tag(s) to remove listeners for
1825
+ * @returns Number of listeners removed
1826
+ *
1827
+ * @example
1828
+ * ```typescript
1829
+ * // Remove all game-related listeners
1830
+ * const removed = bot.channel.offAll(['game']);
1831
+ * console.log(`Removed ${removed} game listeners`);
1832
+ *
1833
+ * // Remove all listeners for multiple tags
1834
+ * bot.channel.offAll(['game', 'moderation']);
1835
+ * ```
1836
+ */
1837
+ offAll(tags: string | string[]): number;
1838
+
1839
+ /**
1840
+ * Query historical channel messages
1841
+ * Searches through stored messages (max 500 most recent)
1842
+ *
1843
+ * @param filter - Query filter criteria
1844
+ * @returns Array of matching messages, newest first
1845
+ *
1846
+ * @example
1847
+ * ```typescript
1848
+ * // Get all moderation messages from last hour
1849
+ * const modLogs = bot.channel.query({
1850
+ * tags: ['moderation'],
1851
+ * since: Date.now() - 3600000,
1852
+ * limit: 100
1853
+ * });
1854
+ *
1855
+ * // Get messages with multiple tags
1856
+ * const gameStarts = bot.channel.query({
1857
+ * tags: ['game', 'start'],
1858
+ * limit: 10
1859
+ * });
1860
+ *
1861
+ * // Get all messages from last 5 minutes
1862
+ * const recent = bot.channel.query({
1863
+ * since: Date.now() - 300000
1864
+ * });
1865
+ * ```
1866
+ */
1867
+ query(filter?: ChannelFilter): ChannelMessage[];
1868
+
1869
+ /**
1870
+ * Get channel system statistics
1871
+ *
1872
+ * @returns Current channel statistics
1873
+ *
1874
+ * @example
1875
+ * ```typescript
1876
+ * const stats = bot.channel.stats();
1877
+ * console.log(`Messages stored: ${stats.totalMessages}`);
1878
+ * console.log(`Active listeners: ${stats.listeners}`);
1879
+ * ```
1880
+ */
1881
+ stats(): ChannelStats;
1882
+
1883
+ /**
1884
+ * Clear all channel data
1885
+ * Removes message history and all listeners
1886
+ *
1887
+ * @example
1888
+ * ```typescript
1889
+ * // Reset channel system
1890
+ * bot.channel.clear();
1891
+ *
1892
+ * // Or on bot shutdown
1893
+ * process.on('SIGINT', () => {
1894
+ * bot.channel.clear();
1895
+ * bot.disconnect();
1896
+ * });
1897
+ * ```
1898
+ */
1899
+ clear(): void;
1900
+ }
1901
+
1902
+ declare class DanceFloor {
1903
+
1904
+ /**
1905
+ * Create a new dance floor
1906
+ * @param Id - Unique identifier
1907
+ * @param corners - 3D boundaries {x, y, z, x1, y1, z1}
1908
+ * @param emotes - Emote configuration (JSON file path, single emote object, or array of emotes)
1909
+ * @returns Promise<DanceFloorConfig>
1910
+ * @example
1911
+ *
1912
+ * let danceFloor = bot.utils.DanceFloor
1913
+ *
1914
+ * // From JSON file
1915
+ * await danceFloor.create('floor1', { x:0, y:0, z:0, x1:10, y1:5, z1:10}, './dance.json');
1916
+ *
1917
+ * // Single emote
1918
+ * await danceFloor.create('floor2', corners, { id: "dance", name: "Dance", duration: 3000 });
1919
+ *
1920
+ * // Array of emotes
1921
+ * await danceFloor.create('floor3', corners, [
1922
+ * { id: "dance", name: "Dance", duration: 3000 },
1923
+ * { id: "wave", name: "Wave", duration: 2000 }
1924
+ * ]);
1925
+ */
1926
+ create(Id: string, corners: DanceFloorCorners, emotes: string | DanceEmote | DanceEmote[]): Promise<DanceFloorConfig>;
1927
+
1928
+ /**
1929
+ * Get dance floor information
1930
+ * @param Id - Dance floor identifier
1931
+ * @returns DanceFloorConfig or null if not found
1932
+ */
1933
+ getInfo(Id: string): DanceFloorConfig | null;
1934
+
1935
+ /**
1936
+ * Hot-reload emote configuration for a specific dance floor
1937
+ * @param floorId - Dance floor identifier
1938
+ * @returns Promise<boolean> - Success status
1939
+ */
1940
+ hotReload(floorId: string): Promise<boolean>;
1941
+
1942
+ /**
1943
+ * Reload all dance floors with file watchers
1944
+ * @returns Promise<Array<{floorId: string, success: boolean, error?: string}>>
1945
+ */
1946
+ reloadAll(): Promise<Array<{ floorId: string, success: boolean, error?: string }>>;
1947
+
1948
+ /**
1949
+ * Update emotes for a dance floor (programmatically)
1950
+ * @param floorId - Dance floor identifier
1951
+ * @param newEmotes - New emote configuration
1952
+ * @returns Promise<boolean>
1953
+ */
1954
+ updateEmotes(floorId: string, newEmotes: string | DanceEmote | DanceEmote[]): Promise<boolean>;
1955
+
1956
+ /**
1957
+ * Destroy all dance floors and cleanup
1958
+ */
1959
+ destroy(): void;
1960
+ }
1961
+
1962
+ declare class AwaitClass {
1963
+ /**
1964
+ * Wait for chat messages that match the filter
1965
+ * @param filter - Filter function that receives (user, message)
1966
+ * @param timeout - Timeout in milliseconds
1967
+ * @param maxToCollect - Maximum number of messages to collect
1968
+ * @param uniqueUsers - If true, only collect one message per user (default: false)
1969
+ *
1970
+ * @returns Promise resolving to array of matching events, or empty array if timeout
1971
+ * @example
1972
+ * ```typescript
1973
+ * // Wait for a specific command from any user
1974
+ * const results = await bot.await.chat(
1975
+ * (user, message) => message === '!play',
1976
+ * 30000,
1977
+ * 1,
1978
+ * false
1979
+ * );
1980
+ * if (results.length > 0) {
1981
+ * const [[user, message]] = results;
1982
+ * await bot.message.send(`Welcome ${user.username} to the game!`);
1983
+ * }
1984
+ *
1985
+ * // Collect one vote per user (unique users only)
1986
+ * await bot.message.send("Vote for your favorite color: !red, !blue, or !green");
1987
+ * const votes = await bot.await.chat(
1988
+ * (user, message) => ['!red', '!blue', '!green'].includes(message),
1989
+ * 45000,
1990
+ * 50,
1991
+ * true // Each user can only vote once
1992
+ * );
1993
+ *
1994
+ * // Count votes - each user counted only once
1995
+ * const redVotes = votes.filter(([user, message]) => message === '!red').length;
1996
+ * const blueVotes = votes.filter(([user, message]) => message === '!blue').length;
1997
+ * await bot.message.send(`Results - Red: ${redVotes}, Blue: ${blueVotes}`);
1998
+ *
1999
+ * // Collect messages from 5 unique users
2000
+ * const responses = await bot.await.chat(
2001
+ * (user, message) => message.startsWith('!feedback'),
2002
+ * 60000,
2003
+ * 5,
2004
+ * true // One feedback per user
2005
+ * );
2006
+ * ```
2007
+ */
2008
+ chat(filter?: ChatFilter, timeout?: number, maxToCollect?: number, uniqueUsers?: boolean): Promise<[User, string][] | []>;
2009
+
2010
+ /**
2011
+ * Wait for whisper messages that match the filter
2012
+ * @param filter - Filter function that receives (user, message)
2013
+ * @param timeout - Timeout in milliseconds
2014
+ * @param maxToCollect - Maximum number of whispers to collect
2015
+ * @param uniqueUsers - If true, only collect one whisper per user (default: false)
2016
+ * @returns Promise resolving to array of matching events, or empty array if timeout
2017
+ * @example
2018
+ * ```typescript
2019
+ * // Secret command system - one request per user
2020
+ * await bot.message.send("Whisper me '!secret' for special access");
2021
+ * const secretRequests = await bot.await.whisper(
2022
+ * (user, message) => message === '!secret',
2023
+ * 30000,
2024
+ * 20,
2025
+ * true // Each user can only request once
2026
+ * );
2027
+ *
2028
+ * // Grant access to each unique user who whispered
2029
+ * for (const [user, message] of secretRequests) {
2030
+ * await bot.whisper.send(user.id, "You now have secret access! Use !commands");
2031
+ * await bot.room.privilege.add(user.id);
2032
+ * }
2033
+ *
2034
+ * // Private moderation reports - one report per user
2035
+ * const reports = await bot.await.whisper(
2036
+ * (user, message) => message.startsWith('!report'),
2037
+ * 60000,
2038
+ * 10,
2039
+ * true // Prevent users from spamming multiple reports
2040
+ * );
2041
+ *
2042
+ * // Each user's first report only
2043
+ * reports.forEach(([user, message]) => {
2044
+ * bot.utils.logger.info('Moderation', `Report from ${user.username}: ${message}`);
2045
+ * });
2046
+ * ```
2047
+ */
2048
+ whisper(filter?: WhisperFilter, timeout?: number, maxToCollect?: number, uniqueUsers?: boolean): Promise<[User, string][] | []>;
2049
+
2050
+ /**
2051
+ * Wait for direct messages that match the filter
2052
+ * @param filter - Filter function that receives (user, message, conversation)
2053
+ * @param timeout - Timeout in milliseconds
2054
+ * @param maxToCollect - Maximum number of DMs to collect
2055
+ * @param uniqueUsers - If true, only collect one DM per user (default: false)
2056
+ * @returns Promise resolving to array of matching events, or empty array if timeout
2057
+ * @example
2058
+ * ```typescript
2059
+ * // Handle support tickets - one ticket per user
2060
+ * const supportTickets = await bot.await.direct(
2061
+ * (user, message, conversation) => message.includes('support') || message.includes('help'),
2062
+ * 120000,
2063
+ * 10,
2064
+ * true // One support request per user
2065
+ * );
2066
+ *
2067
+ * // Each user gets one ticket created
2068
+ * for (const [user, message, conversation] of supportTickets) {
2069
+ * await bot.direct.send(conversation.id, "Thanks for contacting support! We'll help you shortly.");
2070
+ * createSupportTicket(user.id, message, conversation.id);
2071
+ * }
2072
+ *
2073
+ * // Wait for confirmation from unique users
2074
+ * const confirmations = await bot.await.direct(
2075
+ * (user, message, conversation) =>
2076
+ * conversation.id === specificConversationId && message === '!confirm',
2077
+ * 60000,
2078
+ * 5,
2079
+ * true // One confirmation per user
2080
+ * );
2081
+ *
2082
+ * // Collect feedback from 10 unique users
2083
+ * await bot.direct.send(conversationId, "Please rate your experience 1-5 stars");
2084
+ * const ratings = await bot.await.direct(
2085
+ * (user, message, conv) => /^[1-5]$/.test(message) && conv.id === conversationId,
2086
+ * 30000,
2087
+ * 10,
2088
+ * true // One rating per user
2089
+ * );
2090
+ *
2091
+ * // Average rating from unique users only
2092
+ * const averageRating = ratings.reduce((sum, [user, rating]) => sum + parseInt(rating), 0) / ratings.length;
2093
+ * ```
2094
+ */
2095
+ direct(filter?: DirectFilter, timeout?: number, maxToCollect?: number, uniqueUsers?: boolean): Promise<[User, string, Conversation][] | []>;
2096
+
2097
+ /**
2098
+ * Wait for tips that match the filter
2099
+ * @param filter - Filter function that receives (sender, receiver, currency)
2100
+ * @param timeout - Timeout in milliseconds
2101
+ * @param maxToCollect - Maximum number of tips to collect
2102
+ * @param uniqueUsers - If true, only count one tip per sender (default: false)
2103
+ * @returns Promise resolving to array of matching events, or empty array if timeout
2104
+ * @example
2105
+ * ```typescript
2106
+ * // Track first donation from each user
2107
+ * await bot.message.send("Fundraiser started! First donation from each user counts!");
2108
+ * const firstDonations = await bot.await.tip(
2109
+ * (sender, receiver, currency) =>
2110
+ * receiver.id === bot.info.user.id && currency.amount >= 50,
2111
+ * 300000,
2112
+ * 100,
2113
+ * true // Only count first donation from each user
2114
+ * );
2115
+ *
2116
+ * // Count unique donors, not total donations
2117
+ * const uniqueDonors = firstDonations.length;
2118
+ * let totalRaised = firstDonations.reduce((sum, [sender, receiver, currency]) => sum + currency.amount, 0);
2119
+ * await bot.message.send(`${uniqueDonors} unique donors raised ${totalRaised} gold!`);
2120
+ *
2121
+ * // VIP reward - first large donation only
2122
+ * const vipDonors = await bot.await.tip(
2123
+ * (sender, receiver, currency) =>
2124
+ * receiver.id === bot.info.user.id && currency.amount >= 500,
2125
+ * 180000,
2126
+ * 20,
2127
+ * true // Users can only become VIP once
2128
+ * );
2129
+ *
2130
+ * // Grant VIP to first-time large donors
2131
+ * vipDonors.forEach(([sender, receiver, currency]) => {
2132
+ * await bot.whisper.send(sender.id, "You're now a VIP! Special perks unlocked.");
2133
+ * await bot.room.privilege.add(sender.id);
2134
+ * });
2135
+ *
2136
+ * // Track unique tippers for analytics
2137
+ * const uniqueTippers = await bot.await.tip(
2138
+ * (sender, receiver, currency) => receiver.id === bot.info.user.id,
2139
+ * 60000,
2140
+ * 50,
2141
+ * true // Count each tipper only once
2142
+ * );
2143
+ *
2144
+ * bot.utils.logger.info('Economy', `${uniqueTippers.length} unique tippers in the last minute`);
2145
+ * ```
2146
+ */
2147
+ tip(filter?: TipFilter, timeout?: number, maxToCollect?: number, uniqueUsers?: boolean): Promise<[Sender, Receiver, Currency][] | []>;
2148
+
2149
+ /**
2150
+ * Wait for player movements that match the filter
2151
+ * @param filter - Filter function that receives (user, position, anchor)
2152
+ * @param timeout - Timeout in milliseconds
2153
+ * @param maxToCollect - Maximum number of movements to collect
2154
+ * @param uniqueUsers - If true, only collect one movement per user (default: false)
2155
+ * @returns Promise resolving to array of matching events, or empty array if timeout
2156
+ * @example
2157
+ * ```typescript
2158
+ * // Track first entry to dance floor per user
2159
+ * const firstEntrants = await bot.await.movement(
2160
+ * (user, position, anchor) =>
2161
+ * position.x >= 10 && position.x <= 15 &&
2162
+ * position.z >= 10 && position.z <= 15,
2163
+ * 60000,
2164
+ * 30,
2165
+ * true // Only track first time each user enters
2166
+ * );
2167
+ *
2168
+ * // Welcome users on their first entry only
2169
+ * for (const [user, position, anchor] of firstEntrants) {
2170
+ * await bot.message.send(`Welcome to the dance floor, ${user.username}! First time here?`);
2171
+ * await bot.player.emote('dance', user.id);
2172
+ * }
2173
+ *
2174
+ * // Track unique users sitting on premium chairs
2175
+ * const uniqueChairUsers = await bot.await.movement(
2176
+ * (user, position, anchor) =>
2177
+ * anchor?.entity_id === 'premium_chair_001',
2178
+ * 120000,
2179
+ * 10,
2180
+ * true // Track each user only once
2181
+ * );
2182
+ *
2183
+ * // VIP area entry - track first visit per user
2184
+ * const firstVIPVisitors = await bot.await.movement(
2185
+ * (user, position, anchor) =>
2186
+ * position.y >= 5 && // Upper floor
2187
+ * position.x >= 20 && position.x <= 25 &&
2188
+ * position.z >= 20 && position.z <= 25,
2189
+ * 180000,
2190
+ * 50,
2191
+ * true // First visit only
2192
+ * );
2193
+ *
2194
+ * // Award achievement for first time leaving spawn
2195
+ * const spawnLeavers = await bot.await.movement(
2196
+ * (user, position, anchor) => {
2197
+ * const distanceFromSpawn = Math.sqrt(position.x ** 2 + position.z ** 2);
2198
+ * return distanceFromSpawn > 10;
2199
+ * },
2200
+ * 60000,
2201
+ * 100,
2202
+ * true // Achievement only once per user
2203
+ * );
2204
+ *
2205
+ * // Secret room discovery - once per user
2206
+ * const secretDiscoverers = await bot.await.movement(
2207
+ * (user, position, anchor) =>
2208
+ * position.x === 100 && position.y === 5 && position.z === 100,
2209
+ * 300000,
2210
+ * 50,
2211
+ * true // Reward only on first discovery
2212
+ * );
2213
+ *
2214
+ * secretDiscoverers.forEach(([user, position, anchor]) => {
2215
+ * await bot.whisper.send(user.id, "You found the secret room! Here's your reward.");
2216
+ * await bot.player.tip(user.id, 100);
2217
+ * });
2218
+ *
2219
+ * // Zone crossing - track first time per user
2220
+ * const firstZoneCrossers = await bot.await.movement(
2221
+ * (user, position, anchor) => {
2222
+ * const previousPosition = bot.cache.position.get(user.id)?.position;
2223
+ * if (!previousPosition) return false;
2224
+ *
2225
+ * const wasInZoneA = previousPosition.x < 0;
2226
+ * const nowInZoneB = position.x >= 0;
2227
+ * return wasInZoneA && nowInZoneB;
2228
+ * },
2229
+ * 120000,
2230
+ * 30,
2231
+ * true // Only count first crossing per user
2232
+ * );
2233
+ * ```
2234
+ */
2235
+ movement(filter?: MovementFilter, timeout?: number, maxToCollect?: number, uniqueUsers?: boolean): Promise<[User, Position, AnchorPosition | null][] | []>;
2236
+ }
2237
+
2238
+ declare class WebApi {
2239
+ user: {
2240
+ /**
2241
+ * Get user information from Highrise Web API
2242
+ * @param identifier - User ID or username
2243
+ * @returns Promise resolving to formatted user data or null if not found
2244
+ * @throws {TypeError} If identifier is not a non-empty string
2245
+ * @example
2246
+ * ```typescript
2247
+ * const user = await bot.webapi.user.get('Unfairly');
2248
+ * ```
2249
+ */
2250
+ get(identifier: string): Promise<WebApiUser | null>;
2251
+
2252
+ /**
2253
+ * Get user avatar as png in high quality
2254
+ * @param identifier - User ID or username
2255
+ * @param imagePath - User Avatar output path (default: "avatar.png")
2256
+ * @returns Promise resolving to getUserAvatarResponse if success or null if not
2257
+ * @throws {TypeError} If identifier is not a non-empty string
2258
+ *
2259
+ * @todo use username for imagePath -> "username".png
2260
+ *
2261
+ * @example
2262
+ * ```typescript
2263
+ * await bot.webapi.user.get('Unfairly', `${user.username}.png`);
2264
+ * ```
2265
+ */
2266
+ getUserAvatar(identifier: string, imagePath: string): Promise<getUserAvatarResponse>
2267
+ }
2268
+
2269
+ room: {
2270
+ /**
2271
+ * Get detailed room information from Highrise Web API
2272
+ * @param roomId - Room ID to lookup
2273
+ * @returns Promise resolving to detailed room data or null if not found
2274
+ * @throws {TypeError} If roomId is not a non-empty string
2275
+ * @example
2276
+ * ```typescript
2277
+ * const room = await bot.webapi.room.get('692125c2521b7580234d0f35');
2278
+ * ```
2279
+ */
2280
+ get(roomId: string): Promise<DetailedRoom | null>;
2281
+
2282
+ /**
2283
+ * Get a list of rooms from Highrise Web API with pagination
2284
+ * @param params - Query parameters for filtering and pagination
2285
+ * @returns Promise resolving to rooms list with pagination info or null
2286
+ * @throws {TypeError} If params are invalid
2287
+ * @example
2288
+ * ```typescript
2289
+ * // Get recent rooms
2290
+ * const rooms = await bot.webapi.room.list({ limit: 50, sort_order: 'desc' });
2291
+ *
2292
+ * // Search rooms by name
2293
+ * const results = await bot.webapi.room.list({ room_name: 'party', limit: 20 });
2294
+ *
2295
+ * // Get rooms by owner
2296
+ * const ownerRooms = await bot.webapi.room.list({ owner_id: '68a7dd5eecae68acca580f41' });
2297
+ *
2298
+ * // Pagination example
2299
+ * const page1 = await bot.webapi.room.list({ limit: 50 });
2300
+ * const page2 = await bot.webapi.room.list({ limit: 50, starts_after: page1.pagination.lastId });
2301
+ * ```
2302
+ */
2303
+ list(params?: RoomsParams): Promise<RoomsListResponse | null>;
2304
+
2305
+ /**
2306
+ * Get bot current room details
2307
+ */
2308
+ getCurrentRoom(): Promise<DetailedRoom>
2309
+
2310
+ /**
2311
+ * Search rooms by name (convenience method)
2312
+ * @param name - Room name to search for
2313
+ * @param limit - Maximum number of results (default: 20, max: 100)
2314
+ * @returns Promise resolving to rooms list or null
2315
+ * @example
2316
+ * ```typescript
2317
+ * const results = await bot.webapi.room.searchByName('party', 15);
2318
+ * ```
2319
+ */
2320
+ searchByName(name: string, limit?: number): Promise<RoomsListResponse | null>;
2321
+
2322
+ /**
2323
+ * Get rooms by owner ID (convenience method)
2324
+ * @param ownerId - Owner user ID
2325
+ * @param limit - Maximum number of results (default: 20, max: 100)
2326
+ * @returns Promise resolving to rooms list or null
2327
+ * @example
2328
+ * ```typescript
2329
+ * const ownerRooms = await bot.webapi.room.getByOwner('68a7dd5eecae68acca580f41');
2330
+ * ```
2331
+ */
2332
+ getByOwner(ownerId: string, limit?: number): Promise<RoomsListResponse | null>;
2333
+
2334
+ /**
2335
+ * Get recent rooms (convenience method)
2336
+ * @param limit - Maximum number of results (default: 20, max: 100)
2337
+ * @returns Promise resolving to rooms list or null
2338
+ * @example
2339
+ * ```typescript
2340
+ * const recent = await bot.webapi.room.getRecent(10);
2341
+ * ```
2342
+ */
2343
+ getRecent(limit?: number): Promise<RoomsListResponse | null>;
2344
+ }
2345
+
2346
+ post: {
2347
+ /**
2348
+ * Get post information from Highrise Web API
2349
+ * @param postId - Post ID to lookup
2350
+ * @returns Promise resolving to formatted post data or null if not found
2351
+ * @throws {TypeError} If postId is not a non-empty string
2352
+ * @example
2353
+ * ```typescript
2354
+ * const post = await bot.webapi.post.get('post_123456');
2355
+ * ```
2356
+ */
2357
+ get(postId: string): Promise<Post | null>;
2358
+
2359
+ /**
2360
+ * Get a list of posts with basic information (optimized for listing)
2361
+ * @param params - Query parameters for filtering and pagination
2362
+ * @returns Promise resolving to posts list with pagination info or null
2363
+ * @example
2364
+ * ```typescript
2365
+ * const posts = await bot.webapi.post.list({ limit: 50 });
2366
+ * posts.posts.forEach(post => {
2367
+ * console.log(`${post.id}: ${post.content.text.substring(0, 50)}...`);
2368
+ * console.log(`Likes: ${post.stats.likes}, Items: ${post.inventoryPreview?.itemCount}`);
2369
+ * });
2370
+ * ```
2371
+ */
2372
+ list(params?: PostsParams): Promise<PostsListResponse | null>;
2373
+
2374
+ /**
2375
+ * Get posts by specific author (convenience method)
2376
+ * @param authorId - Author user ID
2377
+ * @param limit - Maximum number of results (default: 20, max: 100)
2378
+ * @returns Promise resolving to posts list or null
2379
+ * @example
2380
+ * ```typescript
2381
+ * const authorPosts = await bot.webapi.post.getByAuthor('68a7dd5eecae68acca580f41');
2382
+ * ```
2383
+ */
2384
+ getByAuthor(authorId: string, limit?: number): Promise<PostsListResponse | null>;
2385
+
2386
+ /**
2387
+ * Get recent posts (convenience method)
2388
+ * @param limit - Maximum number of results (default: 20, max: 100)
2389
+ * @returns Promise resolving to posts list or null
2390
+ * @example
2391
+ * ```typescript
2392
+ * const recent = await bot.webapi.post.getRecent(10);
2393
+ * ```
2394
+ */
2395
+ getRecent(limit?: number): Promise<PostsListResponse | null>;
2396
+ }
2397
+
2398
+ item: {
2399
+ /**
2400
+ * Get detailed item information from Highrise Web API
2401
+ * @param itemId - Item ID to lookup
2402
+ * @returns Promise resolving to detailed item data or null if not found
2403
+ * @throws {TypeError} If itemId is not a non-empty string
2404
+ * @example
2405
+ * ```typescript
2406
+ * const item = await bot.webapi.item.get('eye-n_fierycreatureeyes');
2407
+ *
2408
+ * // Example response includes:
2409
+ * // - Basic item info and pricing
2410
+ * // - Acquisition details
2411
+ * // - Skin parts and customization
2412
+ * // - Related items and affiliations
2413
+ * // - Storefront listings with sellers
2414
+ * // - Seller outfits and availability
2415
+ * ```
2416
+ */
2417
+ get(itemId: string): Promise<ItemDetail | null>;
2418
+
2419
+ /**
2420
+ * Get a list of items from Highrise catalog with filtering and pagination
2421
+ * @param params - Query parameters for filtering and pagination
2422
+ * @returns Promise resolving to items list with pagination info or null
2423
+ * @throws {TypeError} If params are invalid
2424
+ * @example
2425
+ * ```typescript
2426
+ * // Get recent items
2427
+ * const items = await bot.webapi.item.list({ limit: 50, sort_order: 'desc' });
2428
+ *
2429
+ * // Get rare shirts
2430
+ * const rareShirts = await bot.webapi.item.list({
2431
+ * category: ItemCategory.SHIRT,
2432
+ * rarity: Rarity.RARE,
2433
+ * limit: 20
2434
+ * });
2435
+ *
2436
+ * // Search for dragon items
2437
+ * const dragonItems = await bot.webapi.item.list({ item_name: 'dragon', limit: 30 });
2438
+ *
2439
+ * // Pagination example
2440
+ * const page1 = await bot.webapi.item.list({ limit: 50 });
2441
+ * const page2 = await bot.webapi.item.list({ limit: 50, starts_after: page1.pagination.lastId });
2442
+ * ```
2443
+ */
2444
+ list(params?: ItemsParams): Promise<ItemsListResponse | null>;
2445
+
2446
+ /**
2447
+ * Search for items in the Highrise catalog
2448
+ * @param params - Search parameters including query and pagination
2449
+ * @returns Promise resolving to items search results with pagination
2450
+ * @throws {TypeError} If params are invalid
2451
+ * @example
2452
+ * ```typescript
2453
+ * // Search for shirts
2454
+ * const shirts = await bot.webapi.item.search({ query: 'shirt', limit: 20 });
2455
+ *
2456
+ * // Paginate results
2457
+ * const page1 = await bot.webapi.item.search({ query: 'hat', limit: 20, skip: 0 });
2458
+ * const page2 = await bot.webapi.item.search({ query: 'hat', limit: 20, skip: 20 });
2459
+ *
2460
+ * // Process results
2461
+ * shirts.items.forEach(item => {
2462
+ * console.log(`${item.name} - ${item.pricing.gems} gems`);
2463
+ * console.log(`Purchasable: ${item.properties.isPurchasable}`);
2464
+ * console.log(`Tradable: ${item.properties.isTradable}`);
2465
+ * });
2466
+ * ```
2467
+ */
2468
+ search(params?: ItemsSearchParams): Promise<ItemsSearchResponse | null>;
2469
+
2470
+ /**
2471
+ * Search items by name (convenience method)
2472
+ * @param name - Item name to search for
2473
+ * @param limit - Maximum number of results (default: 20, max: 100)
2474
+ * @returns Promise resolving to items search results
2475
+ * @example
2476
+ * ```typescript
2477
+ * const hats = await bot.webapi.item.searchByName('hat', 30);
2478
+ * ```
2479
+ */
2480
+ searchByName(name: string, limit?: number): Promise<ItemsSearchResponse | null>;
2481
+
2482
+ /**
2483
+ * Get items by category (convenience method)
2484
+ * @param category - Item category to filter by
2485
+ * @param limit - Maximum number of results (default: 20, max: 100)
2486
+ * @returns Promise resolving to items list or null
2487
+ * @example
2488
+ * ```typescript
2489
+ * const hats = await bot.webapi.item.getByCategory(ItemCategory.HAT, 30);
2490
+ * ```
2491
+ */
2492
+ getByCategory(category: ItemCategory, limit?: number): Promise<ItemsListResponse | null>;
2493
+
2494
+ /**
2495
+ * Get items by rarity (convenience method)
2496
+ * @param rarity - Item rarity to filter by
2497
+ * @param limit - Maximum number of results (default: 20, max: 100)
2498
+ * @returns Promise resolving to items list or null
2499
+ * @example
2500
+ * ```typescript
2501
+ * const epicItems = await bot.webapi.item.getByRarity(Rarity.EPIC, 25);
2502
+ * ```
2503
+ */
2504
+ getByRarity(rarity: Rarity, limit?: number): Promise<ItemsListResponse | null>;
2505
+
2506
+ /**
2507
+ * Get items by name (convenience method)
2508
+ * @param name - Item name to search for
2509
+ * @param limit - Maximum number of results (default: 20, max: 100)
2510
+ * @returns Promise resolving to items list or null
2511
+ * @example
2512
+ * ```typescript
2513
+ * const dragonItems = await bot.webapi.item.getByName('dragon', 20);
2514
+ * ```
2515
+ */
2516
+ getByName(name: string, limit?: number): Promise<ItemsListResponse | null>;
2517
+
2518
+ /**
2519
+ * Get recent items (convenience method)
2520
+ * @param limit - Maximum number of results (default: 20, max: 100)
2521
+ * @returns Promise resolving to items list or null
2522
+ * @example
2523
+ * ```typescript
2524
+ * const recent = await bot.webapi.item.getRecent(15);
2525
+ * ```
2526
+ */
2527
+ getRecent(limit?: number): Promise<ItemsListResponse | null>;
2528
+
2529
+ /**
2530
+ * Get purchasable items (convenience method)
2531
+ * @param query - Search query (optional)
2532
+ * @param limit - Maximum number of results (default: 20, max: 100)
2533
+ * @returns Promise resolving to purchasable items only
2534
+ * @example
2535
+ * ```typescript
2536
+ * const purchasableHats = await bot.webapi.item.getPurchasable('hat');
2537
+ * ```
2538
+ */
2539
+ getPurchasable(query?: string, limit?: number): Promise<ItemsSearchResponse | null>;
2540
+
2541
+ /**
2542
+ * Get tradable items (convenience method)
2543
+ * @param query - Search query (optional)
2544
+ * @param limit - Maximum number of results (default: 20, max: 100)
2545
+ * @returns Promise resolving to tradable items only
2546
+ * @example
2547
+ * ```typescript
2548
+ * const tradableItems = await bot.webapi.item.getTradable('', 50);
2549
+ * ```
2550
+ */
2551
+ getTradable(query?: string, limit?: number): Promise<ItemsSearchResponse | null>;
2552
+
2553
+ /**
2554
+ * Get purchasable items by category (convenience method)
2555
+ * @param category - Item category to filter by
2556
+ * @param limit - Maximum number of results (default: 20, max: 100)
2557
+ * @returns Promise resolving to purchasable items only
2558
+ * @example
2559
+ * ```typescript
2560
+ * const purchasableShirts = await bot.webapi.item.getPurchasableByCategory(ItemCategory.SHIRT);
2561
+ * ```
2562
+ */
2563
+ getPurchasableByCategory(category: ItemCategory, limit?: number): Promise<ItemsListResponse | null>;
2564
+
2565
+ /**
2566
+ * Get tradable items by category (convenience method)
2567
+ * @param category - Item category to filter by
2568
+ * @param limit - Maximum number of results (default: 20, max: 100)
2569
+ * @returns Promise resolving to tradable items only
2570
+ * @example
2571
+ * ```typescript
2572
+ * const tradableHats = await bot.webapi.item.getTradableByCategory(ItemCategory.HAT);
2573
+ * ```
2574
+ */
2575
+ getTradableByCategory(category: ItemCategory, limit?: number): Promise<ItemsListResponse | null>;
2576
+ }
2577
+
2578
+ grab: {
2579
+ /**
2580
+ * Get detailed grab information from Highrise Web API
2581
+ * @param grabId - Grab ID to lookup
2582
+ * @returns Promise resolving to detailed grab data or null if not found
2583
+ * @throws {TypeError} If grabId is not a non-empty string
2584
+ * @example
2585
+ * ```typescript
2586
+ * const grab = await bot.webapi.grab.get('grab_123456');
2587
+ *
2588
+ * // Example response includes:
2589
+ * // - Complete grab details with all rewards and costs
2590
+ * // - Kompu reward system data
2591
+ * // - Limited time offers
2592
+ * // - Progress-based rewards
2593
+ * // - Item metadata and NFI information
2594
+ *
2595
+ * console.log(`🎁 ${grab.title}`);
2596
+ * console.log(`📝 ${grab.description}`);
2597
+ * console.log(`🖼️ Banner: ${grab.bannerImgUrl}`);
2598
+ *
2599
+ * // Process rewards
2600
+ * grab.rewards.forEach(reward => {
2601
+ * console.log(`🎯 Reward: ${reward.amount}x ${reward.rewardId}`);
2602
+ * if (reward.itemId) console.log(` Item: ${reward.itemId}`);
2603
+ * console.log(` Bound: ${reward.accountBound}, Tradable: ${reward.isTradable}`);
2604
+ * });
2605
+ *
2606
+ * // Process costs
2607
+ * grab.costs.forEach(cost => {
2608
+ * console.log(`💰 Cost: ${cost.amount}x ${cost.rewardId}`);
2609
+ * });
2610
+ * ```
2611
+ */
2612
+ get(grabId: string): Promise<Grab | null>;
2613
+ }
2614
+ }
2615
+
2616
+
2617
+ declare class MovementCache {
2618
+ /**
2619
+ * Get user data by either userId or username
2620
+ * Automatically detects identifier type
2621
+ *
2622
+ * @param identifier - User ID (e.g., '68a7dd5eecae68acca580f41') or username (e.g., 'Unfairly')
2623
+ * @returns Cached user data or null if not found
2624
+ *
2625
+ * @example
2626
+ * // Get user position by ID
2627
+ * const userData = bot.cache.position.get('68a7dd5eecae68acca580f41');
2628
+ *
2629
+ * // Get user position by username
2630
+ * const userData = bot.cache.position.get('Unfairly');
2631
+ *
2632
+ * // Check if user is in cache
2633
+ * const isCached = bot.cache.position.get(userId) !== null;
2634
+ */
2635
+ get(identifier: string): CachedUser | null;
2636
+
2637
+ /**
2638
+ * Get all players within a square area centered at a point
2639
+ * @param center - Center point coordinates {x, y, z}
2640
+ * @param sideLength - Length of each side of the square
2641
+ * @returns Array of users with their positions and cache data
2642
+ * @example
2643
+ * ```typescript
2644
+ * // Get players in 8x8 square centered at (10, 0, 10)
2645
+ * const players = bot.cache.position.getPlayersInSquare(
2646
+ * { x: 10, y: 0, z: 10 },
2647
+ * 8
2648
+ * );
2649
+ *
2650
+ * players.forEach(player => {
2651
+ * console.log(`${player.user.username} at (${player.position.x}, ${player.position.z})`);
2652
+ * });
2653
+ * ```
2654
+ */
2655
+ getPlayersInSquare(center: Position, sideLength: number): SpatialUser[];
2656
+
2657
+ /**
2658
+ * Get all players within a rectangular area defined by four corners
2659
+ * @param corners - Object containing four corner coordinates
2660
+ * @returns Array of users with their positions and cache data
2661
+ * @example
2662
+ * ```typescript
2663
+ * // Get players in 10x10 rectangle
2664
+ * const players = bot.cache.position.getPlayersInRectangle({
2665
+ * c1: { x: 5, z: 5 },
2666
+ * c2: { x: 15, z: 5 },
2667
+ * c3: { x: 15, z: 15 },
2668
+ * c4: { x: 5, z: 15 }
2669
+ * });
2670
+ *
2671
+ * // Check if specific user is in area
2672
+ * const targetUser = players.find(p => p.user.id === '68a7dd5eecae68acca580f41');
2673
+ * if (targetUser) {
2674
+ * await bot.message.send(`${targetUser.user.username} is in the designated area!`);
2675
+ * }
2676
+ * ```
2677
+ */
2678
+ getPlayersInRectangle(corners: RectangleCorners): SpatialUser[];
2679
+
2680
+ /**
2681
+ * Get all players within a circular area
2682
+ * @param center - Center point coordinates {x, z}
2683
+ * @param radius - Radius of the circular area
2684
+ * @returns Array of users sorted by distance from center (closest first)
2685
+ * @example
2686
+ * ```typescript
2687
+ * // Get players within 5 units radius of center (10, 10)
2688
+ * const players = bot.cache.position.getPlayersInCircle(
2689
+ * { x: 10, z: 10 },
2690
+ * 5
2691
+ * );
2692
+ *
2693
+ * // Get the closest player to center
2694
+ * const closestPlayer = players[0];
2695
+ * if (closestPlayer) {
2696
+ * console.log(`Closest player: ${closestPlayer.user.username} (${closestPlayer.distance} units)`);
2697
+ * }
2698
+ *
2699
+ * // Filter players within specific distance
2700
+ * const nearbyPlayers = players.filter(p => p.distance <= 3);
2701
+ * ```
2702
+ */
2703
+ getPlayersInCircle(center: { x: number; z: number }, radius: number): SpatialUserWithDistance[];
2704
+
2705
+ /**
2706
+ * Get players within a specific Y-level range (vertical filtering)
2707
+ * @param minY - Minimum Y coordinate
2708
+ * @param maxY - Maximum Y coordinate
2709
+ * @returns Array of users within the vertical range
2710
+ * @example
2711
+ * ```typescript
2712
+ * // Get players on ground level (Y between -1 and 1)
2713
+ * const groundPlayers = bot.cache.position.getPlayersInVerticalRange(-1, 1);
2714
+ *
2715
+ * // Get players on upper floors (Y > 5)
2716
+ * const upperFloorPlayers = bot.cache.position.getPlayersInVerticalRange(5, 50);
2717
+ * ```
2718
+ */
2719
+ getPlayersInVerticalRange(minY: number, maxY: number): SpatialUser[];
2720
+
2721
+ /**
2722
+ * Get the closest player to a specified point
2723
+ * @param point - Reference point coordinates {x, z}
2724
+ * @returns The closest player or null if no players in cache
2725
+ * @example
2726
+ * ```typescript
2727
+ * // Find closest player to bot's position
2728
+ * const closest = bot.cache.position.getClosestPlayer({ x: 10, z: 10 });
2729
+ * if (closest) {
2730
+ * await bot.whisper.send(closest.user.id, `You're the closest player to me!`);
2731
+ * }
2732
+ * ```
2733
+ */
2734
+ getClosestPlayer(point: { x: number; z: number }): SpatialUserWithDistance | null;
2735
+
2736
+ /**
2737
+ * Get players sorted by distance from a point
2738
+ * @param point - Reference point coordinates {x, z}
2739
+ * @param maxDistance - Optional maximum distance filter
2740
+ * @returns Array of players sorted by distance (closest first)
2741
+ * @example
2742
+ * ```typescript
2743
+ * // Get all players sorted by distance from spawn
2744
+ * const sortedPlayers = bot.cache.position.getPlayersByDistance(
2745
+ * { x: 0, z: 0 }
2746
+ * );
2747
+ *
2748
+ * // Get players within 10 units, sorted
2749
+ * const nearbyPlayers = bot.cache.position.getPlayersByDistance(
2750
+ * { x: 10, z: 10 },
2751
+ * 10
2752
+ * );
2753
+ * ```
2754
+ */
2755
+ getPlayersByDistance(point: { x: number; z: number }, maxDistance?: number): SpatialUserWithDistance[];
2756
+
2757
+ /**
2758
+ * Check if a specific player is within a square area
2759
+ * @param userId - User ID to check
2760
+ * @param center - Center point of the square
2761
+ * @param sideLength - Side length of the square
2762
+ * @returns True if player is within the area
2763
+ * @example
2764
+ * ```typescript
2765
+ * // Check if specific user is in dance floor area
2766
+ * const isOnDanceFloor = bot.cache.position.isPlayerInSquare(
2767
+ * '68a7dd5eecae68acca580f41',
2768
+ * { x: 10, y: 0, z: 10 },
2769
+ * 8
2770
+ * );
2771
+ *
2772
+ * if (isOnDanceFloor) {
2773
+ * await bot.player.emote('68a7dd5eecae68acca580f41', 'dance');
2774
+ * }
2775
+ * ```
2776
+ */
2777
+ isPlayerInSquare(userId: string, center: Position, sideLength: number): boolean;
2778
+
2779
+ /**
2780
+ * Check if a specific player is within a rectangular area
2781
+ * @param userId - User ID to check
2782
+ * @param corners - Rectangle corner coordinates
2783
+ * @returns True if player is within the area
2784
+ * @example
2785
+ * ```typescript
2786
+ * const isInVIPArea = bot.cache.position.isPlayerInRectangle(
2787
+ * '68a7dd5eecae68acca580f41',
2788
+ * {
2789
+ * c1: { x: 20, z: 20 },
2790
+ * c2: { x: 25, z: 20 },
2791
+ * c3: { x: 25, z: 25 },
2792
+ * c4: { x: 20, z: 25 }
2793
+ * }
2794
+ * );
2795
+ * ```
2796
+ */
2797
+ isPlayerInRectangle(userId: string, corners: RectangleCorners): boolean;
2798
+
2799
+ /**
2800
+ * Get the number of players in a square area
2801
+ * @param center - Center point of the square
2802
+ * @param sideLength - Side length of the square
2803
+ * @returns Number of players in the area
2804
+ * @example
2805
+ * ```typescript
2806
+ * // Count players in spawn area
2807
+ * const playerCount = bot.cache.position.getPlayerCountInSquare(
2808
+ * { x: 0, y: 0, z: 0 },
2809
+ * 10
2810
+ * );
2811
+ * await bot.message.send(`There are ${playerCount} players at spawn!`);
2812
+ * ```
2813
+ */
2814
+ getPlayerCountInSquare(center: Position, sideLength: number): number;
2815
+
2816
+ /**
2817
+ * Get the number of players in a rectangular area
2818
+ * @param corners - Rectangle corner coordinates
2819
+ * @returns Number of players in the area
2820
+ */
2821
+ getPlayerCountInRectangle(corners: RectangleCorners): number;
2822
+ }
2823
+
2824
+ declare class InventoryClass {
2825
+ /**
2826
+ * Get the bot's inventory items
2827
+ * @returns Promise resolving to array of inventory items
2828
+ * @example
2829
+ * ```typescript
2830
+ * const items = await bot.inventory.get();
2831
+ * console.log(items);
2832
+ * ```
2833
+ */
2834
+ get(): Promise<GetInventoryResponse[]>;
2835
+
2836
+ /**
2837
+ * Outfit management
2838
+ */
2839
+ public outfit: {
2840
+ /**
2841
+ * Set the bot's outfit with specified items
2842
+ * @param outfit - Array of outfit items to wear (default: default skin)
2843
+ * @returns Promise resolving to operation success status
2844
+ * @example
2845
+ * ```typescript
2846
+ * // Set default outfit
2847
+ * await bot.inventory.outfit.set();
2848
+ *
2849
+ * // Set custom outfit
2850
+ * await bot.inventory.outfit.set([
2851
+ * {
2852
+ * type: 'clothing',
2853
+ * amount: 1,
2854
+ * id: 'shirt-n_cooltshirt',
2855
+ * account_bound: false,
2856
+ * active_palette: null
2857
+ * },
2858
+ * {
2859
+ * type: 'clothing',
2860
+ * amount: 1,
2861
+ * id: 'pants-n_jeans',
2862
+ * account_bound: false,
2863
+ * active_palette: null
2864
+ * }
2865
+ * ]);
2866
+ * ```
2867
+ */
2868
+ set(outfit?: Array<Outfit>): Promise<boolean>;
2869
+ }
2870
+
2871
+ /**
2872
+ * Wallet management for the bot's economy
2873
+ */
2874
+ public wallet: {
2875
+ /**
2876
+ * Get the bot's wallet information in a structured format
2877
+ * @returns Promise resolving to organized wallet data
2878
+ * @example
2879
+ * ```typescript
2880
+ * // access to specific currencies
2881
+ * const wallet = await bot.inventory.wallet.get();
2882
+ * console.log(`Gold: ${wallet.gold}`);
2883
+ * console.log(`Boost tokens: ${wallet.boost_tokens}`);
2884
+ * console.log(`Voice tokens: ${wallet.voice_tokens}`);
2885
+ *
2886
+ * // Use in economy checks
2887
+ * if (wallet.gold >= 100) {
2888
+ * await bot.player.tip('68a7dd5eecae68acca580f41', 100);
2889
+ * }
2890
+ * ```
2891
+ */
2892
+ get(): Promise<WalletResponse>;
2893
+ }
2894
+
2895
+ public boost: {
2896
+ /**
2897
+ * Buy room boosts
2898
+ * @param payment_method - Payment method to use (default: 'bot_wallet_only')
2899
+ * @param amount - Number of boosts to buy (default: 1)
2900
+ * @returns Promise resolving to purchase result
2901
+ * @example
2902
+ * ```typescript
2903
+ * const result = await bot.inventory.boost.buy('bot_wallet_only', 1);
2904
+ * if (result === 'success') {
2905
+ * console.log('Boost purchased successfully');
2906
+ * }
2907
+ * ```
2908
+ */
2909
+ buy(payment_method?: PaymentMethods, amount?: number): Promise<string>
2910
+ }
2911
+
2912
+ public voice: {
2913
+ /**
2914
+ * Buy room voice token
2915
+ * @param payment_method - Payment method to use (default: 'bot_wallet_only')
2916
+ * @param amount - Number of voice tokens to buy (default: 1)
2917
+ * @returns Promise resolving to purchase result
2918
+ * @example
2919
+ * ```typescript
2920
+ * const result = await bot.inventory.voice.buy('bot_wallet_only', 1);
2921
+ * if (result === 'success') {
2922
+ * console.log('Voice token purchased successfully');
2923
+ * }
2924
+ * ```
2925
+ */
2926
+ buy(payment_method?: PaymentMethods): Promise<string>
2927
+ }
2928
+
2929
+ public item: {
2930
+ /**
2931
+ * Buy an item from the shop
2932
+ * @param item_id - The ID of the item to purchase
2933
+ * @returns Promise resolving to purchase result
2934
+ * @example
2935
+ * ```typescript
2936
+ * const result = await bot.shop.item.buy('item_123');
2937
+ * if (result === 'success') {
2938
+ * console.log('Item purchased successfully');
2939
+ * }
2940
+ * ```
2941
+ */
2942
+ buy(item_id: string): Promise<string>
2943
+ }
2944
+ }
2945
+
2946
+ declare class MessageClass {
2947
+ /**
2948
+ * Send a message to the Highrise room (visible to all users in the room)
2949
+ * @param message - The message to send to the Highrise room
2950
+ * @throws {Error} If message is empty, too long, or contains invalid characters
2951
+ * @example
2952
+ * // Send a simple message
2953
+ * await bot.message.send("Hello everyone!");
2954
+ *
2955
+ * // Send a welcome message
2956
+ * await bot.message.send("Welcome to the room! 🎉");
2957
+ *
2958
+ * // Send a command announcement
2959
+ * await bot.message.send("Type !help for available commands");
2960
+ */
2961
+ send(message: string): Promise<boolean>;
2962
+ }
2963
+
2964
+ declare class WhisperClass {
2965
+ /**
2966
+ * Send a private whisper message to a specific user in the Highrise room
2967
+ * @param user_id - The user ID to send the whisper to
2968
+ * @param message - The private message to send
2969
+ * @throws {Error} If user_id is invalid or message is empty/too long
2970
+ * @example
2971
+ * // Send a private notification
2972
+ * await bot.whisper.send("68a7dd5eecae68acca580f41", "Your item has been delivered! Check your inventory.");
2973
+ */
2974
+ send(user_id: string, message: string): Promise<boolean>;
2975
+ }
2976
+
2977
+
2978
+ declare class DirectClass {
2979
+
2980
+ /**
2981
+ * Send a direct message to a specific user using the conversation_id
2982
+ * @param conversation_id - The conversation ID to send the message in
2983
+ * @param message - The direct message to send
2984
+ * @throws {Error} If conversation_id is invalid or message is empty/too long
2985
+ * @example
2986
+ * // Send a direct notification
2987
+ * await bot.direct.send("1_on_1:68a7dd5eecae68acca580f41:68a7dd5eecae68acca580f41", "Your item has been delivered! Check your inventory.");
2988
+ */
2989
+ send(conversation_id: string, message: string): Promise<boolean>;
2990
+
2991
+ /**
2992
+ * Send a direct message to a specific user using array of ID
2993
+ * @param user_Ids - Array of IDs to send the message to
2994
+ * @param message - The direct message to send
2995
+ * @throws {Error} If user_Ids is not array or less than 0 or bigger than 100 or message is empty/too long
2996
+ * @example
2997
+ * // Send a bulk direct notification
2998
+ * await bot.direct.bulkSend(['692125c2521b7580234d0f35', '68a7dd5eecae68acca580f41'], "Your item has been delivered! Check your inventory.");
2999
+ */
3000
+ bulkSend(user_Ids: string[], message: string): Promise<boolean>;
3001
+
3002
+ /**
3003
+ * Send a room or world invitation to a conversation
3004
+ * @param conversation_id - The conversation ID to send the invitation to
3005
+ * @param options - Invitation options (must provide exactly one of room_id or world_id)
3006
+ * @returns Promise resolving to operation success status
3007
+ * @throws {TypeError} If conversation_id is invalid or options don't contain exactly one valid option
3008
+ * @example
3009
+ * ```typescript
3010
+ * // Send room invitation
3011
+ * await bot.direct.invite('1_on_1:user1:user2', { room_id: '692125c2521b7580234d0f35' });
3012
+ *
3013
+ * // Send world invitation
3014
+ * await bot.direct.invite('1_on_1:user1:user2', { world_id: 'world_123456' });
3015
+ *
3016
+ * // This will throw an error (no options provided):
3017
+ * await bot.direct.invite('1_on_1:user1:user2', {});
3018
+ *
3019
+ * // This will throw an error (both options provided):
3020
+ * await bot.direct.invite('1_on_1:user1:user2', {
3021
+ * room_id: 'room_123',
3022
+ * world_id: 'world_456'
3023
+ * });
3024
+ * ```
3025
+ */
3026
+ invite(conversation_id: string, options: InviteOptions): Promise<boolean>;
3027
+
3028
+ /**
3029
+ * Send a room or world invitation to a conversation
3030
+ * @param user_Ids - Array of IDs to send the invitation to
3031
+ * @param options - Invitation options (must provide exactly one of room_id or world_id)
3032
+ * @returns Promise resolving to operation success status
3033
+ * @throws {TypeError} If user_Ids is not array or less than 0 or bigger than 100 or options don't contain exactly one valid option
3034
+ * @example
3035
+ * ```typescript
3036
+ * // Send bulk room invitation
3037
+ * await bot.direct.bulkInvite(['692125c2521b7580234d0f35', '68a7dd5eecae68acca580f41'], { room_id: '692125c2521b7580234d0f35' });
3038
+ *
3039
+ * // Send bulk world invitation
3040
+ * await bot.direct.bulkInvite(['692125c2521b7580234d0f35', '68a7dd5eecae68acca580f41'], { world_id: 'world_123456' });
3041
+ *
3042
+ * // This will throw an error (no options provided):
3043
+ * await bot.direct.bulkInvite(['692125c2521b7580234d0f35', '68a7dd5eecae68acca580f41'], {});
3044
+ *
3045
+ * // This will throw an error (both options provided):
3046
+ * await bot.direct.bulkInvite(['692125c2521b7580234d0f35', '68a7dd5eecae68acca580f41'], {
3047
+ * room_id: 'room_123',
3048
+ * world_id: 'world_456'
3049
+ * });
3050
+ * ```
3051
+ */
3052
+ bulkInvite(user_Ids: string[], options: InviteOptions): Promise<boolean>;
3053
+
3054
+ /**
3055
+ * Conversations management for direct messaging
3056
+ */
3057
+ public conversations: {
3058
+ /**
3059
+ * Get the conversations of the bot
3060
+ * @param last_id - Last conversation in the list, used to get the next 20 conversations
3061
+ * @param not_joined - If true, only returns conversations that bot has not joined yet
3062
+ * @returns Array of conversation responses
3063
+ * @example
3064
+ * // Get first 20 conversations
3065
+ * const conversations = await bot.direct.conversations.get();
3066
+ *
3067
+ * // Get next 20 conversations using last_id
3068
+ * const nextConversations = await bot.direct.conversations.get(conversations[19].id);
3069
+ *
3070
+ * // Get only unjoined conversations
3071
+ * const unjoined = await bot.direct.conversations.get(undefined, true);
3072
+ */
3073
+ get(last_id?: string, not_joined?: boolean): Promise<GetConversationsResponse[]>;
3074
+
3075
+ /**
3076
+ * Leave a conversation using conversation_id
3077
+ * @param conversation_id - Conversation id to leave from
3078
+ * @example
3079
+ * await bot.direct.conversations.leave('1_on_1:68a7dd5eecae68acca580f41:68a7dd5eecae68acca580f41');
3080
+ */
3081
+ leave(conversation_id: string): Promise<boolean>;
3082
+ }
3083
+
3084
+ /**
3085
+ * Messages management within conversations
3086
+ */
3087
+ public messages: {
3088
+ /**
3089
+ * Get the messages of a conversation
3090
+ * @param conversation_id - Conversation id to get the messages from
3091
+ * @param last_message_id - Last message id to get the next 20 messages
3092
+ * @returns Array of message responses
3093
+ * @example
3094
+ * // Get first 20 messages from a conversation
3095
+ * const messages = await bot.direct.messages.get('1_on_1:68a7dd5eecae68acca580f41:68a7dd5eecae68acca580f41');
3096
+ *
3097
+ * // Get next 20 messages using last_message_id
3098
+ * const nextMessages = await bot.direct.messages.get('1_on_1:68a7dd5eecae68acca580f41:68a7dd5eecae68acca580f41', messages[19].id);
3099
+ */
3100
+ get(conversation_id: string, last_message_id?: string): Promise<GetMessagesResponse[]>;
3101
+ }
3102
+ }
3103
+
3104
+ declare class PlayerClass {
3105
+
3106
+ /**
3107
+ * Walk the player to specified coordinates with optional facing direction
3108
+ * @param x - The x coordinate to walk to
3109
+ * @param y - The y coordinate to walk to
3110
+ * @param z - The z coordinate to walk to
3111
+ * @param facing - The direction the player should face after walking (default: 'FrontRight')
3112
+ * @throws {TypeError} If any coordinate is missing or invalid types are provided
3113
+ * @example
3114
+ * await bot.player.walk(10, 5, 15, 'FrontLeft');
3115
+ */
3116
+ walk(x: number, y: number, z: number, facing?: Facing): Promise<boolean>;
3117
+
3118
+ /**
3119
+ * Make the bot sit on an anchor
3120
+ * @param entity_id - The entity ID of the anchor
3121
+ * @param anchor_ix - The anchor index (default: 0)
3122
+ * @returns Promise resolving to operation success status
3123
+ * @example
3124
+ * ```typescript
3125
+ * const success = await bot.player.sit('chair_entity_id', 0);
3126
+ * ```
3127
+ */
3128
+ sit(entity_id: string, anchor_ix?: number): Promise<boolean>;
3129
+
3130
+ /**
3131
+ * Teleport a user to specified coordinates with optional facing direction
3132
+ * @param user_id - The user ID of the player to teleport
3133
+ * @param x - The x coordinate to teleport to
3134
+ * @param y - The y coordinate to teleport to
3135
+ * @param z - The z coordinate to teleport to
3136
+ * @param facing - The direction the player should face after teleporting (default: 'FrontRight')
3137
+ * @throws {TypeError} If user_id is missing or coordinates are invalid
3138
+ * @example
3139
+ * await bot.player.teleport('68a7dd5eecae68acca580f41', 20, 10, 30, 'BackLeft');
3140
+ */
3141
+ teleport(user_id: string, x: number, y: number, z: number, facing?: Facing): Promise<boolean>;
3142
+
3143
+ /**
3144
+ * Play an emote on a user
3145
+ * @param emote_id - The ID of the emote to play
3146
+ * @param user_id - The user ID to play the emote on (default: current bot user)
3147
+ * @throws {TypeError} If user_id or emote_id are missing or invalid
3148
+ * @example
3149
+ * // Play emote on bot
3150
+ * await bot.player.emote('dance');
3151
+ *
3152
+ * // Play emote on specific user
3153
+ * await bot.player.emote('wave', '68a7dd5eecae68acca580f41');
3154
+ */
3155
+ emote(emote_id: string, user_id?: string | undefined): Promise<boolean>;
3156
+
3157
+ /**
3158
+ * Send a reaction to a user
3159
+ * @param user_id - The user ID to send the reaction to
3160
+ * @param reaction - The reaction type to send (must be one of: 'clap', 'heart', 'thumbs', 'wave', 'wink')
3161
+ * @throws {TypeError} If user_id or reaction are missing or invalid
3162
+ * @throws {Error} If reaction is not one of the valid reactions
3163
+ * @example
3164
+ * await bot.player.react('68a7dd5eecae68acca580f41', 'clap');
3165
+ * await bot.player.react('68a7dd5eecae68acca580f41', 'heart');
3166
+ */
3167
+ react(user_id: string, reaction: Reactions): Promise<boolean>;
3168
+
3169
+ /**
3170
+ * Transport a user to another room
3171
+ * @param user_id - The user ID to transport to another room
3172
+ * @param room_id - The destination room ID
3173
+ * @throws {TypeError} If user_id or room_id are missing or invalid
3174
+ * @throws {Error} If attempting to transport the bot itself
3175
+ * @example
3176
+ * // Transport a user to another room
3177
+ * await bot.player.transport('68a7dd5eecae68acca580f41', '692125c2521b7580234d0f35');
3178
+ *
3179
+ * // This will throw an error:
3180
+ * // await bot.player.transport(bot.info.user.id, '692125c2521b7580234d0f35');
3181
+ */
3182
+ transport(user_id: string, room_id: string): Promise<boolean>;
3183
+
3184
+ /**
3185
+ * Send a tip to a user
3186
+ * @param user_id - The user ID to tip (must be a non-empty string)
3187
+ * @param gold_bar - The amount of gold bars to tip (must be a number between 1 and 10,000 and a valid gold bar amount)
3188
+ * @throws {TypeError} When user_id is not a string or not in room, or gold_bar is invalid
3189
+ * @throws {Error} When the tip operation fails
3190
+ */
3191
+ tip(user_id: string, gold_bar?: Goldbars): Promise<boolean>;
3192
+
3193
+ /**
3194
+ * Player Outfit management
3195
+ */
3196
+ public outfit: {
3197
+ /**
3198
+ * Get a user's current outfit
3199
+ * @param user_id - The user ID to get the outfit for
3200
+ * @returns Promise resolving to array of outfit items
3201
+ * @example
3202
+ * ```typescript
3203
+ * // Get user's outfit
3204
+ * const outfit = await bot.player.outfit.get('68a7dd5eecae68acca580f41');
3205
+ * console.log(outfit);
3206
+ * // [
3207
+ * // {
3208
+ * // type: 'clothing',
3209
+ * // amount: 1,
3210
+ * // id: 'shirt-n_cooltshirt',
3211
+ * // account_bound: false,
3212
+ * // active_palette: null
3213
+ * // },
3214
+ * // ...
3215
+ * // ]
3216
+ * ```
3217
+ */
3218
+ get(user_id: string): Promise<GetUserOutfitResponse[]>;
3219
+ }
3220
+
3221
+ /**
3222
+ * Moderation actions for room management
3223
+ */
3224
+ public moderation: {
3225
+ /**
3226
+ * Kick a user from the room
3227
+ * @param user_id - The user ID of the user to kick
3228
+ * @throws {TypeError} If user_id is missing or invalid
3229
+ * @example
3230
+ * await bot.player.moderation.kick('68a7dd5eecae68acca580f41');
3231
+ */
3232
+ kick(user_id: string): Promise<boolean>;
3233
+
3234
+ /**
3235
+ * Ban a user from the room for a specified duration
3236
+ * @param user_id - The user ID of the user to ban
3237
+ * @param duration - Ban duration in milliseconds (default: 1 hour)
3238
+ * @throws {TypeError} If user_id is missing or duration is invalid
3239
+ * @example
3240
+ * // Ban for 1 hour (default)
3241
+ * await bot.player.moderation.ban('68a7dd5eecae68acca580f41');
3242
+ *
3243
+ * // Ban for 30 minutes
3244
+ * await bot.player.moderation.ban('68a7dd5eecae68acca580f41', 30 * 60 * 1000);
3245
+ *
3246
+ * // Ban for 1 day
3247
+ * await bot.player.moderation.ban('68a7dd5eecae68acca580f41', 24 * 60 * 60 * 1000);
3248
+ */
3249
+ ban(user_id: string, duration?: number): Promise<boolean>;
3250
+
3251
+ /**
3252
+ * Mute a user in the room for a specified duration
3253
+ * @param user_id - The user ID of the user to mute
3254
+ * @param duration - Mute duration in milliseconds (default: 5 minutes)
3255
+ * @throws {TypeError} If user_id is missing or duration is invalid
3256
+ * @example
3257
+ * // Mute for 5 minutes (default)
3258
+ * await bot.player.moderation.mute('68a7dd5eecae68acca580f41');
3259
+ *
3260
+ * // Mute for 1 hour
3261
+ * await bot.player.moderation.mute('68a7dd5eecae68acca580f41', 60 * 60 * 1000);
3262
+ */
3263
+ mute(user_id: string, duration?: number): Promise<boolean>;
3264
+
3265
+ /**
3266
+ * Unmute a previously muted user in the room
3267
+ * @param user_id - The user ID of the user to unmute
3268
+ * @throws {TypeError} If user_id is missing or invalid
3269
+ * @example
3270
+ * await bot.player.moderation.unmute('68a7dd5eecae68acca580f41');
3271
+ */
3272
+ unmute(user_id: string): Promise<boolean>;
3273
+
3274
+ /**
3275
+ * Unban a previously banned user from the room
3276
+ * @param user_id - The user ID of the user to unban
3277
+ * @throws {TypeError} If user_id is missing or invalid
3278
+ * @example
3279
+ * await bot.player.moderation.unban('68a7dd5eecae68acca580f41');
3280
+ */
3281
+ unban(user_id: string): Promise<boolean>;
3282
+ }
3283
+ }
3284
+
3285
+ declare class Logger {
3286
+ /**
3287
+ * Generic log method for custom log levels
3288
+ * @param level - The log level
3289
+ * @param method - The method name where the log originated
3290
+ * @param message - The main log message
3291
+ * @param data - Optional data object to include in the log
3292
+ * @example
3293
+ * logger.log('CUSTOM', 'myMethod', 'Custom log message', { userId: '68a7dd5eecae68acca580f41' });
3294
+ */
3295
+ log(level: string, method: string, message: string, data?: any): void;
3296
+
3297
+ /**
3298
+ * Log a success message (green color)
3299
+ * @param method - The method name where the log originated
3300
+ * @param message - The success message
3301
+ * @param data - Optional data object to include in the log
3302
+ * @example
3303
+ * logger.success('walk', 'Successfully walked to destination', { x: 10, y: 5, z: 15 });
3304
+ */
3305
+ success(method: string, message: string, data?: any): void;
3306
+
3307
+ /**
3308
+ * Log an error message (red color)
3309
+ * @param method - The method name where the log originated
3310
+ * @param message - The error message
3311
+ * @param data - Optional data object to include in the log
3312
+ * @example
3313
+ * logger.error('teleport', 'Failed to teleport user', { userId: '68a7dd5eecae68acca580f41', error: 'Invalid coordinates' });
3314
+ */
3315
+ error(method: string, message: string, data?: any): void;
3316
+
3317
+ /**
3318
+ * Log a warning message (yellow color)
3319
+ * @param method - The method name where the log originated
3320
+ * @param message - The warning message
3321
+ * @param data - Optional data object to include in the log
3322
+ * @example
3323
+ * logger.warn('moderation.ban', 'User was banned', { userId: '68a7dd5eecae68acca580f41', duration: 3600000 });
3324
+ */
3325
+ warn(method: string, message: string, data?: any): void;
3326
+
3327
+ /**
3328
+ * Log an info message (blue color)
3329
+ * @param method - The method name where the log originated
3330
+ * @param message - The info message
3331
+ * @param data - Optional data object to include in the log
3332
+ * @example
3333
+ * logger.info('emote', 'Playing emote for user', { userId: '68a7dd5eecae68acca580f41', emoteId: 'dance' });
3334
+ */
3335
+ info(method: string, message: string, data?: any): void;
3336
+
3337
+ /**
3338
+ * Log a debug message (magenta color)
3339
+ * @param method - The method name where the log originated
3340
+ * @param message - The debug message
3341
+ * @param data - Optional data object to include in the log
3342
+ * @example
3343
+ * logger.debug('react', 'Validating reaction parameters', { userId: '68a7dd5eecae68acca580f41', reaction: 'wave' });
3344
+ */
3345
+ debug(method: string, message: string, data?: any): void;
3346
+ }
3347
+
3348
+ interface BotUtils {
3349
+ /**
3350
+ * Logger instance for structured, color-coded logging throughout the application
3351
+ * Provides different log levels (SUCCESS, ERROR, WARN, INFO, DEBUG) with timestamps and method tracking
3352
+ *
3353
+ * @example
3354
+ * // Basic logging
3355
+ * bot.utils.logger.info('connection', 'Bot connected successfully');
3356
+ * bot.utils.logger.error('auth', 'Authentication failed', { userId: '68a7dd5eecae68acca580f41' });
3357
+ *
3358
+ * // With different levels
3359
+ * bot.utils.logger.success('payment', 'Payment processed');
3360
+ * bot.utils.logger.warn('moderation', 'User warning issued');
3361
+ * bot.utils.logger.debug('websocket', 'Message received', { type: message._type });
3362
+ */
3363
+ logger: Logger;
3364
+
3365
+ /**
3366
+ * Utility method to create a delay/pause in execution
3367
+ * Returns a Promise that resolves after the specified time, useful for rate limiting,
3368
+ * artificial delays, or waiting between methods
3369
+ *
3370
+ * @param ms - Delay duration in milliseconds
3371
+ * @returns Promise that resolves after the specified delay
3372
+ *
3373
+ * @example
3374
+ * // Basic delay
3375
+ * await bot.utils.sleep(1000); // Wait 1 second
3376
+ *
3377
+ * // Rate limiting between messages
3378
+ * await bot.message.send("First message");
3379
+ * await bot.utils.sleep(500); // Wait 500ms
3380
+ * await bot.message.send("Second message");
3381
+ *
3382
+ * // Artificial delay for user experience
3383
+ * await bot.utils.sleep(2000); // Wait 2 seconds before response
3384
+ * await bot.message.send("Processing complete!");
3385
+ *
3386
+ * // In loops with delays
3387
+ * for (let i = 0; i < 5; i++) {
3388
+ * await bot.message.send(`Message ${i + 1}`);
3389
+ * await bot.utils.sleep(1000); // Wait 1 second between messages
3390
+ * }
3391
+ */
3392
+ sleep(ms: number): Promise<boolean>;
3393
+
3394
+ DanceFloor: DanceFloor
3395
+
3396
+ /**
3397
+ * Creates a new CooldownManager instance with empty cooldown collections.
3398
+ */
3399
+ cooldown: CooldownManager
3400
+
3401
+ /**
3402
+ * Role-based permission management with Web API auto-sync
3403
+ */
3404
+ permissions: RoleManager;
3405
+ }
3406
+
3407
+ declare class RoomClass {
3408
+ /**
3409
+ * Room privilege methods
3410
+ */
3411
+ public privilege: {
3412
+ /**
3413
+ * Get room privilege of a specific user
3414
+ * @param user_id - The user ID to check privilege for
3415
+ * @returns Promise resolving to user privileges
3416
+ * @example
3417
+ * ```typescript
3418
+ * const privileges = await bot.room.privilege.get('68a7dd5eecae68acca580f41');
3419
+ * console.log(privileges.moderator); // true/false
3420
+ * console.log(privileges.designer); // true/false
3421
+ * ```
3422
+ */
3423
+ get(user_id: string): Promise<GetRoomPrivilegeResponse>;
3424
+
3425
+ /**
3426
+ * Check if a user is a moderator in the room
3427
+ * @param user_id - The user ID to check
3428
+ * @returns Promise resolving to boolean indicating moderator status
3429
+ * @example
3430
+ * ```typescript
3431
+ * const isMod = await bot.room.privilege.isModerator('68a7dd5eecae68acca580f41');
3432
+ * if (isMod) {
3433
+ * console.log('User is a moderator');
3434
+ * }
3435
+ * ```
3436
+ */
3437
+ isModerator(user_id: string): Promise<boolean>;
3438
+
3439
+ /**
3440
+ * Check if a user is a designer in the room
3441
+ * @param user_id - The user ID to check
3442
+ * @returns Promise resolving to boolean indicating designer status
3443
+ * @example
3444
+ * ```typescript
3445
+ * const isDesigner = await bot.room.privilege.isDesigner('68a7dd5eecae68acca580f41');
3446
+ * if (isDesigner) {
3447
+ * console.log('User is a designer');
3448
+ * }
3449
+ * ```
3450
+ */
3451
+ isDesigner(user_id: string): Promise<boolean>;
3452
+ }
3453
+
3454
+ /**
3455
+ * Designer privilege management
3456
+ */
3457
+ public designer: {
3458
+ /**
3459
+ * Add designer privileges to a user
3460
+ * @param user_id - The user ID to grant designer privileges to
3461
+ * @returns Promise resolving to operation success status
3462
+ * @example
3463
+ * ```typescript
3464
+ * const success = await bot.room.designer.add('68a7dd5eecae68acca580f41');
3465
+ * if (success) {
3466
+ * console.log('User is now a designer');
3467
+ * }
3468
+ * ```
3469
+ */
3470
+ add(user_id: string): Promise<boolean>;
3471
+
3472
+ /**
3473
+ * Remove designer privileges from a user
3474
+ * @param user_id - The user ID to remove designer privileges from
3475
+ * @returns Promise resolving to operation success status
3476
+ * @example
3477
+ * ```typescript
3478
+ * const success = await bot.room.designer.remove('68a7dd5eecae68acca580f41');
3479
+ * if (success) {
3480
+ * console.log('User is no longer a designer');
3481
+ * }
3482
+ * ```
3483
+ */
3484
+ remove(user_id: string): Promise<boolean>;
3485
+ }
3486
+
3487
+ /**
3488
+ * Moderator privilege management
3489
+ */
3490
+ public moderator: {
3491
+ /**
3492
+ * Add moderator privileges to a user
3493
+ * @param user_id - The user ID to grant moderator privileges to
3494
+ * @returns Promise resolving to operation success status
3495
+ * @example
3496
+ * ```typescript
3497
+ * const success = await bot.room.moderator.add('68a7dd5eecae68acca580f41');
3498
+ * if (success) {
3499
+ * console.log('User is now a moderator');
3500
+ * }
3501
+ * ```
3502
+ */
3503
+ add(user_id: string): Promise<boolean>;
3504
+
3505
+ /**
3506
+ * Remove moderator privileges from a user
3507
+ * @param user_id - The user ID to remove moderator privileges from
3508
+ * @returns Promise resolving to operation success status
3509
+ * @example
3510
+ * ```typescript
3511
+ * const success = await bot.room.moderator.remove('68a7dd5eecae68acca580f41');
3512
+ * if (success) {
3513
+ * console.log('User is no longer a moderator');
3514
+ * }
3515
+ * ```
3516
+ */
3517
+ remove(user_id: string): Promise<boolean>;
3518
+ }
3519
+
3520
+ /**
3521
+ * Room user management methods
3522
+ */
3523
+ public users: {
3524
+ /**
3525
+ * Get all users currently in the room
3526
+ * @returns Promise resolving to array of users with their positions
3527
+ * @example
3528
+ * ```typescript
3529
+ * const users = await bot.room.users.get();
3530
+ * ```
3531
+ */
3532
+ get(): Promise<Array<[
3533
+ User,
3534
+ Position
3535
+ ]>>;
3536
+
3537
+ /**
3538
+ * Get user ID by username
3539
+ * @param username - The username to look up
3540
+ * @returns Promise resolving to user ID
3541
+ * @example
3542
+ * ```typescript
3543
+ * const userId = await bot.room.users.id('Unfairly');
3544
+ * ```
3545
+ */
3546
+ id(username: string): Promise<string> | null;
3547
+
3548
+ /**
3549
+ * Get username by user ID
3550
+ * @param id - The user ID to look up
3551
+ * @returns Promise resolving to username
3552
+ * ```typescript
3553
+ * const username = await bot.room.users.username('692118c325513614015cddbf');
3554
+ * ```
3555
+ */
3556
+ username(id: string): Promise<string> | null;
3557
+
3558
+ /**
3559
+ * Get user position by username or user ID
3560
+ * @param identifier - Username or user ID
3561
+ * @returns Promise resolving to user position
3562
+ * @example
3563
+ * ```typescript
3564
+ * const pos = await bot.room.users.position('Unfairly');
3565
+ * const pos = await bot.room.users.position('692118c325513614015cddbf');
3566
+ * ```
3567
+ */
3568
+ position(identifier: string): Promise<Position | AnchorPosition>;
3569
+ }
3570
+
3571
+ /**
3572
+ * Room voice chat methods
3573
+ */
3574
+ public voice: {
3575
+ /**
3576
+ * Check the current voice chat status in the room (valid only if the bot were created on the room owner account)
3577
+ * @returns Promise resolving an Object for success check or message on failed
3578
+ * @example
3579
+ * ```typescript
3580
+ * const status = await bot.room.voice.check();
3581
+ *
3582
+ * // if success
3583
+ * console.log(status.autoSpeakersId) // [ '6734bf...', '68a73d...' ]
3584
+ *
3585
+ * if failed
3586
+ * console.log(status.message)
3587
+ * ```
3588
+ */
3589
+ check(): Promise<ValidVoiceCheck | InvalidVoiceCheck>
3590
+
3591
+ /**
3592
+ * Invite a user to speak in voice chat
3593
+ * @param user_id - The user ID to invite as speaker
3594
+ * @returns Promise resolving to operation success status
3595
+ * @example
3596
+ * ```typescript
3597
+ * const success = await bot.room.voice.invite('68a7dd5eecae68acca580f41');
3598
+ * ```
3599
+ */
3600
+ invite(user_id: string): Promise<boolean>;
3601
+
3602
+ /**
3603
+ * Remove a user from voice chat speakers
3604
+ * @param user_id - The user ID to remove from speakers
3605
+ * @returns Promise resolving to operation success status
3606
+ * @example
3607
+ * ```typescript
3608
+ * const success = await bot.room.voice.remove('68a7dd5eecae68acca580f41');
3609
+ * ```
3610
+ */
3611
+ remove(user_id: string): Promise<boolean>;
3612
+ }
3613
+ }
3614
+
3615
+ /**
3616
+ * Logger configuration - controls how bot messages appear in console
3617
+ */
3618
+ interface LoggerOptions {
3619
+ /** Show time in logs? (true = [2023-10-05T14:30:00.68a7dd5eecae68acca580f41Z] [INFO]) */
3620
+ showTimestamp?: boolean;
3621
+ /** Show method name? (true = [connect]: Connected) */
3622
+ showMethodName?: boolean;
3623
+ /** Use colors? (true = green success, red errors) */
3624
+ colors?: boolean;
3625
+ }
3626
+
3627
+ /**
3628
+ * Bot connection settings - controls how bot handles disconnections
3629
+ */
3630
+ interface HighriseOptions {
3631
+ /** How logs look in console */
3632
+ LoggerOptions?: LoggerOptions;
3633
+ /** Wait time between reconnect tries (milliseconds) */
3634
+ reconnectDelay: number;
3635
+ /** Auto-reconnect if disconnected? */
3636
+ autoReconnect: boolean;
3637
+ /** Custom roles to create on startup */
3638
+ customRoles?: string[];
3639
+ }
3640
+
3641
+ /**
3642
+ * Configuration options for request senders
3643
+ */
3644
+ interface SenderConfig {
3645
+ /**
3646
+ * Default timeout for requests waiting in milliseconds (default: 10000ms)
3647
+ */
3648
+ defaultTimeout?: number;
3649
+
3650
+ /**
3651
+ * Maximum number of retry attempts for failed requests (default: 2)
3652
+ */
3653
+ maxRetries?: number;
3654
+
3655
+ /**
3656
+ * Delay between retry attempts in milliseconds (default: 100)
3657
+ */
3658
+ retryDelay?: number;
3659
+ }
3660
+
3661
+ declare class Highrise {
3662
+ /**
3663
+ * Creates a new Highrise bot instance
3664
+ * @param Events - Array of event names to listen for
3665
+ * @param options - Configuration options for the bot
3666
+ */
3667
+ constructor(Events: EventType[], options?: HighriseOptions);
3668
+
3669
+ /** Public message actions */
3670
+ public message: MessageClass;
3671
+
3672
+ /** Private whisper actions */
3673
+ public whisper: WhisperClass;
3674
+
3675
+ /** Direct message and conversation actions */
3676
+ public direct: DirectClass;
3677
+
3678
+ /** Player movement and interaction actions */
3679
+ public player: PlayerClass;
3680
+
3681
+ /** Bot information and state */
3682
+ public info: BotInformation;
3683
+
3684
+ /** Utility methods and tools for bot development and management */
3685
+ public utils: BotUtils;
3686
+
3687
+ /** Room methods and management */
3688
+ public room: RoomClass;
3689
+
3690
+ /** Inventory management operations */
3691
+ public inventory: InventoryClass;
3692
+
3693
+ /** WebAPI Class for external Highrise API calls */
3694
+ public webapi: WebApi
3695
+
3696
+ /** Await system for waiting for specific events with filters */
3697
+ public await: AwaitClass
3698
+
3699
+ /**
3700
+ * Hidden channel forbot-to-bot communication
3701
+ * Allows sending and receiving messages between all bots in the room
3702
+ *
3703
+ * @example
3704
+ * ```typescript
3705
+ * // Send to channel
3706
+ * await bot.channel.send('Hello other bots!', ['greeting']);
3707
+ *
3708
+ * // Listen for messages
3709
+ * bot.channel.on(['greeting'], (data) => {
3710
+ * console.log(`Bot ${data.senderId} says: ${data.message}`);
3711
+ * });
3712
+ * ```
3713
+ */
3714
+ public channel: Channel;
3715
+
3716
+ /**
3717
+ * Cache management system for efficient data storage and retrieval
3718
+ * Provides optimized memory usage and fast lookups for frequently accessed data
3719
+ */
3720
+ public cache: {
3721
+ /**
3722
+ * Movement cache for efficient user position tracking
3723
+ * Automatically handles position changes and memory optimization
3724
+ */
3725
+ position: MovementCache
3726
+ }
3727
+
3728
+ /**
3729
+ * Authenticate and connect the bot to a Highrise room
3730
+ * @param token - Bot authentication token (64 characters)
3731
+ * @param room_id - Room ID to connect to (24 characters)
3732
+ * @throws {Error} If token, room_id, or events are invalid
3733
+ * @example
3734
+ * await bot.login('your_64_character_bot_token_here', 'room_id_24_characters_long');
3735
+ */
3736
+ login(token: string, room_id: string): Promise<void>;
3737
+
3738
+ /**
3739
+ * Manually disconnect the WebSocket connection and disable auto-reconnect
3740
+ * Performs graceful shutdown by:
3741
+ * - Disabling auto-reconnection
3742
+ * - Cleaning up intervals and timeouts
3743
+ * - Closing the WebSocket connection with code 1000 (normal closure)
3744
+ * - Resetting connection state
3745
+ *
3746
+ * @example
3747
+ * // Gracefully disconnect from Highrise
3748
+ * bot.disconnect();
3749
+ *
3750
+ * // Example in a cleanup scenario
3751
+ * process.on('SIGINT', () => {
3752
+ * console.log('Shutting down gracefully...');
3753
+ * bot.disconnect();
3754
+ * process.exit(0);
3755
+ * });
3756
+ *
3757
+ * @throws {Error} If there are issues during the cleanup process
3758
+ * @emits Various cleanup events during the disconnection process
3759
+ */
3760
+ disconnect(): void;
3761
+
3762
+ /**
3763
+ * Return system metrics
3764
+ * Shows real-time statistics about bot performance, cache usage, and connection status
3765
+ */
3766
+ getMetrics(): MetricData
3767
+
3768
+ /**
3769
+ * Configures the request/response and fire-and-forget senders
3770
+ * @param config - Configuration object for sender behavior
3771
+ * @example
3772
+ * ```typescript
3773
+ * // Configure with custom timeout and retries
3774
+ * bot.configureSenders({
3775
+ * defaultTimeout: 15000, // 15 second timeout
3776
+ * maxRetries: 3, // 3 retry attempts
3777
+ * retryDelay: 200 // 200ms between retries
3778
+ * });
3779
+ *
3780
+ * // Configure only timeout
3781
+ * bot.configureSenders({
3782
+ * defaultTimeout: 5000 // 5 second timeout only
3783
+ * });
3784
+ *
3785
+ * // Reset to defaults (empty config)
3786
+ * bot.configureSenders();
3787
+ * ```
3788
+ * @throws {Error} If configuration values are outside valid ranges
3789
+ */
3790
+ configureSenders(config?: SenderConfig): void;
3791
+
3792
+ /**
3793
+ * Register an event listener
3794
+ * @param event - Event name to listen for
3795
+ * @param listener - Async callback function to handle the event
3796
+ * @returns The Highrise instance for chaining
3797
+ */
3798
+ on<K extends keyof EventMap>(event: K, listener: (...args: EventMap[K]) => Promise<void>): this;
3799
+ on(event: string, listener: (...args: any[]) => Promise<void>): this;
3800
+
3801
+ /**
3802
+ * Register a one-time event listener
3803
+ * @param event - Event name to listen for
3804
+ * @param listener - Async callback function to handle the event
3805
+ * @returns The Highrise instance for chaining
3806
+ */
3807
+ once<K extends keyof EventMap>(event: K, listener: (...args: EventMap[K]) => Promise<void>): this;
3808
+ once(event: string, listener: (...args: any[]) => Promise<void>): this;
3809
+
3810
+ /**
3811
+ * Emit an event
3812
+ * @param event - Event name to emit
3813
+ * @param args - Arguments to pass to event listeners
3814
+ * @returns True if the event had listeners, false otherwise
3815
+ */
3816
+ emit<K extends keyof EventMap>(event: K, ...args: EventMap[K]): boolean;
3817
+ emit(event: string, ...args: any[]): boolean;
3818
+ }
3819
+
3820
+ export { Highrise, WebApi }