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
package/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /// <reference types="./typings/index.d.ts" />
2
+ 'use strict';
3
+
4
+ /**
5
+ * Highrise Bot SDK
6
+ * A HIghrise WebSocket SDK for Highrise bots
7
+ *
8
+ * @copyright 2025 Yahya Ahmed
9
+ * @license MIT
10
+ */
11
+
12
+ exports.Highrise = require('./src/core/Highrise')
13
+ exports.WebApi = require('./src/classes/WebApi/webapi').WebApi
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "vantiv.io",
3
+ "version": "1.0.0",
4
+ "description": "Enterprise WebSocket infrastructure for Highrise featuring spatial intelligence systems, memory-optimized architecture, and production-grade reliability for scalable application development",
5
+ "keywords": [
6
+ "highrise",
7
+ "websocket",
8
+ "sdk",
9
+ "bot",
10
+ "typescript",
11
+ "spatial",
12
+ "cache"
13
+ ],
14
+ "main": "./index.js",
15
+ "types": "./typings/index.d.ts",
16
+ "author": "Yahya Ahmed eheaahmed2000@gmail.com",
17
+ "license": "MIT",
18
+ "type": "commonjs",
19
+ "dependencies": {
20
+ "axios": "^1.13.2",
21
+ "chalk": "^4.1.2",
22
+ "colors": "^1.4.0",
23
+ "express": "^5.2.1",
24
+ "sharp": "^0.34.5",
25
+ "user-agents": "^1.1.669",
26
+ "ws": "^8.18.3"
27
+ }
28
+ }
@@ -0,0 +1,202 @@
1
+ class AwaitClass {
2
+ constructor(ws) {
3
+ if (!ws) {
4
+ throw new Error('ws instance is required');
5
+ }
6
+ this.ws = ws;
7
+ this._pendingAwaiters = new Map();
8
+ }
9
+
10
+ chat(filter = () => true, timeout = 30000, maxToCollect = 1, uniqueUsers = false) {
11
+ if (!this._validateParameters('chat', filter, timeout, maxToCollect)) {
12
+ return Promise.resolve([]);
13
+ }
14
+
15
+ return this._createAwaiter('chat', filter, timeout, maxToCollect, uniqueUsers);
16
+ }
17
+
18
+ whisper(filter = () => true, timeout = 30000, maxToCollect = 1, uniqueUsers = false) {
19
+ if (!this._validateParameters('whisper', filter, timeout, maxToCollect)) {
20
+ return Promise.resolve([]);
21
+ }
22
+
23
+ return this._createAwaiter('whisper', filter, timeout, maxToCollect, uniqueUsers);
24
+ }
25
+
26
+ direct(filter = () => true, timeout = 30000, maxToCollect = 1, uniqueUsers = false) {
27
+ if (!this._validateParameters('direct', filter, timeout, maxToCollect)) {
28
+ return Promise.resolve([]);
29
+ }
30
+ return this._createAwaiter('direct', filter, timeout, maxToCollect, uniqueUsers);
31
+ }
32
+
33
+ tip(filter = () => true, timeout = 30000, maxToCollect = 1, uniqueUsers = false) {
34
+ if (!this._validateParameters('tip', filter, timeout, maxToCollect)) {
35
+ return Promise.resolve([]);
36
+ }
37
+ return this._createAwaiter('tip', filter, timeout, maxToCollect, uniqueUsers);
38
+ }
39
+
40
+ movement(filter = () => true, timeout = 30000, maxToCollect = 1, uniqueUsers = false) {
41
+ if (!this._validateParameters('movement', filter, timeout, maxToCollect)) {
42
+ return Promise.resolve([]);
43
+ }
44
+ return this._createAwaiter('movement', filter, timeout, maxToCollect, uniqueUsers);
45
+ }
46
+
47
+ _validateParameters(method, filter, timeout, maxToCollect) {
48
+ try {
49
+ if (typeof filter !== 'function') {
50
+ throw new TypeError(`Filter must be a function`);
51
+ }
52
+
53
+ if (typeof timeout !== 'number') {
54
+ throw new TypeError(`Timeout must be a number`);
55
+ }
56
+ if (timeout < 0) {
57
+ throw new RangeError(`Timeout cannot be negative`);
58
+ }
59
+ if (timeout > 300000) {
60
+ throw new RangeError(`Timeout cannot exceed 5 minutes (300000ms)`);
61
+ }
62
+
63
+ if (typeof maxToCollect !== 'number') {
64
+ throw new TypeError(`maxToCollect must be a number`);
65
+ }
66
+ if (!Number.isInteger(maxToCollect)) {
67
+ throw new TypeError(`maxToCollect must be an integer`);
68
+ }
69
+ if (maxToCollect < 1) {
70
+ throw new RangeError(`maxToCollect must be at least 1`);
71
+ }
72
+ if (maxToCollect > 1000) {
73
+ throw new RangeError(`maxToCollect cannot exceed 1000`);
74
+ }
75
+
76
+ if (!this.ws.isConnected || !this.ws.isConnected()) {
77
+ throw new Error(`WebSocket is not connected to Highrise`);
78
+ }
79
+
80
+ return true;
81
+
82
+ } catch (error) {
83
+ if (error instanceof TypeError) {
84
+ this.ws._logger.error(`await.${method}`, `TypeError: ${error.message}`, { timeout, maxToCollect }, error);
85
+ } else if (error instanceof RangeError) {
86
+ this.ws._logger.error(`await.${method}`, `RangeError: ${error.message}`, { timeout, maxToCollect }, error);
87
+ } else {
88
+ this.ws._logger.error(`await.${method}`, error.message, { timeout, maxToCollect }, error);
89
+ }
90
+ return false;
91
+ }
92
+ }
93
+
94
+ _createAwaiter(eventType, filter, timeout, maxToCollect, uniqueUsers = false) {
95
+ return new Promise((resolve, reject) => {
96
+ const awaiterId = Symbol('awaiter');
97
+ const collected = [];
98
+ const seenUsers = new Set();
99
+ let timeoutId;
100
+
101
+ const cleanup = () => {
102
+ clearTimeout(timeoutId);
103
+ this._pendingAwaiters.delete(awaiterId);
104
+ };
105
+
106
+ const awaiter = {
107
+ eventType,
108
+ filter,
109
+ maxToCollect,
110
+ collected,
111
+ uniqueUsers,
112
+ seenUsers,
113
+ resolve: (results) => {
114
+ cleanup();
115
+ resolve(results);
116
+ },
117
+ reject: (error) => {
118
+ cleanup();
119
+ reject(error);
120
+ }
121
+ };
122
+
123
+ this._pendingAwaiters.set(awaiterId, awaiter);
124
+
125
+ if (timeout > 0) {
126
+ timeoutId = setTimeout(() => {
127
+ awaiter.resolve(collected);
128
+ }, timeout);
129
+ }
130
+ });
131
+ }
132
+
133
+ _processEvent(eventType, ...eventArgs) {
134
+ for (const [awaiterId, awaiter] of this._pendingAwaiters) {
135
+ if (awaiter.eventType === eventType) {
136
+ try {
137
+ this._validateEventArguments(eventType, eventArgs);
138
+
139
+ if (awaiter.uniqueUsers && eventArgs[0]?.id) {
140
+ if (awaiter.seenUsers.has(eventArgs[0].id)) {
141
+ continue;
142
+ }
143
+ awaiter.seenUsers.add(eventArgs[0].id);
144
+ }
145
+
146
+ if (awaiter.filter(...eventArgs)) {
147
+ awaiter.collected.push(eventArgs);
148
+
149
+ if (awaiter.collected.length >= awaiter.maxToCollect) {
150
+ awaiter.resolve(awaiter.collected);
151
+ }
152
+ }
153
+ } catch (error) {
154
+ this.ws._logger.error(`await.${eventType}`, `Filter error: ${error.message}`)
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ _validateEventArguments(eventType, eventArgs) {
161
+ const validators = {
162
+ chat: (args) => {
163
+ if (args.length !== 2) throw new TypeError('Chat event requires 2 arguments (user, message)');
164
+ if (!args[0] || typeof args[0].id !== 'string') throw new TypeError('Invalid user object in chat event');
165
+ if (typeof args[1] !== 'string') throw new TypeError('Invalid message in chat event');
166
+ },
167
+ whisper: (args) => {
168
+ if (args.length !== 2) throw new TypeError('Whisper event requires 2 arguments (user, message)');
169
+ if (!args[0] || typeof args[0].id !== 'string') throw new TypeError('Invalid user object in whisper event');
170
+ if (typeof args[1] !== 'string') throw new TypeError('Invalid message in whisper event');
171
+ },
172
+ direct: (args) => {
173
+ if (args.length !== 3) throw new TypeError('Direct event requires 3 arguments (user, message, conversation)');
174
+ if (!args[0] || typeof args[0].id !== 'string') throw new TypeError('Invalid user object in direct event');
175
+ if (typeof args[1] !== 'string') throw new TypeError('Invalid message in direct event');
176
+ if (!args[2] || typeof args[2].id !== 'string') throw new TypeError('Invalid conversation object in direct event');
177
+ },
178
+ tip: (args) => {
179
+ if (args.length !== 3) throw new TypeError('Tip event requires 3 arguments (sender, receiver, currency)');
180
+ if (!args[0] || typeof args[0].id !== 'string') throw new TypeError('Invalid sender in tip event');
181
+ if (!args[1] || typeof args[1].id !== 'string') throw new TypeError('Invalid receiver in tip event');
182
+ if (!args[2] || typeof args[2].amount !== 'number') throw new TypeError('Invalid currency in tip event');
183
+ },
184
+ movement: (args) => {
185
+ if (args.length !== 3) throw new TypeError('Movement event requires 3 arguments (user, position, anchor)');
186
+ if (!args[0] || typeof args[0].id !== 'string') throw new TypeError('Invalid user object in movement event');
187
+ if (!args[1] || typeof args[1].x !== 'number') throw new TypeError('Invalid position in movement event');
188
+ if (args[2] !== null && (!args[2] || typeof args[2].entity_id !== 'string')) throw new TypeError('Invalid anchor in movement event');
189
+ }
190
+ };
191
+
192
+ if (validators[eventType]) {
193
+ try {
194
+ validators[eventType](eventArgs);
195
+ } catch (error) {
196
+ this.ws._logger.error(`await.${eventType}`, error.message)
197
+ }
198
+ }
199
+ }
200
+ }
201
+
202
+ module.exports = AwaitClass;
@@ -0,0 +1,73 @@
1
+ class ChannelClass {
2
+ constructor(bot) {
3
+ this.bot = bot;
4
+ this.logger = bot.logger;
5
+ this._manager = bot._channelManager;
6
+ }
7
+
8
+ async send(message, tags = []) {
9
+ if (!this._manager) {
10
+ this.logger.error('Channel.send', 'Channel manager not available');
11
+ return false;
12
+ }
13
+ return await this._manager.send(message, tags);
14
+ }
15
+
16
+ on(tags, callback) {
17
+ if (!this._manager) {
18
+ this.logger.error('Channel.on', 'Channel manager not available');
19
+ return null;
20
+ }
21
+ return this._manager.on(tags, callback);
22
+ }
23
+
24
+ once(tags, callback) {
25
+ if (!this._manager) {
26
+ this.logger.error('Channel.once', 'Channel manager not available');
27
+ return null;
28
+ }
29
+ return this._manager.once(tags, callback);
30
+ }
31
+
32
+ off(listenerId) {
33
+ if (!this._manager) {
34
+ this.logger.error('Channel.off', 'Channel manager not available');
35
+ return false;
36
+ }
37
+ return this._manager.off(listenerId);
38
+ }
39
+
40
+ offAll(tags) {
41
+ if (!this._manager) {
42
+ this.logger.error('Channel.offAll', 'Channel manager not available');
43
+ return 0;
44
+ }
45
+ return this._manager.offAll(tags);
46
+ }
47
+
48
+ query(filter = {}) {
49
+ if (!this._manager) {
50
+ this.logger.error('Channel.query', 'Channel manager not available');
51
+ return [];
52
+ }
53
+ return this._manager.query(filter);
54
+ }
55
+
56
+ stats() {
57
+ if (!this._manager) {
58
+ this.logger.error('Channel.stats', 'Channel manager not available');
59
+ return { totalMessages: 0, listeners: 0 };
60
+ }
61
+ return this._manager.getStats();
62
+ }
63
+
64
+ clear() {
65
+ if (!this._manager) {
66
+ this.logger.error('Channel.clear', 'Channel manager not available');
67
+ return;
68
+ }
69
+ this._manager.clear();
70
+ }
71
+ }
72
+
73
+ module.exports = { ChannelClass };
@@ -0,0 +1,263 @@
1
+ class DirectClass {
2
+ constructor(bot) {
3
+ this.bot = bot
4
+ this.logger = this.bot.logger
5
+ }
6
+
7
+ async send(conversation_id, message) {
8
+ const method = 'bot.direct.send'
9
+
10
+ try {
11
+ if (typeof conversation_id !== 'string' || !conversation_id) throw new TypeError('conversation_id must be a string and non-empty string')
12
+ if (typeof message !== 'string' || !message) throw new TypeError('message must be a string and non-empty string')
13
+
14
+ const payload = {
15
+ _type: 'SendMessageRequest',
16
+ conversation_id: conversation_id,
17
+ content: message,
18
+ type: 'text'
19
+ }
20
+
21
+ const response = await this.bot._fireAndForget.send(payload)
22
+ return response.success
23
+ } catch (error) {
24
+ if (error instanceof TypeError) {
25
+ this.logger.error(method, `TypeError: ${error.message}`, { conversation_id, message }, error);
26
+ } else {
27
+ this.logger.error(method, `Failed to send message: ${error.message}`, { conversation_id, message }, error);
28
+ return false
29
+ }
30
+ }
31
+ }
32
+
33
+ async bulkSend(user_ids, message) {
34
+ const method = 'bot.direct.bulkSend'
35
+
36
+ try {
37
+ if (!Array.isArray(user_ids) || user_ids.length <= 0 || user_ids.length > 100) {
38
+ throw new TypeError('user_ids must be an array with at least 1 ID and maximum 100 IDs');
39
+ }
40
+
41
+ const invalidUserIds = user_ids.filter(id => typeof id !== 'string' || id.trim() === '');
42
+ if (invalidUserIds.length > 0) {
43
+ throw new TypeError(`All user_ids must be non-empty strings. Invalid IDs: ${invalidUserIds.join(', ')}`);
44
+ }
45
+
46
+ if (typeof message !== 'string' || !message.trim()) {
47
+ throw new TypeError('message must be a non-empty string');
48
+ }
49
+
50
+ const payload = {
51
+ _type: 'SendBulkMessageRequest',
52
+ user_ids: user_ids,
53
+ content: message,
54
+ type: 'text'
55
+ }
56
+
57
+ const response = await this.bot._fireAndForget.send(payload)
58
+ return response.success
59
+ } catch (error) {
60
+ if (error instanceof TypeError) {
61
+ this.logger.error(method, `TypeError: ${error.message}`, { conversation_id, message }, error);
62
+ } else {
63
+ this.logger.error(method, `Failed to send bulk messages: ${error.message}`, { conversation_id, message }, error);
64
+ return false
65
+ }
66
+ }
67
+ }
68
+
69
+ async bulkInvite(user_ids, options = {}) {
70
+ const method = 'bot.direct.bulkSend'
71
+
72
+ try {
73
+ if (!Array.isArray(user_ids) || user_ids.length <= 0 || user_ids.length > 100) {
74
+ throw new TypeError('user_ids must be an array with at least 1 ID and maximum 100 IDs');
75
+ }
76
+
77
+ const invalidUserIds = user_ids.filter(id => typeof id !== 'string' || id.trim() === '');
78
+ if (invalidUserIds.length > 0) {
79
+ throw new TypeError(`All user_ids must be non-empty strings. Invalid IDs: ${invalidUserIds.join(', ')}`);
80
+ }
81
+
82
+ if (typeof options !== 'object' || options === null) {
83
+ throw new TypeError('options must be an object')
84
+ }
85
+
86
+ const providedOptions = [];
87
+ if (options.room_id) providedOptions.push('room_id');
88
+ if (options.world_id) providedOptions.push('world_id');
89
+
90
+ if (providedOptions.length === 0) {
91
+ throw new TypeError('Must provide exactly one of: room_id or world_id')
92
+ }
93
+ if (providedOptions.length > 1) {
94
+ throw new TypeError(`Cannot provide both ${providedOptions.join(' and ')} - must provide exactly one`)
95
+ }
96
+
97
+ const payload = {
98
+ _type: 'SendBulkMessageRequest',
99
+ user_ids: user_ids,
100
+ content: '',
101
+ type: 'invite'
102
+ }
103
+
104
+ if (options.room_id) {
105
+ if (typeof options.room_id !== 'string') {
106
+ throw new TypeError('room_id must be a string')
107
+ }
108
+ payload.room_id = options.room_id;
109
+ } else if (options.world_id) {
110
+ if (typeof options.world_id !== 'string') {
111
+ throw new TypeError('world_id must be a string')
112
+ }
113
+ payload.world_id = options.world_id;
114
+ }
115
+
116
+ const response = await this.bot._fireAndForget.send(payload)
117
+ return response.success
118
+ } catch (error) {
119
+ if (error instanceof TypeError) {
120
+ this.logger.error(method, `TypeError: ${error.message}`, { conversation_id, message }, error);
121
+ } else {
122
+ this.logger.error(method, `Failed to send bulk invites: ${error.message}`, { conversation_id, message }, error);
123
+ return false
124
+ }
125
+ }
126
+ }
127
+
128
+ async invite(conversation_id, options = {}) {
129
+ const method = 'bot.invite.send'
130
+
131
+ try {
132
+ if (typeof conversation_id !== 'string' || !conversation_id) {
133
+ throw new TypeError('conversation_id must be a non-empty string')
134
+ }
135
+
136
+ if (typeof options !== 'object' || options === null) {
137
+ throw new TypeError('options must be an object')
138
+ }
139
+
140
+ const providedOptions = [];
141
+ if (options.room_id) providedOptions.push('room_id');
142
+ if (options.world_id) providedOptions.push('world_id');
143
+
144
+ if (providedOptions.length === 0) {
145
+ throw new TypeError('Must provide exactly one of: room_id or world_id')
146
+ }
147
+ if (providedOptions.length > 1) {
148
+ throw new TypeError(`Cannot provide both ${providedOptions.join(' and ')} - must provide exactly one`)
149
+ }
150
+
151
+ const payload = {
152
+ _type: 'SendMessageRequest',
153
+ conversation_id: conversation_id,
154
+ content: '',
155
+ type: 'invite'
156
+ }
157
+
158
+ if (options.room_id) {
159
+ if (typeof options.room_id !== 'string') {
160
+ throw new TypeError('room_id must be a string')
161
+ }
162
+ payload.room_id = options.room_id;
163
+ } else if (options.world_id) {
164
+ if (typeof options.world_id !== 'string') {
165
+ throw new TypeError('world_id must be a string')
166
+ }
167
+ payload.world_id = options.world_id;
168
+ }
169
+
170
+ const response = await this.bot._fireAndForget.send(payload)
171
+ return response.success
172
+
173
+ } catch (error) {
174
+ if (error instanceof TypeError) {
175
+ this.logger.error(method, `TypeError: ${error.message}`,
176
+ { conversation_id, options }, error);
177
+ } else {
178
+ this.logger.error(method, `Failed to send invite: ${error.message}`,
179
+ { conversation_id, options }, error);
180
+ return false
181
+ }
182
+ }
183
+ }
184
+
185
+ conversations = {
186
+ get: async (last_id = null, not_joined = false) => {
187
+ const method = 'bot.direct.conversations.get'
188
+
189
+ try {
190
+ if (typeof last_id !== 'string' && last_id !== null) throw new TypeError('last_id must be a string or null')
191
+ if (typeof not_joined !== 'boolean') throw new TypeError('not_joined must be a boolean')
192
+
193
+ const payload = {
194
+ _type: 'GetConversationsRequest',
195
+ last_id,
196
+ not_joined,
197
+ }
198
+
199
+ const response = await this.bot._requestResponse.send(payload)
200
+ return response.conversations
201
+ } catch (error) {
202
+ if (error instanceof TypeError) {
203
+ this.logger.error(method, `TypeError: ${error.message}`, { last_id, not_joined }, error);
204
+ } else {
205
+ this.logger.error(method, `Failed to get conversations: ${error.message}`, { last_id, not_joined }, error);
206
+ return [];
207
+ }
208
+ }
209
+ },
210
+
211
+ leave: async (conversation_id) => {
212
+ const method = 'bot.direct.conversations.leave'
213
+
214
+ try {
215
+ if (typeof conversation_id !== 'string' || !conversation_id) throw new TypeError('conversation_id must be a string and non-empty string')
216
+
217
+ const payload = {
218
+ _type: 'LeaveConversationRequest',
219
+ conversation_id: conversation_id,
220
+ }
221
+
222
+ const response = await this.bot._fireAndForget.send(payload)
223
+ return response.success
224
+ } catch (error) {
225
+ if (error instanceof TypeError) {
226
+ this.logger.error(method, `TypeError: ${error.message}`, { conversation_id }, error);
227
+ } else {
228
+ this.logger.error(method, `Failed to leave conversation: ${error.message}`, { conversation_id }, error);
229
+ return false
230
+ }
231
+ }
232
+ }
233
+ }
234
+
235
+ messages = {
236
+ get: async (conversation_id, last_message_id = null) => {
237
+ const method = 'bot.direct.messages.get'
238
+
239
+ try {
240
+ if (typeof conversation_id !== 'string' || !conversation_id) throw new TypeError('conversation_id must be a string and non-empty string')
241
+ if (typeof last_message_id !== 'string' && last_message_id !== null) throw new TypeError('last_message_id must be a string or null')
242
+
243
+ const payload = {
244
+ _type: 'GetMessagesRequest',
245
+ conversation_id,
246
+ last_message_id,
247
+ }
248
+
249
+ const response = await this.bot._requestResponse.send(payload)
250
+ return response.messages
251
+ } catch (error) {
252
+ if (error instanceof TypeError) {
253
+ this.logger.error(method, `TypeError: ${error.message}`, { conversation_id, last_message_id }, error);
254
+ } else {
255
+ this.logger.error(method, `Failed to get messages: ${error.message}`, { conversation_id, last_message_id }, error);
256
+ return [];
257
+ }
258
+ }
259
+ }
260
+ }
261
+ }
262
+
263
+ module.exports = { DirectClass }