@wavezfm/api 0.1.9 → 0.2.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 (38) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +31 -9
  3. package/dist/index.d.ts +216 -30
  4. package/dist/index.js.map +1 -1
  5. package/dist/realtime/roomBot.js +39 -0
  6. package/dist/realtime/roomBot.js.map +1 -1
  7. package/dist/resources/billing.d.ts +80 -1
  8. package/dist/resources/billing.js +32 -0
  9. package/dist/resources/billing.js.map +1 -1
  10. package/dist/resources/chat.d.ts +3 -1
  11. package/dist/resources/chat.js +19 -0
  12. package/dist/resources/chat.js.map +1 -1
  13. package/dist/resources/friend.d.ts +1 -12
  14. package/dist/resources/friend.js +3 -18
  15. package/dist/resources/friend.js.map +1 -1
  16. package/dist/resources/playlist.d.ts +33 -8
  17. package/dist/resources/playlist.js +29 -3
  18. package/dist/resources/playlist.js.map +1 -1
  19. package/dist/resources/room.d.ts +32 -3
  20. package/dist/resources/room.js +53 -6
  21. package/dist/resources/room.js.map +1 -1
  22. package/dist/resources/roomBot.d.ts +6 -1
  23. package/dist/resources/roomBot.js +7 -2
  24. package/dist/resources/roomBot.js.map +1 -1
  25. package/dist/resources/settings.d.ts +52 -2
  26. package/dist/resources/settings.js +32 -0
  27. package/dist/resources/settings.js.map +1 -1
  28. package/dist/resources/shop.d.ts +5 -0
  29. package/dist/resources/shop.js +3 -0
  30. package/dist/resources/shop.js.map +1 -1
  31. package/dist/resources/source.d.ts +6 -6
  32. package/dist/resources/source.js +6 -3
  33. package/dist/resources/source.js.map +1 -1
  34. package/dist/resources/system.d.ts +3 -1
  35. package/dist/resources/system.js +6 -0
  36. package/dist/resources/system.js.map +1 -1
  37. package/dist/types.d.ts +197 -3
  38. package/package.json +3 -2
package/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0
4
+
5
+ ### Added
6
+
7
+ - Chat image uploads and media previews.
8
+ - External room media validation, metadata, Google Drive helpers, room leave, playback history, deletion, audit-log clearing, and word filters.
9
+ - Playlist search, ordering, availability checks, JSON import/export, track clipping, recent-room filtering, and paginated media search.
10
+ - GIF favorites, Last.fm account flows, Discord role sync, and social-image settings.
11
+ - Subscription management, payment history, miscellaneous checkout, Mercado Pago, and room subscription gifts.
12
+ - Notification center status and clearing.
13
+ - Room-bot word filters and superfans.
14
+
15
+ ### Fixed
16
+
17
+ - Unwrapped room detail responses so `room.getBySlug()` and slug-based joins return the actual room.
18
+ - Corrected paginated media search, playlist mutation, user settings, and checkout response types to match the server.
19
+
20
+ ### Removed
21
+
22
+ - Obsolete friend-request methods whose server routes no longer exist. Fan and superfan methods remain under `client.friend` for compatibility.
package/README.md CHANGED
@@ -159,6 +159,9 @@ await client.settings.update({
159
159
  presenceStatus: "busy",
160
160
  showChatBadge: true,
161
161
  });
162
+ await client.settings.getGifFavorites();
163
+ await client.settings.replaceGifFavorites(favorites);
164
+ const lastFm = await client.settings.getLastFmAccount();
162
165
  await client.settings.getTwoFactor();
163
166
  await client.settings.startEmailTwoFactor({ password: "secret" });
164
167
  await client.settings.startAuthenticatorTwoFactor({ password: "secret" });
@@ -183,8 +186,11 @@ await client.room.getBySlug("wavezfm-lounge");
183
186
  await client.room.getWaitlist("wavezfm-lounge");
184
187
  await client.room.create({ slug: "my-room", name: "My Room" });
185
188
  await client.room.join("wavezfm-lounge");
189
+ await client.room.leave("room-id");
186
190
  await client.room.favorite("room-id");
187
191
  await client.room.getManagement("room-id");
192
+ await client.room.getPlaybackHistory("room-id", 40);
193
+ await client.room.validateExternalMedia("https://youtu.be/...");
188
194
  ```
189
195
 
190
196
  #### Playlists
@@ -194,12 +200,19 @@ await client.playlist.list();
194
200
  await client.playlist.create("My Playlist");
195
201
  await client.playlist.update("playlist-id", { name: "Late Night Set" });
196
202
  await client.playlist.getTracks("playlist-id");
203
+ await client.playlist.searchTracks("nightcore");
197
204
  await client.playlist.previewUrl("https://youtube.com/watch?v=dQw4w9WgXcQ");
198
205
  await client.playlist.addTrack("playlist-id", {
199
206
  source: "youtube",
200
207
  sourceId: "dQw4w9WgXcQ",
201
208
  });
202
209
  await client.playlist.reorderTracks("playlist-id", ["track-a", "track-b"]);
210
+ await client.playlist.updateTrackClip("playlist-id", "track-id", {
211
+ clipStartMs: 15_000,
212
+ clipEndMs: 90_000,
213
+ });
214
+ await client.playlist.exportJson("playlist-id");
215
+ await client.playlist.importJson({ data: exportedPlaylist });
203
216
  await client.playlist.startSpotifyImport({
204
217
  playlistId: "playlist-id",
205
218
  url: "https://open.spotify.com/playlist/...",
@@ -209,7 +222,8 @@ await client.playlist.startSpotifyImport({
209
222
  #### Sources
210
223
 
211
224
  ```ts
212
- await client.source.searchYouTube("lofi hip hop", 10);
225
+ const youtube = await client.source.searchYouTube("lofi hip hop", 10);
226
+ console.log(youtube.data.items, youtube.data.nextPageToken);
213
227
  await client.source.searchSoundCloud("nightcore", 10);
214
228
  await client.source.searchAll("ambient");
215
229
  ```
@@ -219,6 +233,8 @@ await client.source.searchAll("ambient");
219
233
  ```ts
220
234
  await client.chat.getMessages("room-id", 0, 50);
221
235
  await client.chat.getMessagesBySlug("wavezfm-lounge", 0, 50);
236
+ await client.chat.previewMedia("https://prnt.sc/...");
237
+ await client.chat.uploadImage(imageBlob, "cover.webp");
222
238
  await client.chat.updateMessage("room-id", "message-id", {
223
239
  content: "edited message",
224
240
  });
@@ -226,15 +242,13 @@ await client.chat.pinMessage("room-id", "message-id");
226
242
  await client.chat.clearChat("room-id");
227
243
  ```
228
244
 
229
- #### Friends / Fans
245
+ #### Fans
230
246
 
231
247
  ```ts
232
- await client.friend.list();
233
- await client.friend.pending();
234
- await client.friend.sendRequest("user-id");
235
- await client.friend.acceptRequest("request-id");
236
248
  await client.friend.follow("user-id");
237
249
  await client.friend.followers();
250
+ await client.friend.following();
251
+ await client.friend.superfans();
238
252
  ```
239
253
 
240
254
  #### Shop
@@ -251,6 +265,9 @@ await client.shop.getInventory();
251
265
 
252
266
  ```ts
253
267
  await client.billing.createSubscriptionCheckout({ cycle: "monthly" });
268
+ await client.billing.getCheckoutSessionStatus("cs_test_...");
269
+ await client.billing.cancelSubscription();
270
+ await client.billing.resumeSubscription();
254
271
  await client.billing.createDiamondCheckout({ quantity: 1000 });
255
272
  await client.billing.createRoomDonationCheckout("room-id", { amountCents: 500 });
256
273
  await client.billing.createGlobalDonationCheckout({ amountCents: 1000 });
@@ -266,6 +283,8 @@ await client.billing.listPendingGifts();
266
283
  ```ts
267
284
  await client.system.status();
268
285
  await client.system.publicStats();
286
+ await client.system.getNotificationCenterStatus();
287
+ await client.system.clearNotificationCenter();
269
288
  await client.system.health();
270
289
  ```
271
290
 
@@ -312,7 +331,7 @@ Important:
312
331
  ### Bot Resources
313
332
 
314
333
  ```ts
315
- client.api.setRoomBotToken(process.env.WAVEZ_ROOM_BOT_TOKEN!);
334
+ client.api.setRoomBotToken(process.env.WAVEZFM_ROOM_BOT_TOKEN!);
316
335
 
317
336
  await client.roomBot.getState("room-id");
318
337
  await client.roomBot.getQueueStatus("room-id");
@@ -335,6 +354,9 @@ await client.roomBot.updateSettings("room-id", {
335
354
  actorUsername: "Night Shift Bot",
336
355
  },
337
356
  });
357
+ await client.roomBot.updateWordFilters("room-id", {
358
+ blockedWordPatterns: ["spam"],
359
+ });
338
360
 
339
361
  const state = await client.roomBot.getState("room-id");
340
362
  console.log(state.data.room?.description);
@@ -365,7 +387,7 @@ import {
365
387
 
366
388
  const bot = createRoomBotRealtimeClient({
367
389
  baseURL: "https://api.wavez.fm",
368
- botToken: process.env.WAVEZ_ROOM_BOT_TOKEN!,
390
+ botToken: process.env.WAVEZFM_ROOM_BOT_TOKEN!,
369
391
  roomId: "room-id",
370
392
  locale: "en",
371
393
  autoReconnect: true,
@@ -421,7 +443,7 @@ try {
421
443
  const client = createApiClient({ baseURL: "https://api.wavez.fm" });
422
444
 
423
445
  client.api.setAuthToken("optional-bearer-token");
424
- client.api.setRoomBotToken(process.env.WAVEZ_ROOM_BOT_TOKEN!);
446
+ client.api.setRoomBotToken(process.env.WAVEZFM_ROOM_BOT_TOKEN!);
425
447
 
426
448
  client.api.getAuthToken();
427
449
  client.api.getRoomBotToken();
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export { createRoomBotResource } from "./resources/roomBot.js";
15
15
  export { parseRoomQueueSnapshot } from "./utils/roomQueue.js";
16
16
  export { formatMentionText } from "./utils/chat.js";
17
17
  export { createRoomBotRealtimeClient } from "./realtime/roomBot.js";
18
- export type { ApiClientConfig, ApiLike, ApiQuery, ApiQueryValue, ApiRequestOptions, ApiSuccessResponse, AuthMode, AuthUser, BadgeAssignment, ChatMessage, CheckoutSessionResponse, InventoryResponse, InventoryCatalogEntry, InventoryCatalogItem, MediaSearchResult, PlaylistSummary, PlaylistTrack, RoomBotPermission, RoomQueueEntry, RoomQueuePlayback, RoomQueueSnapshot, RoomQueueStatusResponse, RoomQueueUser, RoomQueueViewerStatus, RoomBotEditMessageInput, RoomBotMessageReplyInput, RoomBotEventsResponse, RoomPresenceEventFilterType, RoomBotQueueAddResponse, RoomBotRealtimeClient, RoomBotRealtimeOptions, RoomBotSendMessageInput, RoomBotState, RoomBotToken, RoomPresenceEvent, RoomPresenceEventType, RoomSummary, WavezApiLocale, WavezApiMessageKey, WavezApiMessages, WavezApiMessageValues, StoreCatalogResponse, StoreCatalogItem, StoreCatalogSection, SystemDonationGoal, SystemPublicStats, SystemStatus, TwoFactorStatus, UserSettings, UserProfile, WalletBalance, WebSocketLike, WsPacket, } from "./types.js";
18
+ export type { ApiClientConfig, ApiLike, ApiQuery, ApiQueryValue, ApiRequestOptions, ApiSuccessResponse, AuthMode, AuthUser, BadgeAssignment, ChatImageUploadResponse, ChatMediaPreviewResponse, ChatMessage, CheckoutSessionResponse, GifFavorite, InventoryResponse, InventoryCatalogEntry, InventoryCatalogItem, LastFmAccountProfile, LastFmLinkStatus, LastFmWriteResponse, MediaSearchResponse, MediaSearchResult, NotificationCenterClearResponse, NotificationCenterStatus, PlaylistJsonExport, PlaylistJsonImportResult, PlaylistJsonTrack, PlaylistSummary, PlaylistTrack, PlaylistTrackAvailabilityInput, PlaylistTrackAvailabilityResult, PlaylistTrackSearchResult, RoomBotPermission, RoomExternalMediaMetadataResponse, RoomExternalMediaProvider, RoomExternalMediaSubtitleTrack, RoomExternalMediaValidationResponse, RoomPlaybackHistoryEntry, RoomQueueEntry, RoomQueuePlayback, RoomQueueSnapshot, RoomQueueStatusResponse, RoomQueueUser, RoomQueueViewerStatus, RoomBotEditMessageInput, RoomBotMessageReplyInput, RoomBotEventsResponse, RoomPresenceEventFilterType, RoomBotQueueAddResponse, RoomBotRealtimeClient, RoomBotRealtimeOptions, RoomBotSendMessageInput, RoomBotState, RoomBotToken, RoomPresenceEvent, RoomPresenceEventType, RoomSummary, WavezApiLocale, WavezApiMessageKey, WavezApiMessages, WavezApiMessageValues, StoreCatalogResponse, StoreCatalogItem, StoreCatalogSection, MiscStoreItem, SystemDonationGoal, SystemPublicStats, SystemStatus, TwoFactorStatus, UserSettings, UserProfile, WalletBalance, WebSocketLike, WsPacket, } from "./types.js";
19
19
  import type { ApiClientConfig } from "./types.js";
20
20
  export declare function createApiClient(config: ApiClientConfig): {
21
21
  api: import("./core/api.js").WavezApi;
@@ -57,14 +57,64 @@ export declare function createApiClient(config: ApiClientConfig): {
57
57
  get(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").UserSettings>>;
58
58
  update(input: {
59
59
  bio?: string;
60
+ countryCode?: string;
61
+ colorTheme?: "wavezfm" | "wavezfm-black";
60
62
  timeFormat?: "12h" | "24h";
61
63
  notifyChatMentions?: boolean;
64
+ notifyFanToasts?: boolean;
62
65
  playMentionSound?: boolean;
66
+ playWhisperSound?: boolean;
63
67
  lastFmScrobblingEnabled?: boolean;
64
- presenceStatus?: "online" | "busy" | "away";
68
+ presenceStatus?: "online" | "busy" | "away" | "invisible";
65
69
  selectedBadgeIds?: string[];
66
70
  showChatBadge?: boolean;
71
+ showFanRelationsOnProfile?: boolean;
72
+ showSuperfansOnProfile?: boolean;
73
+ showOnlineRoomOnProfile?: boolean;
74
+ showLastSeenOnProfile?: boolean;
75
+ blockUnknownWhispers?: boolean;
76
+ autoOpenIncomingWhispers?: boolean;
77
+ sfwMode?: boolean;
78
+ sfwModeAudioEnabled?: boolean;
67
79
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").UserSettings>>;
80
+ getGifFavorites(): Promise<import("./types.js").ApiSuccessResponse<{
81
+ favorites: import("./types.js").GifFavorite[];
82
+ }>>;
83
+ replaceGifFavorites(favorites: import("./types.js").GifFavorite[]): Promise<import("./types.js").ApiSuccessResponse<{
84
+ favorites: import("./types.js").GifFavorite[];
85
+ }>>;
86
+ getLastFmConnectUrl(options?: {
87
+ successCallbackURL?: string;
88
+ errorCallbackURL?: string;
89
+ }): Promise<import("./types.js").ApiSuccessResponse<{
90
+ url: string;
91
+ }>>;
92
+ getLastFmLinkStatus(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").LastFmLinkStatus>>;
93
+ getLastFmAccount(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").LastFmAccountProfile>>;
94
+ disconnectLastFm(): Promise<import("./types.js").ApiSuccessResponse<{
95
+ success: true;
96
+ }>>;
97
+ submitLastFmNowPlaying(input: {
98
+ artist: string;
99
+ track: string;
100
+ durationSeconds?: number | null;
101
+ }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").LastFmWriteResponse>>;
102
+ submitLastFmScrobble(input: {
103
+ artist: string;
104
+ track: string;
105
+ durationSeconds?: number | null;
106
+ timestamp?: number | null;
107
+ }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").LastFmWriteResponse>>;
108
+ syncDiscordSubscriptionRole(): Promise<import("./types.js").ApiSuccessResponse<{
109
+ success: true;
110
+ }>>;
111
+ updateSocialImage(input: {
112
+ provider: "discord";
113
+ imageUrl: string;
114
+ }): Promise<import("./types.js").ApiSuccessResponse<{
115
+ updated: boolean;
116
+ applied: boolean;
117
+ }>>;
68
118
  getTwoFactor(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").TwoFactorStatus>>;
69
119
  sendPhoneVerification(input: {
70
120
  phoneNumber: string;
@@ -109,9 +159,24 @@ export declare function createApiClient(config: ApiClientConfig): {
109
159
  status: number;
110
160
  headers: Headers;
111
161
  }>;
112
- getBySlug(slug: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").RoomSummary>>;
162
+ getBySlug(slug: string): Promise<{
163
+ data: import("./types.js").RoomSummary;
164
+ status: number;
165
+ headers: Headers;
166
+ }>;
113
167
  getJoinPreview(slug: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
114
168
  getWaitlist(slug: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").RoomQueueStatusResponse>>;
169
+ getExternalMediaMetadata(url: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").RoomExternalMediaMetadataResponse>>;
170
+ validateExternalMedia(url: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").RoomExternalMediaValidationResponse>>;
171
+ getGoogleDriveSubtitle(input: {
172
+ id?: string;
173
+ url?: string;
174
+ format?: "srt" | "vtt";
175
+ }): Promise<import("./types.js").ApiSuccessResponse<string>>;
176
+ getGoogleDriveStreamUrl(input: {
177
+ id?: string;
178
+ url?: string;
179
+ }): string;
115
180
  getQueueStatus(slug: string, options?: {
116
181
  viewerUserId?: string | null;
117
182
  viewerPublicId?: number | null;
@@ -125,9 +190,17 @@ export declare function createApiClient(config: ApiClientConfig): {
125
190
  isPrivate?: boolean;
126
191
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").RoomSummary>>;
127
192
  join(roomIdOrSlug: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
193
+ leave(roomId: string): Promise<import("./types.js").ApiSuccessResponse<void>>;
128
194
  favorite(roomId: string): Promise<import("./types.js").ApiSuccessResponse<void>>;
129
195
  unfavorite(roomId: string): Promise<import("./types.js").ApiSuccessResponse<void>>;
130
196
  getManagement(roomId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
197
+ getPlaybackHistory(roomId: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<{
198
+ history: import("./types.js").RoomPlaybackHistoryEntry[];
199
+ }>>;
200
+ delete(roomId: string): Promise<import("./types.js").ApiSuccessResponse<{
201
+ success: true;
202
+ room: Record<string, unknown>;
203
+ }>>;
131
204
  createBotToken(roomId: string, input: {
132
205
  botName: string;
133
206
  botAvatarUrl?: string;
@@ -136,9 +209,10 @@ export declare function createApiClient(config: ApiClientConfig): {
136
209
  expiresInHours?: number;
137
210
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").RoomBotToken>>;
138
211
  listEmojis(roomId: string): Promise<import("./types.js").ApiSuccessResponse<unknown[]>>;
139
- listAuditLogs(roomId: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<{
212
+ listAuditLogs(roomId: string, limit?: number, page?: number): Promise<import("./types.js").ApiSuccessResponse<{
140
213
  logs: unknown[];
141
214
  }>>;
215
+ clearAuditLogs(roomId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
142
216
  updateSettings(roomId: string, input: Record<string, unknown>): Promise<import("./types.js").ApiSuccessResponse<{
143
217
  room: Record<string, unknown>;
144
218
  }>>;
@@ -149,6 +223,11 @@ export declare function createApiClient(config: ApiClientConfig): {
149
223
  }): Promise<import("./types.js").ApiSuccessResponse<{
150
224
  room: Record<string, unknown>;
151
225
  }>>;
226
+ updateWordFilters(roomId: string, input: {
227
+ blockedWordPatterns: string[];
228
+ }): Promise<import("./types.js").ApiSuccessResponse<{
229
+ room: Record<string, unknown>;
230
+ }>>;
152
231
  setRole(roomId: string, userId: string, role: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
153
232
  setQueueAccess(roomId: string, userId: string, blocked: boolean): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
154
233
  unban(roomId: string, userId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
@@ -158,19 +237,24 @@ export declare function createApiClient(config: ApiClientConfig): {
158
237
  };
159
238
  playlist: {
160
239
  list(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistSummary[]>>;
240
+ searchTracks(query: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistTrackSearchResult[]>>;
161
241
  create(input: {
162
242
  name: string;
163
243
  } | string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistSummary>>;
164
244
  update(playlistId: string, input: {
165
245
  name?: string;
166
246
  isActive?: boolean;
167
- }): Promise<import("./types.js").ApiSuccessResponse<{
168
- success: true;
169
- }>>;
247
+ }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistSummary>>;
248
+ reorder(playlistIds: string[]): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistSummary[]>>;
170
249
  remove(playlistId: string): Promise<import("./types.js").ApiSuccessResponse<{
171
250
  success: true;
172
251
  }>>;
173
- getTracks(playlistId: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistTrack[]>>;
252
+ getTracks(playlistId: string, options?: {
253
+ roomId?: string | null;
254
+ recentWindowMinutes?: number | null;
255
+ }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistTrack[]>>;
256
+ exportJson(playlistId: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistJsonExport>>;
257
+ checkTrackAvailability(items: import("./types.js").PlaylistTrackAvailabilityInput[]): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistTrackAvailabilityResult[]>>;
174
258
  previewUrl(url: string): Promise<import("./types.js").ApiSuccessResponse<{
175
259
  kind: "track";
176
260
  sourceId: string;
@@ -178,6 +262,7 @@ export declare function createApiClient(config: ApiClientConfig): {
178
262
  title: string;
179
263
  artist?: string;
180
264
  thumbnailUrl?: string | null;
265
+ isLive?: boolean;
181
266
  } | {
182
267
  kind: "playlist";
183
268
  importSource: string;
@@ -185,6 +270,8 @@ export declare function createApiClient(config: ApiClientConfig): {
185
270
  title: string;
186
271
  totalTracks: number;
187
272
  thumbnailUrl?: string | null;
273
+ totalDurationMs?: number | null;
274
+ tracks?: import("./types.js").PlaylistTrack[];
188
275
  truncated?: boolean;
189
276
  }>>;
190
277
  addTrack(playlistId: string, input: {
@@ -193,12 +280,25 @@ export declare function createApiClient(config: ApiClientConfig): {
193
280
  source?: string;
194
281
  title?: string;
195
282
  artist?: string;
196
- durationMs?: number;
283
+ durationMs?: number | null;
197
284
  thumbnailUrl?: string | null;
198
- }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistTrack>>;
285
+ isLive?: boolean | null;
286
+ clipStartMs?: number | null;
287
+ clipEndMs?: number | null;
288
+ insertAtTop?: boolean;
289
+ }): Promise<import("./types.js").ApiSuccessResponse<{
290
+ track: import("./types.js").PlaylistTrack;
291
+ progression: Record<string, unknown> | null;
292
+ }>>;
199
293
  reorderTracks(playlistId: string, trackIds: string[]): Promise<import("./types.js").ApiSuccessResponse<{
200
294
  success: true;
201
295
  }>>;
296
+ updateTrackClip(playlistId: string, trackId: string, input: {
297
+ clipStartMs?: number | null;
298
+ clipEndMs?: number | null;
299
+ }): Promise<import("./types.js").ApiSuccessResponse<{
300
+ track: import("./types.js").PlaylistTrack;
301
+ }>>;
202
302
  removeTrack(playlistId: string, trackId: string): Promise<import("./types.js").ApiSuccessResponse<{
203
303
  success: true;
204
304
  }>>;
@@ -216,23 +316,29 @@ export declare function createApiClient(config: ApiClientConfig): {
216
316
  playlistId: string;
217
317
  url: string;
218
318
  }): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
319
+ importJson(input: {
320
+ playlistId?: string | null;
321
+ data: unknown;
322
+ }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").PlaylistJsonImportResult>>;
219
323
  cancelImport(jobId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
220
- searchPreview(query: string, source?: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResult[]>>;
324
+ searchPreview(query: string, source?: string, limit?: number, pageToken?: string | null): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResponse>>;
221
325
  };
222
326
  source: {
223
- search(source: string, query: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResult[]>>;
224
- searchYouTube(query: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResult[]>>;
225
- searchSoundCloud(query: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResult[]>>;
327
+ search(source: string, query: string, limit?: number, pageToken?: string | null): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResponse>>;
328
+ searchYouTube(query: string, limit?: number, pageToken?: string | null): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResponse>>;
329
+ searchSoundCloud(query: string, limit?: number, pageToken?: string | null): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").MediaSearchResponse>>;
226
330
  searchAll(query: string, limit?: number): Promise<{
227
331
  data: {
228
- youtube: import("./types.js").MediaSearchResult[];
229
- soundcloud: import("./types.js").MediaSearchResult[];
332
+ youtube: import("./types.js").MediaSearchResponse;
333
+ soundcloud: import("./types.js").MediaSearchResponse;
230
334
  };
231
335
  status: number;
232
336
  headers: Headers;
233
337
  }>;
234
338
  };
235
339
  chat: {
340
+ previewMedia(url: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").ChatMediaPreviewResponse>>;
341
+ uploadImage(image: Blob | FormData, fileName?: string): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").ChatImageUploadResponse>>;
236
342
  getMessages(roomId: string, offset?: number, limit?: number): Promise<import("./types.js").ApiSuccessResponse<{
237
343
  history: boolean;
238
344
  pinnedMessage?: Record<string, unknown> | null;
@@ -259,18 +365,6 @@ export declare function createApiClient(config: ApiClientConfig): {
259
365
  }>>;
260
366
  };
261
367
  friend: {
262
- list(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").UserProfile[]>>;
263
- pending(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").UserProfile[]>>;
264
- sendRequest(userId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
265
- acceptRequest(requestId: string): Promise<import("./types.js").ApiSuccessResponse<{
266
- success: true;
267
- }>>;
268
- rejectRequest(requestId: string): Promise<import("./types.js").ApiSuccessResponse<{
269
- success: true;
270
- }>>;
271
- remove(friendshipId: string): Promise<import("./types.js").ApiSuccessResponse<{
272
- success: true;
273
- }>>;
274
368
  follow(userId: string): Promise<import("./types.js").ApiSuccessResponse<{
275
369
  success: true;
276
370
  }>>;
@@ -279,6 +373,7 @@ export declare function createApiClient(config: ApiClientConfig): {
279
373
  }>>;
280
374
  followers(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").UserProfile[]>>;
281
375
  following(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").UserProfile[]>>;
376
+ superfans(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").UserProfile[]>>;
282
377
  };
283
378
  shop: {
284
379
  getCatalog(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").StoreCatalogResponse>>;
@@ -287,56 +382,142 @@ export declare function createApiClient(config: ApiClientConfig): {
287
382
  itemId: string;
288
383
  idempotencyKey?: string;
289
384
  }): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
385
+ purchaseMisc(input: {
386
+ itemId: string;
387
+ idempotencyKey?: string;
388
+ displayUsername?: string | null;
389
+ }): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
290
390
  equip(itemId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
291
391
  getInventory(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").InventoryResponse>>;
292
392
  };
293
393
  billing: {
394
+ getCheckoutSessionStatus(sessionId: string): Promise<import("./types.js").ApiSuccessResponse<{
395
+ sessionId: string;
396
+ status: string | null;
397
+ paymentStatus: string | null;
398
+ kind: string | null;
399
+ cycle: "monthly" | "annual" | null;
400
+ }>>;
401
+ cancelSubscription(): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
402
+ resumeSubscription(): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
403
+ upgradeSubscription(input?: {
404
+ locale?: string | null;
405
+ }): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
406
+ listSubscriptionPaymentHistory(): Promise<import("./types.js").ApiSuccessResponse<unknown[]>>;
294
407
  createSubscriptionCheckout(input?: {
295
408
  cycle?: string | null;
296
409
  currency?: string | null;
410
+ locale?: string | null;
297
411
  returnPath?: string | null;
412
+ uiMode?: string | null;
413
+ provider?: string | null;
298
414
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
299
415
  createDiamondCheckout(input?: {
300
416
  quantity?: number;
301
417
  currency?: string | null;
418
+ locale?: string | null;
302
419
  returnPath?: string | null;
420
+ uiMode?: string | null;
421
+ provider?: string | null;
422
+ }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
423
+ createMiscShopCheckout(input: {
424
+ itemId: string;
425
+ roomSlug?: string | null;
426
+ username?: string | null;
427
+ displayUsername?: string | null;
428
+ locale?: string | null;
429
+ returnPath?: string | null;
430
+ uiMode?: string | null;
431
+ provider?: string | null;
303
432
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
304
433
  createRoomDonationCheckout(roomId: string, input?: {
305
434
  amountCents?: number;
435
+ currency?: string | null;
306
436
  locale?: string | null;
307
437
  returnPath?: string | null;
438
+ uiMode?: string | null;
439
+ provider?: string | null;
308
440
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
309
441
  createGlobalDonationCheckout(input?: {
310
442
  amountCents?: number;
443
+ currency?: string | null;
311
444
  locale?: string | null;
312
445
  returnPath?: string | null;
446
+ uiMode?: string | null;
447
+ provider?: string | null;
313
448
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
314
449
  createDiamondGiftCheckout(input: {
315
450
  recipientUsername: string;
316
451
  quantity?: number;
317
452
  currency?: string | null;
453
+ locale?: string | null;
318
454
  returnPath?: string | null;
319
455
  message?: string | null;
320
456
  anonymous?: boolean;
321
457
  announceInRoom?: boolean;
322
458
  announceRoomSlug?: string | null;
459
+ uiMode?: string | null;
323
460
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
324
461
  createSubscriptionGiftCheckout(input: {
325
- recipientUsername: string;
462
+ recipientUsername?: string | null;
463
+ recipientUserId?: string | null;
326
464
  cycle?: string | null;
327
465
  currency?: string | null;
466
+ locale?: string | null;
328
467
  returnPath?: string | null;
329
468
  message?: string | null;
330
469
  anonymous?: boolean;
331
470
  announceInRoom?: boolean;
332
471
  announceRoomSlug?: string | null;
472
+ uiMode?: string | null;
473
+ provider?: string | null;
333
474
  }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
475
+ createSubscriptionRoomGiftCheckout(input: {
476
+ roomSlug: string;
477
+ count?: number;
478
+ currency?: string | null;
479
+ locale?: string | null;
480
+ returnPath?: string | null;
481
+ message?: string | null;
482
+ anonymous?: boolean;
483
+ announceInRoom?: boolean;
484
+ uiMode?: string | null;
485
+ }): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").CheckoutSessionResponse>>;
486
+ createMercadoPagoPayment(input: {
487
+ kind: string;
488
+ cycle?: string | null;
489
+ quantity?: number;
490
+ amountCents?: number;
491
+ itemId?: string | null;
492
+ roomSlug?: string | null;
493
+ username?: string | null;
494
+ displayUsername?: string | null;
495
+ roomId?: string | null;
496
+ recipientUserId?: string | null;
497
+ currency?: string | null;
498
+ locale?: string | null;
499
+ returnPath?: string | null;
500
+ message?: string | null;
501
+ anonymous?: boolean;
502
+ announceInRoom?: boolean;
503
+ announceRoomSlug?: string | null;
504
+ formData?: Record<string, unknown> | null;
505
+ }): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
506
+ getMercadoPagoPaymentStatus(paymentId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
507
+ createMercadoPagoSubscription(input?: {
508
+ cycle?: string | null;
509
+ locale?: string | null;
510
+ returnPath?: string | null;
511
+ formData?: Record<string, unknown> | null;
512
+ }): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
334
513
  listPendingGifts(): Promise<import("./types.js").ApiSuccessResponse<unknown[]>>;
335
514
  markGiftSeen(giftId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
336
515
  };
337
516
  system: {
338
517
  status(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").SystemStatus>>;
339
518
  publicStats(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").SystemPublicStats>>;
519
+ getNotificationCenterStatus(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").NotificationCenterStatus>>;
520
+ clearNotificationCenter(): Promise<import("./types.js").ApiSuccessResponse<import("./types.js").NotificationCenterClearResponse>>;
340
521
  health(): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
341
522
  };
342
523
  roomBot: {
@@ -374,7 +555,7 @@ export declare function createApiClient(config: ApiClientConfig): {
374
555
  }>>;
375
556
  getManagement(roomId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
376
557
  listEmojis(roomId: string): Promise<import("./types.js").ApiSuccessResponse<unknown[]>>;
377
- listAuditLogs(roomId: string, limit?: number): Promise<import("./types.js").ApiSuccessResponse<{
558
+ listAuditLogs(roomId: string, limit?: number, page?: number): Promise<import("./types.js").ApiSuccessResponse<{
378
559
  logs: unknown[];
379
560
  }>>;
380
561
  updateSettings(roomId: string, input: Record<string, unknown>): Promise<import("./types.js").ApiSuccessResponse<{
@@ -387,6 +568,11 @@ export declare function createApiClient(config: ApiClientConfig): {
387
568
  }): Promise<import("./types.js").ApiSuccessResponse<{
388
569
  room: Record<string, unknown>;
389
570
  }>>;
571
+ updateWordFilters(roomId: string, input: {
572
+ blockedWordPatterns: string[];
573
+ }): Promise<import("./types.js").ApiSuccessResponse<{
574
+ room: Record<string, unknown>;
575
+ }>>;
390
576
  setRole(roomId: string, userId: string, role: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
391
577
  setQueueAccess(roomId: string, userId: string, blocked: boolean): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
392
578
  unban(roomId: string, userId: string): Promise<import("./types.js").ApiSuccessResponse<Record<string, unknown>>>;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AA0DpE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,UAAU,eAAe,CAAC,MAAuB;IACnD,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAE9B,OAAO;QACH,GAAG;QACH,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,QAAQ,EAAE,sBAAsB,CAAC,GAAG,CAAC;QACrC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,QAAQ,EAAE,sBAAsB,CAAC,GAAG,CAAC;QACrC,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC;QACjC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC;QACjC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC;QACnC,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC;QACjC,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC;KACtC,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AA+EpE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,UAAU,eAAe,CAAC,MAAuB;IACnD,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAE9B,OAAO;QACH,GAAG;QACH,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,QAAQ,EAAE,sBAAsB,CAAC,GAAG,CAAC;QACrC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,QAAQ,EAAE,sBAAsB,CAAC,GAAG,CAAC;QACrC,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC;QACjC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC;QACjC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAC7B,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC;QACnC,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC;QACjC,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC;KACtC,CAAC;AACN,CAAC"}