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,156 @@
1
+ const { payment_methods, default_skin } = require("highrise-core/src/constants/TypesConstants");
2
+
3
+ class InventoryClass {
4
+ constructor(bot) {
5
+ this.bot = bot;
6
+ this.logger = this.bot.logger
7
+ }
8
+
9
+ async get() {
10
+ const method = 'bot.inventory.get'
11
+
12
+ try {
13
+ const payload = {
14
+ _type: 'GetInventoryRequest'
15
+ }
16
+
17
+ const response = await this.bot._requestResponse.send(payload)
18
+ return response.items
19
+ } catch (error) {
20
+ this.logger.error(method, `Failed to get bot inventory: ${error.message}`, error);
21
+ return []
22
+ }
23
+ }
24
+
25
+ outfit = {
26
+ set: async (outfit = default_skin) => {
27
+ const method = 'bot.inventory.outfit.set'
28
+
29
+ try {
30
+ if (!outfit || !Array.isArray(outfit)) throw new TypeError('outfit must be an array')
31
+
32
+ const payload = {
33
+ _type: 'SetOutfitRequest',
34
+ outfit: outfit
35
+ }
36
+
37
+ const response = await this.bot._fireAndForget.send(payload)
38
+ return response.success;
39
+ } catch (error) {
40
+ if (error instanceof TypeError) {
41
+ this.logger.error(method, `TypeError: ${error.message}`, error);
42
+ } else {
43
+ this.logger.error(method, `Failed to set outfit: ${error.message}`, error);
44
+ return false
45
+ }
46
+ }
47
+ }
48
+ }
49
+
50
+ wallet = {
51
+ get: async () => {
52
+ const method = 'bot.inventory.wallet.get'
53
+
54
+ try {
55
+ const payload = {
56
+ _type: 'GetWalletRequest'
57
+ }
58
+
59
+ const response = await this.bot._requestResponse.send(payload)
60
+
61
+ const walletData = response.content.reduce((acc, item) => {
62
+ acc[item.type] = item.amount;
63
+ return acc;
64
+ }, {});
65
+
66
+ return {
67
+ gold: walletData.gold || 0,
68
+ boost_tokens: walletData.room_boost_tokens || 0,
69
+ voice_tokens: walletData.room_voice_tokens || 0,
70
+ };
71
+ } catch (error) {
72
+ this.logger.error(method, `Failed to get bot wallet: ${error.message}`, error);
73
+ }
74
+ }
75
+ }
76
+
77
+ boost = {
78
+ buy: async (payment_method = 'bot_wallet_only', amount = 1) => {
79
+ const method = 'bot.inventory.boost.buy'
80
+ try {
81
+ if (!payment_method || typeof payment_method !== 'string' || !payment_methods.includes(payment_method)) {
82
+ throw new TypeError(`payment_method must be a string and a vaild payment method`)
83
+ }
84
+
85
+ if (!amount || typeof amount !== 'number' || amount <= 0) throw new TypeError('amount must be a positive number')
86
+
87
+ const payload = {
88
+ _type: 'BuyRoomBoostRequest',
89
+ payment_method: payment_method,
90
+ amount: amount
91
+ }
92
+
93
+ const response = await this.bot._requestResponse.send(payload)
94
+ return response.result
95
+ } catch (error) {
96
+ if (error instanceof TypeError) {
97
+ this.logger.error(method, `TypeError: ${error.message}`, { payment_method, amount }, error);
98
+ } else {
99
+ this.logger.error(method, `Failed to buy boost token: ${error.message}`, { payment_method, amount }, error);
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ voice = {
106
+ buy: async (payment_method = 'bot_wallet_only') => {
107
+ const method = 'bot.inventory.voice.buy'
108
+ try {
109
+ if (!payment_method || typeof payment_method !== 'string' || !payment_methods.includes(payment_method)) {
110
+ throw new TypeError(`payment_method must be a string and a vaild payment method\nValid payment methods: ${payment_methods.join(', ')}`)
111
+ }
112
+
113
+ const payload = {
114
+ _type: 'BuyVoiceTimeRequest',
115
+ payment_method: payment_method
116
+ }
117
+
118
+ const response = await this.bot._requestResponse.send(payload)
119
+ return response.result
120
+ } catch (error) {
121
+ if (error instanceof TypeError) {
122
+ this.logger.error(method, `TypeError: ${error.message}`, { payment_method }, error);
123
+ } else {
124
+ this.logger.error(method, `Failed to buy voice token: ${error.message}`, { payment_method }, error);
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ item = {
131
+ buy: async (item_id) => {
132
+ const method = 'bot.inventory.item.buy'
133
+ try {
134
+ if (!item_id || typeof item_id !== 'string') {
135
+ throw new TypeError(`item_id must be a string`)
136
+ }
137
+
138
+ const payload = {
139
+ _type: 'BuyItemRequest',
140
+ item_id: item_id
141
+ }
142
+
143
+ const response = await this.bot._requestResponse.send(payload)
144
+ return response.result
145
+ } catch (error) {
146
+ if (error instanceof TypeError) {
147
+ this.logger.error(method, `TypeError: ${error.message}`, { item_id }, error);
148
+ } else {
149
+ this.logger.error(method, `Failed to buy item: ${error.message}`, { item_id }, error);
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ module.exports = { InventoryClass }
@@ -0,0 +1,278 @@
1
+ const { IcecastStreamer, IcecastQueue, Track, YouTubeExtractor, IcecastServer } = require('./lib/AudioStreaming.js');
2
+ const EventEmitter = require('events')
3
+
4
+ class MusicClass extends EventEmitter {
5
+ constructor(bot, config = {}) {
6
+ super()
7
+ this.bot = bot;
8
+ this.config = {
9
+ enabled: config.enabled || false,
10
+ icecast: config.icecast || {},
11
+ queue: config.queue || {},
12
+ autoStartServer: config.autoStartServer || true,
13
+ serverPort: config.serverPort || 3000,
14
+ maxQueueSize: config.maxQueueSize || 100,
15
+ defaultVolume: config.defaultVolume || 80,
16
+ allowedFormats: config.allowedFormats || ['youtube', 'direct']
17
+ };
18
+
19
+ if (!this.config.enabled) {
20
+ console.log('Music module is disabled. Enable it in config to use music features.');
21
+ return;
22
+ }
23
+
24
+ this.initializeStreamer();
25
+ this.setupEventHandlers();
26
+
27
+ if (this.config.autoStartServer) {
28
+ this.startWebServer();
29
+ }
30
+
31
+ }
32
+
33
+ initializeStreamer() {
34
+ try {
35
+ this.streamer = new IcecastStreamer(this.config.icecast);
36
+ this.queue = new IcecastQueue(this.streamer, this.config.queue);
37
+
38
+ this.streamer.on('playbackStart', (track) => {
39
+ this.emit('playbackStart', track);
40
+ });
41
+
42
+ this.streamer.on('playbackEnd', (track) => {
43
+ this.emit('playbackEnd', track);
44
+ });
45
+
46
+ this.streamer.on('progress', (data) => {
47
+ this.emit('progress', data);
48
+ });
49
+
50
+ this.streamer.on('error', (error) => {
51
+ this.emit('error', error);
52
+ });
53
+
54
+ this.streamer.on('streamStopped', () => {
55
+ this.emit('streamStopped');
56
+ });
57
+
58
+ } catch (error) {
59
+ console.error('Failed to initialize Icecast streamer:', error);
60
+ throw error;
61
+ }
62
+ }
63
+
64
+ setupEventHandlers() {
65
+ this.bot.on('Ready', () => {
66
+ this.emit('Ready');
67
+ });
68
+
69
+ this.bot.on('error', (error) => {
70
+ this.emit('error', error);
71
+ });
72
+ }
73
+
74
+ async play(query, metadata = {}) {
75
+ try {
76
+ if (!this.streamer) {
77
+ throw new Error('Streamer not initialized');
78
+ }
79
+
80
+ let trackInfo;
81
+ let source = 'direct';
82
+
83
+ if (this.isValidUrl(query)) {
84
+ if (query.includes('youtube.com') || query.includes('youtu.be')) {
85
+ trackInfo = await YouTubeExtractor.getStreamUrl(query);
86
+ source = 'youtube';
87
+ } else {
88
+ trackInfo = {
89
+ url: query,
90
+ title: metadata.title || 'Unknown Track',
91
+ duration: metadata.duration || 0,
92
+ thumbnail: metadata.thumbnail || null
93
+ };
94
+ }
95
+ } else {
96
+ trackInfo = await YouTubeExtractor.searchTrack(query);
97
+ source = 'youtube';
98
+ }
99
+
100
+ if (!trackInfo) {
101
+ return {
102
+ success: false,
103
+ error: 'Could not find or play the requested track'
104
+ };
105
+ }
106
+
107
+ const track = new Track({
108
+ url: trackInfo.url,
109
+ title: trackInfo.title || metadata.title || 'Unknown Track',
110
+ duration: trackInfo.duration || metadata.duration || 0,
111
+ requester: metadata.requester || 'System',
112
+ requesterId: metadata.requesterId || 'system',
113
+ thumbnail: trackInfo.thumbnail || metadata.thumbnail,
114
+ source: source
115
+ });
116
+
117
+ const result = await this.queue.add(track);
118
+
119
+ return {
120
+ success: true,
121
+ track: {
122
+ title: track.title,
123
+ duration: track.duration,
124
+ formattedDuration: track.getFormattedDuration(),
125
+ requester: track.requester,
126
+ thumbnail: track.thumbnail
127
+ },
128
+ position: result.position,
129
+ isNowPlaying: result.isNowPlaying || false
130
+ };
131
+
132
+ } catch (error) {
133
+ console.error('Error playing track:', error);
134
+ return {
135
+ success: false,
136
+ error: error.message
137
+ };
138
+ }
139
+ }
140
+
141
+ async skip() {
142
+ try {
143
+ const result = await this.queue.skip();
144
+
145
+ let upcoming = null;
146
+ if (this.queue.queue.length > 0) {
147
+ const nextTrack = this.queue.queue[0];
148
+ upcoming = {
149
+ title: nextTrack.title,
150
+ duration: nextTrack.duration,
151
+ formattedDuration: nextTrack.getFormattedDuration()
152
+ };
153
+ }
154
+
155
+ return {
156
+ success: result,
157
+ upcoming: upcoming
158
+ };
159
+ } catch (error) {
160
+ console.error('Error skipping track:', error);
161
+ return {
162
+ success: false,
163
+ error: error.message
164
+ };
165
+ }
166
+ }
167
+
168
+ getNowPlaying() {
169
+ const np = this.streamer.getNowPlaying();
170
+ if (!np || !np.track) {
171
+ return null;
172
+ }
173
+
174
+ return {
175
+ track: np.track,
176
+ position: np.position || 0,
177
+ duration: np.duration || 0,
178
+ progress: np.progress || 0,
179
+ remaining: np.remaining || 0,
180
+ formattedPosition: this.formatDuration(np.position || 0),
181
+ formattedDuration: np.track.getFormattedDuration(),
182
+ formattedRemaining: this.formatDuration(np.remaining || 0)
183
+ };
184
+ }
185
+
186
+ getQueue() {
187
+ return {
188
+ queue: this.queue?.getQueue(),
189
+ upcoming: this.queue?.getQueue().slice(0, 10),
190
+ loopMode: this.queue.loopMode,
191
+ length: this.queue.queue.length
192
+ };
193
+ }
194
+
195
+ toggleLoop() {
196
+ const modes = ['off', 'track', 'queue'];
197
+ const currentIndex = modes.indexOf(this.queue.loopMode);
198
+ const nextIndex = (currentIndex + 1) % modes.length;
199
+ this.queue.loopMode = modes[nextIndex];
200
+
201
+ return {
202
+ success: true,
203
+ newMode: this.queue.loopMode
204
+ };
205
+ }
206
+
207
+ shuffle() {
208
+ if (this.queue.queue.length === 0) {
209
+ return {
210
+ success: false,
211
+ error: 'Queue is empty'
212
+ };
213
+ }
214
+
215
+ for (let i = this.queue.queue.length - 1; i > 0; i--) {
216
+ const j = Math.floor(Math.random() * (i + 1));
217
+ [this.queue.queue[i], this.queue.queue[j]] = [this.queue.queue[j], this.queue.queue[i]];
218
+ }
219
+
220
+ return {
221
+ success: true,
222
+ queue: this.getQueue()
223
+ };
224
+ }
225
+
226
+ isValidUrl(string) {
227
+ try {
228
+ new URL(string);
229
+ return true;
230
+ } catch (_) {
231
+ return false;
232
+ }
233
+ }
234
+
235
+ formatDuration(seconds) {
236
+ if (!seconds) return '0:00';
237
+
238
+ const hours = Math.floor(seconds / 3600);
239
+ const minutes = Math.floor((seconds % 3600) / 60);
240
+ const secondsRemaining = Math.floor(seconds % 60);
241
+
242
+ if (hours > 0) {
243
+ return `${hours}:${minutes.toString().padStart(2, '0')}:${secondsRemaining.toString().padStart(2, '0')}`;
244
+ }
245
+ return `${minutes}:${secondsRemaining.toString().padStart(2, '0')}`;
246
+ }
247
+
248
+ startWebServer() {
249
+ try {
250
+ this.webServer = new IcecastServer({
251
+ port: this.config.serverPort,
252
+ publicStreamUrl: this.streamer.publicStreamUrl,
253
+ logger: this.bot.utils.logger
254
+ });
255
+
256
+ this.webServer.start();
257
+ return true;
258
+ } catch (error) {
259
+ console.error('Failed to start web server:', error);
260
+ return false;
261
+ }
262
+ }
263
+
264
+ destroy() {
265
+ try {
266
+ if (this.streamer) {
267
+ this.streamer.stop();
268
+ }
269
+
270
+ return true;
271
+ } catch (error) {
272
+ console.error('Error destroying music class:', error);
273
+ return false;
274
+ }
275
+ }
276
+ }
277
+
278
+ module.exports = MusicClass;