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.
- package/LICENSE +21 -0
- package/README.md +864 -0
- package/index.js +13 -0
- package/package.json +28 -0
- package/src/classes/Actions/Awaiter.js +202 -0
- package/src/classes/Actions/Channel.js +73 -0
- package/src/classes/Actions/Direct.js +263 -0
- package/src/classes/Actions/Inventory.js +156 -0
- package/src/classes/Actions/Music.js +278 -0
- package/src/classes/Actions/Player.js +377 -0
- package/src/classes/Actions/Public.js +66 -0
- package/src/classes/Actions/Room.js +333 -0
- package/src/classes/Actions/Utils.js +29 -0
- package/src/classes/Actions/lib/AudioStreaming.js +447 -0
- package/src/classes/Caches/MovementCache.js +357 -0
- package/src/classes/Handlers/AxiosErrorHandler.js +68 -0
- package/src/classes/Handlers/ErrorHandler.js +65 -0
- package/src/classes/Handlers/EventHandlers.js +259 -0
- package/src/classes/Handlers/WebSocketHandlers.js +54 -0
- package/src/classes/Managers/ChannelManager.js +303 -0
- package/src/classes/Managers/DanceFloorManagers.js +509 -0
- package/src/classes/Managers/Helpers/CleanupManager.js +130 -0
- package/src/classes/Managers/Helpers/LoggerManager.js +171 -0
- package/src/classes/Managers/Helpers/MetricsManager.js +83 -0
- package/src/classes/Managers/Networking/ConnectionManager.js +259 -0
- package/src/classes/Managers/Networking/CooldownManager.js +516 -0
- package/src/classes/Managers/Networking/EventsManager.js +64 -0
- package/src/classes/Managers/Networking/KeepAliveManager.js +109 -0
- package/src/classes/Managers/Networking/MessageHandler.js +110 -0
- package/src/classes/Managers/Networking/Request.js +329 -0
- package/src/classes/Managers/PermissionManager.js +288 -0
- package/src/classes/WebApi/Category/Grab.js +98 -0
- package/src/classes/WebApi/Category/Item.js +347 -0
- package/src/classes/WebApi/Category/Post.js +154 -0
- package/src/classes/WebApi/Category/Room.js +137 -0
- package/src/classes/WebApi/Category/User.js +88 -0
- package/src/classes/WebApi/webapi.js +52 -0
- package/src/constants/TypesConstants.js +89 -0
- package/src/constants/WebSocketConstants.js +80 -0
- package/src/core/Highrise.js +123 -0
- package/src/core/HighriseWebsocket.js +228 -0
- package/src/utils/ConvertSvgToPng.js +51 -0
- package/src/utils/ModelPool.js +160 -0
- package/src/utils/Models.js +128 -0
- package/src/utils/versionCheck.js +27 -0
- package/src/validators/ConfigValidator.js +205 -0
- package/src/validators/ConnectionValidator.js +65 -0
- package/typings/index.d.ts +3820 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
class ItemCategory {
|
|
2
|
+
constructor(webapi, AxiosError) {
|
|
3
|
+
this.webapi = webapi;
|
|
4
|
+
this.logger = webapi.logger;
|
|
5
|
+
this.base = webapi.base;
|
|
6
|
+
this.AxiosErrorHandler = AxiosError
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async get(itemId) {
|
|
10
|
+
const method = 'bot.webapi.item.get'
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
if (!itemId || typeof itemId !== 'string') {
|
|
14
|
+
throw new TypeError('itemId must be a non-empty string');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const response = await this.base.get(`/items/${itemId}`);
|
|
18
|
+
if (response.status === 200 && response.data?.item) {
|
|
19
|
+
return this._formatItemDetail(response.data.item);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error instanceof TypeError) {
|
|
24
|
+
this.logger.error(method, `TypeError: ${error.message}`, { itemId }, error);
|
|
25
|
+
} else {
|
|
26
|
+
return this.AxiosErrorHandler.handle(error, this.logger, method, { itemId });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async list(params = {}) {
|
|
32
|
+
const method = 'bot.webapi.item.list'
|
|
33
|
+
|
|
34
|
+
const validatedParams = {
|
|
35
|
+
limit: Math.min(params.limit || 20, 100),
|
|
36
|
+
sort_order: params.sort_order || 'desc',
|
|
37
|
+
rarity: params.rarity,
|
|
38
|
+
item_name: params.item_name,
|
|
39
|
+
category: params.category,
|
|
40
|
+
starts_after: params.starts_after,
|
|
41
|
+
ends_before: params.ends_before
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const AllowedSortOrder = ['asc', 'desc'];
|
|
45
|
+
const AllowedRarities = ['common', 'uncommon', 'rare', 'epic', 'legendary', 'none_'];
|
|
46
|
+
const AllowedCategories = [
|
|
47
|
+
'bag', 'blush', 'body', 'dress', 'earrings', 'emote', 'eye', 'eyebrow',
|
|
48
|
+
'face_hair', 'fishing_rod', 'freckle', 'glasses', 'gloves', 'hair_back',
|
|
49
|
+
'hair_front', 'handbag', 'hat', 'jacket', 'lashes', 'mole', 'mouth',
|
|
50
|
+
'necklace', 'nose', 'pants', 'shirt', 'shoes', 'shorts', 'skirt',
|
|
51
|
+
'watch', 'fullsuit', 'sock', 'tattoo', 'rod', 'aura'
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
if (typeof params !== 'object') {
|
|
56
|
+
throw new TypeError('params must be an object');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (validatedParams.limit <= 0 || validatedParams.limit > 100) {
|
|
60
|
+
throw new TypeError('limit must be between 1 and 100');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!AllowedSortOrder.includes(validatedParams.sort_order)) {
|
|
64
|
+
throw new TypeError(`sort_order must be one of: ${AllowedSortOrder.join(', ')}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (validatedParams.rarity && !AllowedRarities.includes(validatedParams.rarity)) {
|
|
68
|
+
throw new TypeError(`rarity must be one of: ${AllowedRarities.join(', ')}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (validatedParams.category && !AllowedCategories.includes(validatedParams.category)) {
|
|
72
|
+
throw new TypeError(`category must be one of: ${AllowedCategories.join(', ')}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const response = await this.base.get('/items', {
|
|
76
|
+
params: validatedParams
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (response.status === 200 && response.data?.items) {
|
|
80
|
+
return this._formatItemsList(response.data);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return null;
|
|
84
|
+
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (error instanceof TypeError) {
|
|
87
|
+
this.logger.error(method, `TypeError: ${error.message}`, { params }, error);
|
|
88
|
+
throw error;
|
|
89
|
+
} else {
|
|
90
|
+
return this.AxiosErrorHandler.handle(error, this.logger, method, { params });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async search(params = {}) {
|
|
96
|
+
const method = 'bot.webapi.item.search'
|
|
97
|
+
|
|
98
|
+
const validatedParams = {
|
|
99
|
+
limit: Math.min(params.limit || 20, 100),
|
|
100
|
+
skip: Math.max(params.skip || 0, 0),
|
|
101
|
+
query: params.query || ''
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
if (typeof params !== 'object') {
|
|
106
|
+
throw new TypeError('params must be an object');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (validatedParams.limit <= 0 || validatedParams.limit > 100) {
|
|
110
|
+
throw new TypeError('limit must be between 1 and 100');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (typeof validatedParams.query !== 'string') {
|
|
114
|
+
throw new TypeError('query must be a string');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (validatedParams.skip < 0) {
|
|
118
|
+
throw new TypeError('skip cannot be negative');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const response = await this.base.get('/items/search', {
|
|
122
|
+
params: validatedParams
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (response.status === 200 && response.data?.items) {
|
|
126
|
+
return this._formatItemsSearch(response.data);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return null;
|
|
130
|
+
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (error instanceof TypeError) {
|
|
133
|
+
this.logger.error(method, `TypeError: ${error.message}`, { params }, error);
|
|
134
|
+
throw error;
|
|
135
|
+
} else {
|
|
136
|
+
return this.AxiosErrorHandler.handle(error, this.logger, method, { params });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async searchByName(name, limit = 20) {
|
|
142
|
+
return this.search({ query: name, limit });
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async getByCategory(category, limit = 20) {
|
|
146
|
+
return this.list({ category, limit });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async getByRarity(rarity, limit = 20) {
|
|
150
|
+
return this.list({ rarity, limit });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async getByName(name, limit = 20) {
|
|
154
|
+
return this.list({ item_name: name, limit });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async getRecent(limit = 20) {
|
|
158
|
+
return this.list({ limit, sort_order: 'desc' });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async getPurchasable(query = '', limit = 20) {
|
|
162
|
+
const result = await this.search({ query, limit });
|
|
163
|
+
if (result) {
|
|
164
|
+
return {
|
|
165
|
+
...result,
|
|
166
|
+
items: result.items.filter(item => item.properties.isPurchasable)
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async getTradable(query = '', limit = 20) {
|
|
173
|
+
const result = await this.search({ query, limit });
|
|
174
|
+
if (result) {
|
|
175
|
+
return {
|
|
176
|
+
...result,
|
|
177
|
+
items: result.items.filter(item => item.properties.isTradable)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async getPurchasableByCategory(category, limit = 20) {
|
|
184
|
+
const result = await this.list({ category, limit });
|
|
185
|
+
if (result) {
|
|
186
|
+
return {
|
|
187
|
+
...result,
|
|
188
|
+
items: result.items.filter(item => item.properties.isPurchasable)
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async getTradableByCategory(category, limit = 20) {
|
|
195
|
+
const result = await this.list({ category, limit });
|
|
196
|
+
if (result) {
|
|
197
|
+
return {
|
|
198
|
+
...result,
|
|
199
|
+
items: result.items.filter(item => item.properties.isTradable)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
_formatItemsList(apiResponse) {
|
|
206
|
+
return {
|
|
207
|
+
items: apiResponse.items.map(item => this._formatItem(item)),
|
|
208
|
+
pagination: {
|
|
209
|
+
total: apiResponse.total,
|
|
210
|
+
firstId: apiResponse.first_id,
|
|
211
|
+
lastId: apiResponse.last_id,
|
|
212
|
+
hasMore: apiResponse.items.length > 0
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
_formatItemsSearch(apiResponse) {
|
|
218
|
+
return {
|
|
219
|
+
items: apiResponse.items.map(item => this._formatItem(item)),
|
|
220
|
+
pagination: {
|
|
221
|
+
total: apiResponse.total,
|
|
222
|
+
hasMore: apiResponse.items.length > 0,
|
|
223
|
+
skip: apiResponse.skip || 0
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
_formatItem(itemData) {
|
|
229
|
+
return {
|
|
230
|
+
id: itemData.item_id,
|
|
231
|
+
name: itemData.item_name,
|
|
232
|
+
category: itemData.category,
|
|
233
|
+
colorLinkedCategories: itemData.color_linked_categories,
|
|
234
|
+
colorPalettes: itemData.color_palettes,
|
|
235
|
+
createdAt: itemData.created_at,
|
|
236
|
+
description: itemData.description_key,
|
|
237
|
+
pricing: {
|
|
238
|
+
gems: itemData.gems_sale_price,
|
|
239
|
+
pops: itemData.pops_sale_price
|
|
240
|
+
},
|
|
241
|
+
properties: {
|
|
242
|
+
isPurchasable: itemData.is_purchasable || false,
|
|
243
|
+
isTradable: itemData.is_tradable || false
|
|
244
|
+
},
|
|
245
|
+
images: {
|
|
246
|
+
main: itemData.image_url,
|
|
247
|
+
icon: itemData.icon_url
|
|
248
|
+
},
|
|
249
|
+
links: {
|
|
250
|
+
linkIds: Array.isArray(itemData.link_ids) ? itemData.link_ids : [],
|
|
251
|
+
inspiredBy: itemData.inspired_by
|
|
252
|
+
},
|
|
253
|
+
skinParts: {
|
|
254
|
+
front: Array.isArray(itemData.m_front_skin_part_list)
|
|
255
|
+
? itemData.m_front_skin_part_list.map(part => this._formatSkinPart(part))
|
|
256
|
+
: [],
|
|
257
|
+
back: Array.isArray(itemData.m_back_skin_part_list)
|
|
258
|
+
? itemData.m_back_skin_part_list.map(part => this._formatSkinPart(part))
|
|
259
|
+
: []
|
|
260
|
+
},
|
|
261
|
+
metadata: {
|
|
262
|
+
dependentColors: itemData.m_dependent_colors,
|
|
263
|
+
releaseDate: itemData.release_date,
|
|
264
|
+
keywords: itemData.keywords
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
_formatItemDetail(itemData) {
|
|
270
|
+
return {
|
|
271
|
+
...this._formatItem(itemData),
|
|
272
|
+
acquisition: {
|
|
273
|
+
cost: itemData.acquisition_cost,
|
|
274
|
+
amount: itemData.acquisition_amount,
|
|
275
|
+
currency: itemData.acquisition_currency
|
|
276
|
+
},
|
|
277
|
+
relatedItems: itemData.related_items ? this._formatRelatedItems(itemData.related_items) : null,
|
|
278
|
+
affiliations: Array.isArray(itemData.affiliations) ? itemData.affiliations.map(affil => this._formatAffiliation(affil)) : [],
|
|
279
|
+
storefrontListings: itemData.storefront_listings ? this._formatStorefrontListings(itemData.storefront_listings) : null
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
_formatSkinPart(skinPart) {
|
|
284
|
+
return {
|
|
285
|
+
bone: skinPart.bone,
|
|
286
|
+
slot: skinPart.slot,
|
|
287
|
+
imageFile: skinPart.image_file,
|
|
288
|
+
attachmentName: skinPart.attachment_name,
|
|
289
|
+
hasRemoteRenderLayer: skinPart.has_remote_render_layer || false
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
_formatRelatedItems(relatedItems) {
|
|
294
|
+
return {
|
|
295
|
+
items: Array.isArray(relatedItems.items) ? relatedItems.items.map(item => ({
|
|
296
|
+
id: item.item_id,
|
|
297
|
+
name: item.disp_name
|
|
298
|
+
})) : []
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
_formatAffiliation(affiliation) {
|
|
303
|
+
return {
|
|
304
|
+
id: affiliation.id,
|
|
305
|
+
title: affiliation.title,
|
|
306
|
+
type: affiliation.type,
|
|
307
|
+
eventType: affiliation.event_type
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
_formatStorefrontListings(storefront) {
|
|
312
|
+
return {
|
|
313
|
+
sellers: Array.isArray(storefront.sellers) ? storefront.sellers.map(seller => this._formatSeller(seller)) : [],
|
|
314
|
+
pages: storefront.pages || 0,
|
|
315
|
+
total: storefront.total || 0
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
_formatSeller(seller) {
|
|
320
|
+
return {
|
|
321
|
+
userId: seller.user_id,
|
|
322
|
+
username: seller.username,
|
|
323
|
+
outfit: Array.isArray(seller.outfit) ? seller.outfit.map(item => this._formatOutfitItem(item)) : [],
|
|
324
|
+
lastConnectedAt: seller.last_connected_at
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
_formatOutfitItem(outfitItem) {
|
|
329
|
+
return {
|
|
330
|
+
itemId: outfitItem.item_id,
|
|
331
|
+
name: outfitItem.name,
|
|
332
|
+
rarity: outfitItem.rarity,
|
|
333
|
+
activePalette: outfitItem.active_palette,
|
|
334
|
+
parts: outfitItem.parts,
|
|
335
|
+
colors: outfitItem.colors ? this._formatOutfitItemColors(outfitItem.colors) : null,
|
|
336
|
+
linkedColors: outfitItem.linked_colors
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
_formatOutfitItemColors(colors) {
|
|
341
|
+
return {
|
|
342
|
+
linkedColors: colors.linked_colors
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
module.exports = ItemCategory
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
class PostCategory {
|
|
2
|
+
constructor(webapi, AxiosError) {
|
|
3
|
+
this.webapi = webapi;
|
|
4
|
+
this.logger = webapi.logger;
|
|
5
|
+
this.base = webapi.base;
|
|
6
|
+
this.AxiosErrorHandler = AxiosError
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async get(postId) {
|
|
10
|
+
const method = 'bot.webapi.post.get'
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
if (!postId || typeof postId !== 'string') {
|
|
14
|
+
throw new TypeError('postId must be a non-empty string');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const response = await this.base.get(`/posts/${postId}`);
|
|
18
|
+
if (response.status === 200 && response.data?.post) {
|
|
19
|
+
return this._formatPostDetail(response.data.post);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error instanceof TypeError) {
|
|
24
|
+
this.logger.error(method, `TypeError: ${error.message}`, { postId }, error);
|
|
25
|
+
} else {
|
|
26
|
+
return this.AxiosErrorHandler.handle(error, this.logger, method, { postId });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async list(params = {}) {
|
|
32
|
+
const method = 'bot.webapi.post.list'
|
|
33
|
+
|
|
34
|
+
const validatedParams = {
|
|
35
|
+
limit: Math.min(params.limit || 20, 100),
|
|
36
|
+
sort_order: params.sort_order || 'desc',
|
|
37
|
+
author_id: params.author_id,
|
|
38
|
+
starts_after: params.starts_after,
|
|
39
|
+
ends_before: params.ends_before
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const AllowedSortOrder = ['asc', 'desc'];
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
if (typeof params !== 'object') {
|
|
46
|
+
throw new TypeError('params must be an object');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (validatedParams.limit <= 0 || validatedParams.limit > 100) {
|
|
50
|
+
throw new TypeError('limit must be between 1 and 100');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!AllowedSortOrder.includes(validatedParams.sort_order)) {
|
|
54
|
+
throw new TypeError(`sort_order must be one of: ${AllowedSortOrder.join(', ')}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const response = await this.base.get('/posts', {
|
|
58
|
+
params: validatedParams
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (response.status === 200 && response.data?.posts) {
|
|
62
|
+
return this._formatPostsList(response.data);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error instanceof TypeError) {
|
|
69
|
+
this.logger.error(method, `TypeError: ${error.message}`, { params }, error);
|
|
70
|
+
throw error;
|
|
71
|
+
} else {
|
|
72
|
+
return this.AxiosErrorHandler.handle(error, this.logger, method, { params });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async getByAuthor(authorId, limit = 20) {
|
|
78
|
+
return this.list({ author_id: authorId, limit });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async getRecent(limit = 20) {
|
|
82
|
+
return this.list({ limit, sort_order: 'desc' });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
_formatPostsList(apiResponse) {
|
|
86
|
+
return {
|
|
87
|
+
posts: apiResponse.posts.map(post => this._formatPostBasic(post)),
|
|
88
|
+
pagination: {
|
|
89
|
+
total: apiResponse.total,
|
|
90
|
+
firstId: apiResponse.first_id,
|
|
91
|
+
lastId: apiResponse.last_id,
|
|
92
|
+
hasMore: apiResponse.posts.length > 0
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_formatPostBasic(postData) {
|
|
98
|
+
return {
|
|
99
|
+
id: postData.post_id,
|
|
100
|
+
authorId: postData.author_id,
|
|
101
|
+
createdAt: this.webapi._formatDate(postData.created_at),
|
|
102
|
+
type: postData.type,
|
|
103
|
+
visibility: postData.visibility,
|
|
104
|
+
|
|
105
|
+
stats: {
|
|
106
|
+
comments: postData.num_comments || 0,
|
|
107
|
+
likes: postData.num_likes || 0,
|
|
108
|
+
reposts: postData.num_reposts || 0
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
content: {
|
|
112
|
+
text: postData.text || '',
|
|
113
|
+
hasBody: !!postData.body,
|
|
114
|
+
caption: postData.caption
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
fileKey: postData.file_key,
|
|
118
|
+
|
|
119
|
+
featuredUserIds: Array.isArray(postData.featured_user_ids) ? postData.featured_user_ids : [],
|
|
120
|
+
|
|
121
|
+
inventory: postData.inventory ? this.webapi._formatInventory(postData.inventory) : null,
|
|
122
|
+
|
|
123
|
+
body: postData.body ? this._formatPostBody(postData.body) : null
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_formatPostDetail(postData) {
|
|
128
|
+
return {
|
|
129
|
+
...this._formatPostBasic(postData),
|
|
130
|
+
comments: Array.isArray(postData.comments) ? postData.comments.map(comment => this._formatComment(comment)) : []
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_formatPostBody(body) {
|
|
135
|
+
if (!body) return null;
|
|
136
|
+
return {
|
|
137
|
+
text: body.text || '',
|
|
138
|
+
inventory: body.inventory ? this.webapi._formatInventory(body.inventory) : null
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
_formatComment(comment) {
|
|
143
|
+
return {
|
|
144
|
+
id: comment.id,
|
|
145
|
+
content: comment.content,
|
|
146
|
+
postId: comment.post_id,
|
|
147
|
+
authorId: comment.author_id,
|
|
148
|
+
authorName: comment.author_name,
|
|
149
|
+
likes: comment.num_likes || 0
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = PostCategory
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
class RoomCategory {
|
|
2
|
+
constructor(webapi, AxiosError) {
|
|
3
|
+
this.webapi = webapi;
|
|
4
|
+
this.logger = webapi.logger;
|
|
5
|
+
this.base = webapi.base;
|
|
6
|
+
this.AxiosErrorHandler = AxiosError
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async get(roomId) {
|
|
10
|
+
const method = 'bot.webapi.room.get'
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
if (!roomId || typeof roomId !== 'string') {
|
|
14
|
+
throw new TypeError('roomId must be a non-empty string');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const response = await this.base.get(`/rooms/${roomId}`);
|
|
18
|
+
if (response.status === 200 && response.data?.room) {
|
|
19
|
+
return this._formatRoomDetail(response.data.room);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return null;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.log(error)
|
|
25
|
+
if (error instanceof TypeError) {
|
|
26
|
+
this.logger.error(method, `TypeError: ${error.message}`, { roomId }, error);
|
|
27
|
+
} else {
|
|
28
|
+
return this.AxiosErrorHandler.handle(error, this.logger, method, { roomId });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async list(params = {}) {
|
|
34
|
+
const method = 'bot.webapi.room.list'
|
|
35
|
+
|
|
36
|
+
const validatedParams = {
|
|
37
|
+
limit: Math.min(params.limit || 20, 100),
|
|
38
|
+
sort_order: params.sort_order || 'desc',
|
|
39
|
+
room_name: params.room_name,
|
|
40
|
+
owner_id: params.owner_id,
|
|
41
|
+
starts_after: params.starts_after,
|
|
42
|
+
ends_before: params.ends_before
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const AllowedSortOrder = ['asc', 'desc'];
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
if (typeof params !== 'object') {
|
|
49
|
+
throw new TypeError('params must be an object');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (validatedParams.limit <= 0 || validatedParams.limit > 100) {
|
|
53
|
+
throw new TypeError('limit must be between 1 and 100');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!AllowedSortOrder.includes(validatedParams.sort_order)) {
|
|
57
|
+
throw new TypeError(`sort_order must be one of: ${AllowedSortOrder.join(', ')}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const response = await this.base.get('/rooms', {
|
|
61
|
+
params: validatedParams
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (response.status === 200 && response.data?.rooms) {
|
|
65
|
+
return this._formatRoomsList(response.data);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return null;
|
|
69
|
+
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (error instanceof TypeError) {
|
|
72
|
+
this.logger.error(method, `TypeError: ${error.message}`, { params }, error);
|
|
73
|
+
throw error;
|
|
74
|
+
} else {
|
|
75
|
+
return this.AxiosErrorHandler.handle(error, this.logger, method, { params });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async getCurrentRoom() {
|
|
81
|
+
const room = await this.get(this.webapi.bot.info.room.id)
|
|
82
|
+
return room
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async searchByName(name, limit = 20) {
|
|
86
|
+
return this.list({ room_name: name, limit });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async getByOwner(ownerId, limit = 20) {
|
|
90
|
+
return this.list({ owner_id: ownerId, limit });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async getRecent(limit = 20) {
|
|
94
|
+
return this.list({ limit, sort_order: 'desc' });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_formatRoomsList(apiResponse) {
|
|
98
|
+
return {
|
|
99
|
+
rooms: apiResponse.rooms.map(room => this._formatRoomBasic(room)),
|
|
100
|
+
pagination: {
|
|
101
|
+
total: apiResponse.total,
|
|
102
|
+
firstId: apiResponse.first_id,
|
|
103
|
+
lastId: apiResponse.last_id,
|
|
104
|
+
hasMore: apiResponse.rooms.length > 0
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_formatRoomBasic(roomData) {
|
|
110
|
+
return {
|
|
111
|
+
id: roomData.room_id,
|
|
112
|
+
name: roomData.disp_name,
|
|
113
|
+
description: roomData.description,
|
|
114
|
+
category: roomData.category,
|
|
115
|
+
createdAt: this.webapi._formatDate(roomData.created_at),
|
|
116
|
+
accessPolicy: roomData.access_policy,
|
|
117
|
+
ownerId: roomData.owner_id,
|
|
118
|
+
languages: Array.isArray(roomData.locale) ? roomData.locale : [roomData.locale],
|
|
119
|
+
isHomeRoom: roomData.is_home_room,
|
|
120
|
+
designerIds: Array.isArray(roomData.designer_ids) ? roomData.designer_ids : [],
|
|
121
|
+
moderatorIds: Array.isArray(roomData.moderator_ids) ? roomData.moderator_ids : []
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
_formatRoomDetail(roomData) {
|
|
126
|
+
return {
|
|
127
|
+
...this._formatRoomBasic(roomData),
|
|
128
|
+
connectedUsers: roomData.num_connected || 0,
|
|
129
|
+
thumbnail: roomData.thumbnail_url,
|
|
130
|
+
banner: roomData.banner_url,
|
|
131
|
+
crewId: roomData.crew_id,
|
|
132
|
+
bots: roomData.bots ? JSON.parse(roomData.bots) : [],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
module.exports = RoomCategory
|