vantiv.io 1.0.7 → 1.0.9
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vantiv.io",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Enterprise WebSocket infrastructure for Highrise featuring spatial intelligence systems, memory-optimized architecture, and production-grade reliability for scalable application development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"highrise",
|
|
@@ -23,38 +23,38 @@ class MusicClass extends EventEmitter {
|
|
|
23
23
|
|
|
24
24
|
this.initializeStreamer();
|
|
25
25
|
this.setupEventHandlers();
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
if (this.config.autoStartServer) {
|
|
28
28
|
this.startWebServer();
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
initializeStreamer() {
|
|
34
34
|
try {
|
|
35
35
|
this.streamer = new IcecastStreamer(this.config.icecast);
|
|
36
|
-
this.queue = new IcecastQueue(this.streamer, { ...this.config.queue, ...this.config.icecast});
|
|
37
|
-
|
|
36
|
+
this.queue = new IcecastQueue(this.streamer, { ...this.config.queue, ...this.config.icecast });
|
|
37
|
+
|
|
38
38
|
this.streamer.on('playbackStart', (track) => {
|
|
39
39
|
this.emit('playbackStart', track);
|
|
40
40
|
});
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
this.streamer.on('playbackEnd', (track) => {
|
|
43
43
|
this.emit('playbackEnd', track);
|
|
44
44
|
});
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
this.streamer.on('progress', (data) => {
|
|
47
47
|
this.emit('progress', data);
|
|
48
48
|
});
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
this.streamer.on('error', (error) => {
|
|
51
51
|
this.emit('error', error);
|
|
52
52
|
});
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
this.streamer.on('streamStopped', () => {
|
|
55
55
|
this.emit('streamStopped');
|
|
56
56
|
});
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
} catch (error) {
|
|
59
59
|
console.error('Failed to initialize Icecast streamer:', error);
|
|
60
60
|
throw error;
|
|
@@ -79,10 +79,19 @@ class MusicClass extends EventEmitter {
|
|
|
79
79
|
|
|
80
80
|
let trackInfo;
|
|
81
81
|
let source = 'direct';
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
if (this.isValidUrl(query)) {
|
|
84
84
|
if (query.includes('youtube.com') || query.includes('youtu.be')) {
|
|
85
|
-
|
|
85
|
+
try {
|
|
86
|
+
trackInfo = await YouTubeExtractor.getStreamUrl(query);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: error.message.includes('yt-dlp')
|
|
91
|
+
? 'Missing dependency: yt-dlp'
|
|
92
|
+
: `YouTube error: ${error.message}`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
86
95
|
source = 'youtube';
|
|
87
96
|
} else {
|
|
88
97
|
trackInfo = {
|
|
@@ -115,7 +124,7 @@ class MusicClass extends EventEmitter {
|
|
|
115
124
|
});
|
|
116
125
|
|
|
117
126
|
const result = await this.queue.add(track);
|
|
118
|
-
|
|
127
|
+
|
|
119
128
|
return {
|
|
120
129
|
success: true,
|
|
121
130
|
track: {
|
|
@@ -128,7 +137,7 @@ class MusicClass extends EventEmitter {
|
|
|
128
137
|
position: result.position,
|
|
129
138
|
isNowPlaying: result.isNowPlaying || false
|
|
130
139
|
};
|
|
131
|
-
|
|
140
|
+
|
|
132
141
|
} catch (error) {
|
|
133
142
|
console.error('Error playing track:', error);
|
|
134
143
|
return {
|
|
@@ -141,7 +150,7 @@ class MusicClass extends EventEmitter {
|
|
|
141
150
|
async skip() {
|
|
142
151
|
try {
|
|
143
152
|
const result = await this.queue.skip();
|
|
144
|
-
|
|
153
|
+
|
|
145
154
|
let upcoming = null;
|
|
146
155
|
if (this.queue.queue.length > 0) {
|
|
147
156
|
const nextTrack = this.queue.queue[0];
|
|
@@ -151,7 +160,7 @@ class MusicClass extends EventEmitter {
|
|
|
151
160
|
formattedDuration: nextTrack.getFormattedDuration()
|
|
152
161
|
};
|
|
153
162
|
}
|
|
154
|
-
|
|
163
|
+
|
|
155
164
|
return {
|
|
156
165
|
success: result,
|
|
157
166
|
upcoming: upcoming
|
|
@@ -197,7 +206,7 @@ class MusicClass extends EventEmitter {
|
|
|
197
206
|
const currentIndex = modes.indexOf(this.queue.loopMode);
|
|
198
207
|
const nextIndex = (currentIndex + 1) % modes.length;
|
|
199
208
|
this.queue.loopMode = modes[nextIndex];
|
|
200
|
-
|
|
209
|
+
|
|
201
210
|
return {
|
|
202
211
|
success: true,
|
|
203
212
|
newMode: this.queue.loopMode
|
|
@@ -223,6 +232,18 @@ class MusicClass extends EventEmitter {
|
|
|
223
232
|
};
|
|
224
233
|
}
|
|
225
234
|
|
|
235
|
+
removeFromQueue(index) {
|
|
236
|
+
return this.queue?.remove(index) || null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
moveInQueue(from, to) {
|
|
240
|
+
return this.queue?.move(from, to) || false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
clearQueue() {
|
|
244
|
+
return this.queue?.clear() || [];
|
|
245
|
+
}
|
|
246
|
+
|
|
226
247
|
isValidUrl(string) {
|
|
227
248
|
try {
|
|
228
249
|
new URL(string);
|
|
@@ -234,31 +255,24 @@ class MusicClass extends EventEmitter {
|
|
|
234
255
|
|
|
235
256
|
formatDuration(seconds) {
|
|
236
257
|
if (!seconds) return '0:00';
|
|
237
|
-
|
|
258
|
+
|
|
238
259
|
const hours = Math.floor(seconds / 3600);
|
|
239
260
|
const minutes = Math.floor((seconds % 3600) / 60);
|
|
240
261
|
const secondsRemaining = Math.floor(seconds % 60);
|
|
241
|
-
|
|
262
|
+
|
|
242
263
|
if (hours > 0) {
|
|
243
264
|
return `${hours}:${minutes.toString().padStart(2, '0')}:${secondsRemaining.toString().padStart(2, '0')}`;
|
|
244
265
|
}
|
|
245
266
|
return `${minutes}:${secondsRemaining.toString().padStart(2, '0')}`;
|
|
246
267
|
}
|
|
247
268
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
this.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
}
|
|
269
|
+
getHealth() {
|
|
270
|
+
return {
|
|
271
|
+
streamer: this.streamer?.getHealth(),
|
|
272
|
+
queue: this.queue?.getStatus(),
|
|
273
|
+
webServer: !!this.webServer,
|
|
274
|
+
uptime: process.uptime()
|
|
275
|
+
};
|
|
262
276
|
}
|
|
263
277
|
|
|
264
278
|
destroy() {
|
|
@@ -266,7 +280,7 @@ class MusicClass extends EventEmitter {
|
|
|
266
280
|
if (this.streamer) {
|
|
267
281
|
this.streamer.stop();
|
|
268
282
|
}
|
|
269
|
-
|
|
283
|
+
|
|
270
284
|
return true;
|
|
271
285
|
} catch (error) {
|
|
272
286
|
console.error('Error destroying music class:', error);
|
|
@@ -148,7 +148,7 @@ class IcecastStreamer extends EventEmitter {
|
|
|
148
148
|
if (!this.config.fallbackUrl || this.isFallbackActive || this.isStreaming) {
|
|
149
149
|
return false;
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
if (this.ffmpegProcess) {
|
|
153
153
|
this.ffmpegProcess.kill('SIGKILL');
|
|
154
154
|
this.ffmpegProcess = null;
|
|
@@ -156,10 +156,10 @@ class IcecastStreamer extends EventEmitter {
|
|
|
156
156
|
|
|
157
157
|
const args = this.getFallbackFFmpegArgs();
|
|
158
158
|
this.fallbackProcess = spawn('ffmpeg', args);
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
this.isFallbackActive = true;
|
|
161
161
|
this.isStreaming = false;
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
this.currentTrack = new Track({
|
|
164
164
|
url: this.config.fallbackUrl,
|
|
165
165
|
title: 'Fallback Music',
|
|
@@ -173,11 +173,11 @@ class IcecastStreamer extends EventEmitter {
|
|
|
173
173
|
|
|
174
174
|
this.fallbackProcess.stderr.on('data', (data) => {
|
|
175
175
|
const message = data.toString();
|
|
176
|
-
|
|
176
|
+
|
|
177
177
|
if (message.includes('Stream mapping') || message.includes('Output')) {
|
|
178
178
|
this.emit('fallbackStart', this.currentTrack);
|
|
179
179
|
}
|
|
180
|
-
|
|
180
|
+
|
|
181
181
|
if (message.includes('Error') || message.includes('Failed')) {
|
|
182
182
|
console.error('Fallback FFmpeg error:', message.trim());
|
|
183
183
|
}
|
|
@@ -187,7 +187,7 @@ class IcecastStreamer extends EventEmitter {
|
|
|
187
187
|
this.isFallbackActive = false;
|
|
188
188
|
this.currentTrack = null;
|
|
189
189
|
this.fallbackProcess = null;
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
this.emit('fallbackEnd', { code });
|
|
192
192
|
});
|
|
193
193
|
|
|
@@ -219,7 +219,7 @@ class IcecastStreamer extends EventEmitter {
|
|
|
219
219
|
this.isStreaming = false;
|
|
220
220
|
this.emit('streamStopped');
|
|
221
221
|
}
|
|
222
|
-
|
|
222
|
+
|
|
223
223
|
this.stopFallback();
|
|
224
224
|
}
|
|
225
225
|
|
|
@@ -233,6 +233,18 @@ class IcecastStreamer extends EventEmitter {
|
|
|
233
233
|
};
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
getHealth() {
|
|
237
|
+
return {
|
|
238
|
+
status: this.isStreaming ? 'playing' :
|
|
239
|
+
this.isFallbackActive ? 'fallback' : 'idle',
|
|
240
|
+
latencyMs: this.currentTrack?.startedAt ?
|
|
241
|
+
Date.now() - this.currentTrack.startedAt : 0,
|
|
242
|
+
lastError: this.lastError,
|
|
243
|
+
uptime: this.currentTrack?.startedAt ?
|
|
244
|
+
(Date.now() - this.currentTrack.startedAt) / 1000 : 0,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
236
248
|
getNowPlaying() {
|
|
237
249
|
if (!this.currentTrack) return null;
|
|
238
250
|
|
|
@@ -300,12 +312,12 @@ class IcecastQueue {
|
|
|
300
312
|
this.history = [];
|
|
301
313
|
this.maxHistory = config.maxHistory || 50;
|
|
302
314
|
this.skipRequested = false;
|
|
303
|
-
|
|
315
|
+
|
|
304
316
|
this.fallbackEnabled = config.fallbackEnabled || false;
|
|
305
317
|
this.fallbackUrl = config.fallbackUrl || '';
|
|
306
318
|
|
|
307
319
|
this.setupEventListeners();
|
|
308
|
-
|
|
320
|
+
|
|
309
321
|
this.checkAndStartFallback();
|
|
310
322
|
}
|
|
311
323
|
|
|
@@ -332,27 +344,27 @@ class IcecastQueue {
|
|
|
332
344
|
this.streamer.on('playbackStart', (track) => {
|
|
333
345
|
this.currentTrack = track;
|
|
334
346
|
});
|
|
335
|
-
|
|
347
|
+
|
|
336
348
|
this.streamer.on('fallbackStart', (track) => {
|
|
337
349
|
this.currentTrack = track;
|
|
338
350
|
});
|
|
339
|
-
|
|
351
|
+
|
|
340
352
|
this.streamer.on('fallbackEnd', () => {
|
|
341
353
|
this.currentTrack = null;
|
|
342
354
|
this.checkAndStartFallback();
|
|
343
355
|
});
|
|
344
356
|
}
|
|
345
|
-
|
|
357
|
+
|
|
346
358
|
checkAndStartFallback() {
|
|
347
|
-
if (this.queue.length === 0 &&
|
|
359
|
+
if (this.queue.length === 0 &&
|
|
348
360
|
!this.streamer.isStreaming &&
|
|
349
361
|
!this.streamer.isFallbackActive &&
|
|
350
|
-
this.fallbackEnabled &&
|
|
362
|
+
this.fallbackEnabled &&
|
|
351
363
|
this.fallbackUrl) {
|
|
352
|
-
|
|
364
|
+
|
|
353
365
|
setTimeout(() => {
|
|
354
|
-
if (this.queue.length === 0 &&
|
|
355
|
-
!this.streamer.isStreaming &&
|
|
366
|
+
if (this.queue.length === 0 &&
|
|
367
|
+
!this.streamer.isStreaming &&
|
|
356
368
|
!this.streamer.isFallbackActive) {
|
|
357
369
|
this.streamer.startFallback();
|
|
358
370
|
}
|
|
@@ -453,18 +465,35 @@ class IcecastQueue {
|
|
|
453
465
|
return this.queue.splice(position - 1, 1)[0];
|
|
454
466
|
}
|
|
455
467
|
|
|
468
|
+
move(fromIndex, toIndex) {
|
|
469
|
+
if (fromIndex < 0 || fromIndex >= this.queue.length ||
|
|
470
|
+
toIndex < 0 || toIndex >= this.queue.length) {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const track = this.queue.splice(fromIndex, 1)[0];
|
|
475
|
+
this.queue.splice(toIndex, 0, track);
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
clearExceptCurrent() {
|
|
480
|
+
const cleared = this.queue.splice(0);
|
|
481
|
+
this.checkAndStartFallback();
|
|
482
|
+
return cleared;
|
|
483
|
+
}
|
|
484
|
+
|
|
456
485
|
clear() {
|
|
457
486
|
const cleared = [...this.queue];
|
|
458
487
|
this.queue = [];
|
|
459
|
-
|
|
488
|
+
|
|
460
489
|
this.checkAndStartFallback();
|
|
461
|
-
|
|
490
|
+
|
|
462
491
|
return cleared;
|
|
463
492
|
}
|
|
464
493
|
|
|
465
494
|
addToHistory(track, success = true) {
|
|
466
495
|
if (track.isFallback) return;
|
|
467
|
-
|
|
496
|
+
|
|
468
497
|
const historyEntry = {
|
|
469
498
|
...track,
|
|
470
499
|
playedAt: Date.now(),
|
|
@@ -499,14 +528,14 @@ class IcecastQueue {
|
|
|
499
528
|
async delay(ms) {
|
|
500
529
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
501
530
|
}
|
|
502
|
-
|
|
531
|
+
|
|
503
532
|
startFallback() {
|
|
504
533
|
if (this.fallbackEnabled && this.fallbackUrl) {
|
|
505
534
|
return this.streamer.startFallback();
|
|
506
535
|
}
|
|
507
536
|
return false;
|
|
508
537
|
}
|
|
509
|
-
|
|
538
|
+
|
|
510
539
|
stopFallback() {
|
|
511
540
|
return this.streamer.stopFallback();
|
|
512
541
|
}
|
|
@@ -525,12 +554,27 @@ class YouTubeExtractor {
|
|
|
525
554
|
'--no-playlist',
|
|
526
555
|
'--no-check-certificates',
|
|
527
556
|
'--quiet'
|
|
528
|
-
]
|
|
557
|
+
], {
|
|
558
|
+
timeout: 15000
|
|
559
|
+
});
|
|
529
560
|
|
|
530
561
|
let data = '';
|
|
531
562
|
ytdlp.stdout.on('data', (chunk) => data += chunk.toString());
|
|
532
563
|
ytdlp.stderr.on('data', () => { });
|
|
533
564
|
|
|
565
|
+
ytdlp.on('error', (err) => {
|
|
566
|
+
if (err.code === 'ENOENT') {
|
|
567
|
+
reject(new Error('yt-dlp not found. Install with: pip install yt-dlp'));
|
|
568
|
+
} else {
|
|
569
|
+
reject(err);
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
ytdlp.on('timeout', () => {
|
|
574
|
+
ytdlp.kill('SIGKILL');
|
|
575
|
+
reject(new Error('YouTube fetch timed out (15s)'));
|
|
576
|
+
});
|
|
577
|
+
|
|
534
578
|
ytdlp.on('close', (code) => {
|
|
535
579
|
if (code !== 0) {
|
|
536
580
|
resolve(null);
|
|
@@ -34,11 +34,6 @@ class ConnectionManager extends EventEmitter {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
_establishConnection() {
|
|
37
|
-
if (this.reconnecting || this.connected) {
|
|
38
|
-
this.logger.debug('ConnectionManager', 'Connection attempt already in progress — skipping');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
37
|
if (!this.connectionAuth) {
|
|
43
38
|
throw new Error('No connection authentication available');
|
|
44
39
|
}
|
|
@@ -59,7 +54,8 @@ class ConnectionManager extends EventEmitter {
|
|
|
59
54
|
[WebSocketConstants.HEADERS.API_TOKEN]: token,
|
|
60
55
|
[WebSocketConstants.HEADERS.ROOM_ID]: roomId
|
|
61
56
|
},
|
|
62
|
-
handshakeTimeout: WebSocketConstants.DEFAULT_HANDSHAKE_TIMEOUT
|
|
57
|
+
handshakeTimeout: WebSocketConstants.DEFAULT_HANDSHAKE_TIMEOUT,
|
|
58
|
+
autoPong: true
|
|
63
59
|
});
|
|
64
60
|
|
|
65
61
|
this._setupWebSocketHandlers();
|
|
@@ -105,7 +101,7 @@ class ConnectionManager extends EventEmitter {
|
|
|
105
101
|
this.reconnecting = false;
|
|
106
102
|
this._clearReconnectTimeout();
|
|
107
103
|
|
|
108
|
-
this.emit('
|
|
104
|
+
this.emit('Connected');
|
|
109
105
|
this.logger.info('ConnectionManager', 'WebSocket connection established');
|
|
110
106
|
}
|
|
111
107
|
|
|
@@ -115,7 +111,7 @@ class ConnectionManager extends EventEmitter {
|
|
|
115
111
|
this.reconnecting = false;
|
|
116
112
|
|
|
117
113
|
const reasonStr = reason?.toString('utf8') || `Binary reason (length: ${reason?.length || 0})`;
|
|
118
|
-
this.emit('
|
|
114
|
+
this.emit('Disconnected', { code, reason: reasonStr });
|
|
119
115
|
|
|
120
116
|
this.logger.warn('ConnectionManager', 'Connection closed', {
|
|
121
117
|
code,
|
|
@@ -188,7 +184,7 @@ class ConnectionManager extends EventEmitter {
|
|
|
188
184
|
}
|
|
189
185
|
|
|
190
186
|
this.connected = false;
|
|
191
|
-
this.emit('
|
|
187
|
+
this.emit('Disconnected', { code, reason, IsManual: true });
|
|
192
188
|
}
|
|
193
189
|
|
|
194
190
|
send(data) {
|
package/typings/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ type EventType =
|
|
|
14
14
|
| 'TipReactionEvent'
|
|
15
15
|
| 'RoomModeratedEvent'
|
|
16
16
|
| 'ChannelEvent'
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
type Goldbars = 1 | 5 | 10 | 50 | 100 | 500 | 1000 | 5000 | 10000
|
|
19
19
|
type ItemCategory =
|
|
20
20
|
| "bag"
|
|
@@ -368,6 +368,12 @@ interface CooldownManagerStats {
|
|
|
368
368
|
memoryUsage: CooldownMemoryUsage;
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
+
interface DisconnectedData {
|
|
372
|
+
code: number | null,
|
|
373
|
+
reason: string,
|
|
374
|
+
IsManual: boolean
|
|
375
|
+
}
|
|
376
|
+
|
|
371
377
|
interface EventMap {
|
|
372
378
|
UserLeft: [user: User]
|
|
373
379
|
Ready: [session: ReadyEvent]
|
|
@@ -380,6 +386,11 @@ interface EventMap {
|
|
|
380
386
|
Direct: [user: User, message: string, conversation: Conversation]
|
|
381
387
|
Moderation: [moderator: User, target: User, action: ModerationAction]
|
|
382
388
|
Movement: [user: User, position: Position | null, anchor: AnchorPosition | null]
|
|
389
|
+
|
|
390
|
+
// Connections
|
|
391
|
+
error: [data: any]
|
|
392
|
+
Connected: []
|
|
393
|
+
Disconnected: [data: DisconnectedData]
|
|
383
394
|
}
|
|
384
395
|
|
|
385
396
|
|
|
@@ -983,6 +994,468 @@ interface ChannelStats {
|
|
|
983
994
|
listeners: number;
|
|
984
995
|
}
|
|
985
996
|
|
|
997
|
+
/**
|
|
998
|
+
* Icecast stream configuration
|
|
999
|
+
*/
|
|
1000
|
+
interface IcecastConfig {
|
|
1001
|
+
/** Icecast server hostname or IP address */
|
|
1002
|
+
server?: string;
|
|
1003
|
+
/** Icecast server port */
|
|
1004
|
+
port?: number;
|
|
1005
|
+
/** Mount point for the stream */
|
|
1006
|
+
mount?: string;
|
|
1007
|
+
/** Source password for Icecast authentication */
|
|
1008
|
+
sourcePassword?: string;
|
|
1009
|
+
/** Fallback URL to play when queue is empty */
|
|
1010
|
+
fallbackUrl?: string;
|
|
1011
|
+
/** Whether fallback is enabled */
|
|
1012
|
+
fallbackEnabled?: boolean;
|
|
1013
|
+
/** Audio format (mp3, aac, etc.) */
|
|
1014
|
+
audioFormat?: string;
|
|
1015
|
+
/** Audio bitrate (e.g., '192k') */
|
|
1016
|
+
audioBitrate?: string;
|
|
1017
|
+
/** Audio sample rate in Hz */
|
|
1018
|
+
audioSampleRate?: number;
|
|
1019
|
+
/** Number of audio channels (1 for mono, 2 for stereo) */
|
|
1020
|
+
audioChannels?: number;
|
|
1021
|
+
/** Content type for Icecast stream */
|
|
1022
|
+
contentType?: string;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* Queue configuration
|
|
1027
|
+
*/
|
|
1028
|
+
interface QueueConfig {
|
|
1029
|
+
/** Maximum number of tracks to keep in history */
|
|
1030
|
+
maxHistory?: number;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* Music configuration for Highrise bot
|
|
1035
|
+
*/
|
|
1036
|
+
interface MusicConfig {
|
|
1037
|
+
/** Whether the music module is enabled */
|
|
1038
|
+
enabled?: boolean;
|
|
1039
|
+
/** Icecast server configuration */
|
|
1040
|
+
icecast?: IcecastConfig;
|
|
1041
|
+
/** Queue management configuration */
|
|
1042
|
+
queue?: QueueConfig;
|
|
1043
|
+
/** Automatically start web server for stream monitoring */
|
|
1044
|
+
autoStartServer?: boolean;
|
|
1045
|
+
/** Port for the web server */
|
|
1046
|
+
serverPort?: number;
|
|
1047
|
+
/** Maximum queue size */
|
|
1048
|
+
maxQueueSize?: number;
|
|
1049
|
+
/** Default volume level (0-100) */
|
|
1050
|
+
defaultVolume?: number;
|
|
1051
|
+
/** Allowed audio source formats */
|
|
1052
|
+
allowedFormats?: string[];
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Music playback status and information
|
|
1057
|
+
*/
|
|
1058
|
+
interface MusicNowPlaying {
|
|
1059
|
+
/** Current track information */
|
|
1060
|
+
track: Track;
|
|
1061
|
+
/** Current playback position in seconds */
|
|
1062
|
+
position: number;
|
|
1063
|
+
/** Total track duration in seconds */
|
|
1064
|
+
duration: number;
|
|
1065
|
+
/** Playback progress percentage (0-100) */
|
|
1066
|
+
progress: number;
|
|
1067
|
+
/** Time remaining in seconds */
|
|
1068
|
+
remaining: number;
|
|
1069
|
+
/** Formatted position string (e.g., '1:30') */
|
|
1070
|
+
formattedPosition: string;
|
|
1071
|
+
/** Formatted duration string (e.g., '3:45') */
|
|
1072
|
+
formattedDuration: string;
|
|
1073
|
+
/** Formatted remaining time string (e.g., '2:15') */
|
|
1074
|
+
formattedRemaining: string;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* Queue information
|
|
1079
|
+
*/
|
|
1080
|
+
interface QueueInfo {
|
|
1081
|
+
/** Current queue of tracks */
|
|
1082
|
+
queue: Track[];
|
|
1083
|
+
/** Upcoming tracks (first 10 in queue) */
|
|
1084
|
+
upcoming: Track[];
|
|
1085
|
+
/** Current loop mode */
|
|
1086
|
+
loopMode: 'off' | 'track' | 'queue';
|
|
1087
|
+
/** Number of tracks in queue */
|
|
1088
|
+
length: number;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Play result from music operations
|
|
1093
|
+
*/
|
|
1094
|
+
interface PlayResult {
|
|
1095
|
+
/** Whether the operation was successful */
|
|
1096
|
+
success: boolean;
|
|
1097
|
+
/** Track information (if successful) */
|
|
1098
|
+
track?: {
|
|
1099
|
+
title: string;
|
|
1100
|
+
duration: number;
|
|
1101
|
+
formattedDuration: string;
|
|
1102
|
+
requester: string;
|
|
1103
|
+
thumbnail?: string | null;
|
|
1104
|
+
};
|
|
1105
|
+
/** Position in queue (if added to queue) */
|
|
1106
|
+
position?: number;
|
|
1107
|
+
/** Whether track is now playing immediately */
|
|
1108
|
+
isNowPlaying?: boolean;
|
|
1109
|
+
/** Error message (if failed) */
|
|
1110
|
+
error?: string;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* Skip result from music operations
|
|
1115
|
+
*/
|
|
1116
|
+
interface SkipResult {
|
|
1117
|
+
/** Whether skip was successful */
|
|
1118
|
+
success: boolean;
|
|
1119
|
+
/** Upcoming track information */
|
|
1120
|
+
upcoming?: {
|
|
1121
|
+
title: string;
|
|
1122
|
+
duration: number;
|
|
1123
|
+
formattedDuration: string;
|
|
1124
|
+
};
|
|
1125
|
+
/** Error message (if failed) */
|
|
1126
|
+
error?: string;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/**
|
|
1130
|
+
* Loop toggle result
|
|
1131
|
+
*/
|
|
1132
|
+
interface LoopResult {
|
|
1133
|
+
/** Whether operation was successful */
|
|
1134
|
+
success: boolean;
|
|
1135
|
+
/** New loop mode */
|
|
1136
|
+
newMode: string;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* Shuffle result
|
|
1141
|
+
*/
|
|
1142
|
+
interface ShuffleResult {
|
|
1143
|
+
/** Whether shuffle was successful */
|
|
1144
|
+
success: boolean;
|
|
1145
|
+
/** Updated queue information */
|
|
1146
|
+
queue?: QueueInfo;
|
|
1147
|
+
/** Error message (if failed) */
|
|
1148
|
+
error?: string;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Music event types
|
|
1153
|
+
*/
|
|
1154
|
+
interface MusicEventMap {
|
|
1155
|
+
'playbackStart': [track: Track];
|
|
1156
|
+
'playbackEnd': [track: Track];
|
|
1157
|
+
'progress': [data: { position: number, duration: number, progress: number }];
|
|
1158
|
+
'error': [error: Error];
|
|
1159
|
+
'streamStopped': [];
|
|
1160
|
+
'Ready': [];
|
|
1161
|
+
'ready': [];
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/**
|
|
1165
|
+
* Logger configuration - controls how bot messages appear in console
|
|
1166
|
+
*/
|
|
1167
|
+
interface LoggerOptions {
|
|
1168
|
+
/** Show time in logs? (true = [2023-10-05T14:30:00.68a7dd5eecae68acca580f41Z] [INFO]) */
|
|
1169
|
+
showTimestamp?: boolean;
|
|
1170
|
+
/** Show method name? (true = [connect]: Connected) */
|
|
1171
|
+
showMethodName?: boolean;
|
|
1172
|
+
/** Use colors? (true = green success, red errors) */
|
|
1173
|
+
colors?: boolean;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
/**
|
|
1177
|
+
* Bot connection settings - controls how bot handles disconnections
|
|
1178
|
+
*/
|
|
1179
|
+
interface HighriseOptions {
|
|
1180
|
+
/** How logs look in console */
|
|
1181
|
+
LoggerOptions?: LoggerOptions;
|
|
1182
|
+
/** Wait time between reconnect tries (milliseconds) */
|
|
1183
|
+
reconnectDelay?: number;
|
|
1184
|
+
/** Auto-reconnect if disconnected? */
|
|
1185
|
+
autoReconnect?: boolean;
|
|
1186
|
+
/** Custom roles to create on startup */
|
|
1187
|
+
customRoles?: string[];
|
|
1188
|
+
/** Music module configuration */
|
|
1189
|
+
music?: MusicConfig;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* Configuration options for request senders
|
|
1194
|
+
*/
|
|
1195
|
+
interface SenderConfig {
|
|
1196
|
+
/**
|
|
1197
|
+
* Default timeout for requests waiting in milliseconds (default: 10000ms)
|
|
1198
|
+
*/
|
|
1199
|
+
defaultTimeout?: number;
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* Maximum number of retry attempts for failed requests (default: 2)
|
|
1203
|
+
*/
|
|
1204
|
+
maxRetries?: number;
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* Delay between retry attempts in milliseconds (default: 100)
|
|
1208
|
+
*/
|
|
1209
|
+
retryDelay?: number;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
interface PlayMetadata {
|
|
1213
|
+
title?: string;
|
|
1214
|
+
duration?: number;
|
|
1215
|
+
requester?: string;
|
|
1216
|
+
requesterId?: string;
|
|
1217
|
+
thumbnail?: string | null;
|
|
1218
|
+
source?: string;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
interface MusicHealthInfo {
|
|
1222
|
+
streamer: {
|
|
1223
|
+
status: 'idle' | 'playing' | 'fallback' | 'error';
|
|
1224
|
+
latencyMs: number;
|
|
1225
|
+
uptimeSeconds: number;
|
|
1226
|
+
lastError?: string;
|
|
1227
|
+
};
|
|
1228
|
+
queue: {
|
|
1229
|
+
length: number;
|
|
1230
|
+
isProcessing: boolean;
|
|
1231
|
+
};
|
|
1232
|
+
webServer: boolean;
|
|
1233
|
+
systemUptime: number;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
/**
|
|
1237
|
+
* Track information
|
|
1238
|
+
*/
|
|
1239
|
+
class Track {
|
|
1240
|
+
id: number;
|
|
1241
|
+
url: string;
|
|
1242
|
+
title: string;
|
|
1243
|
+
duration: number;
|
|
1244
|
+
requester: string;
|
|
1245
|
+
requesterId: string;
|
|
1246
|
+
addedAt: number;
|
|
1247
|
+
thumbnail?: string | null;
|
|
1248
|
+
source: string;
|
|
1249
|
+
isFallback?: boolean;
|
|
1250
|
+
position?: number;
|
|
1251
|
+
startedAt?: number;
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* Formats track duration (in seconds) as a readable time string.
|
|
1255
|
+
*
|
|
1256
|
+
* @returns
|
|
1257
|
+
* - `"Unknown"` if duration is `0`, `null`, or `invalid`
|
|
1258
|
+
* - `"M:SS"` for tracks under 1 hour (e.g., `"0:05"`, `"3:45"`)
|
|
1259
|
+
* - `"H:MM:SS"` for tracks 1+ hours (e.g., `"1:05:30"`)
|
|
1260
|
+
*
|
|
1261
|
+
* Note: Minutes are not padded in M:SS mode (`0:05`, not `00:05`),
|
|
1262
|
+
* but minutes/seconds are padded in H:MM:SS mode.
|
|
1263
|
+
*/
|
|
1264
|
+
getFormattedDuration(): string;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
declare class MusicClass {
|
|
1268
|
+
/**
|
|
1269
|
+
* Creates a new MusicClass instance
|
|
1270
|
+
* @param bot - Highrise bot instance
|
|
1271
|
+
* @param config - Music configuration
|
|
1272
|
+
*/
|
|
1273
|
+
constructor(bot: Highrise, config: MusicConfig);
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* Play a track from URL or search query
|
|
1277
|
+
* @param query - YouTube URL, direct URL, or search query
|
|
1278
|
+
* @param metadata - Track metadata (requester, title, etc.)
|
|
1279
|
+
* @returns Promise resolving to play result or error when thrown
|
|
1280
|
+
* @example
|
|
1281
|
+
* ```typescript
|
|
1282
|
+
* // Play YouTube video by URL
|
|
1283
|
+
* const result = await bot.music.play(
|
|
1284
|
+
* 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
|
1285
|
+
* { requester: 'User123', requesterId: 'user_123' }
|
|
1286
|
+
* );
|
|
1287
|
+
*
|
|
1288
|
+
* // Search and play YouTube video
|
|
1289
|
+
* const result = await bot.music.play(
|
|
1290
|
+
* 'never gonna give you up',
|
|
1291
|
+
* { requester: 'User123', requesterId: 'user_123' }
|
|
1292
|
+
* );
|
|
1293
|
+
* ```
|
|
1294
|
+
*/
|
|
1295
|
+
play(query: string, metadata?: PlayMetadata): Promise<PlayResult>;
|
|
1296
|
+
|
|
1297
|
+
/**
|
|
1298
|
+
* Skip the currently playing track
|
|
1299
|
+
* @returns Promise resolving to skip result
|
|
1300
|
+
* @example
|
|
1301
|
+
* ```typescript
|
|
1302
|
+
* const result = await bot.music.skip();
|
|
1303
|
+
* if (result.success && result.upcoming) {
|
|
1304
|
+
* await bot.message.send(`Now playing: ${result.upcoming.title}`);
|
|
1305
|
+
* }
|
|
1306
|
+
* ```
|
|
1307
|
+
*/
|
|
1308
|
+
skip(): Promise<SkipResult>;
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* Get information about currently playing track
|
|
1312
|
+
* @returns Now playing information or null if nothing is playing
|
|
1313
|
+
* @example
|
|
1314
|
+
* ```typescript
|
|
1315
|
+
* const np = bot.music.getNowPlaying();
|
|
1316
|
+
* if (np) {
|
|
1317
|
+
* await bot.message.send(
|
|
1318
|
+
* `Now playing: ${np.track.title}\n` +
|
|
1319
|
+
* `Progress: ${np.formattedPosition} / ${np.formattedDuration}`
|
|
1320
|
+
* );
|
|
1321
|
+
* }
|
|
1322
|
+
* ```
|
|
1323
|
+
*/
|
|
1324
|
+
getNowPlaying(): MusicNowPlaying | null;
|
|
1325
|
+
|
|
1326
|
+
/**
|
|
1327
|
+
* Get current queue information
|
|
1328
|
+
* @returns Queue information
|
|
1329
|
+
* @example
|
|
1330
|
+
* ```typescript
|
|
1331
|
+
* const queue = bot.music.getQueue();
|
|
1332
|
+
* await bot.message.send(
|
|
1333
|
+
* `Queue: ${queue.length} tracks\n` +
|
|
1334
|
+
* `Loop mode: ${queue.loopMode}`
|
|
1335
|
+
* );
|
|
1336
|
+
* ```
|
|
1337
|
+
*/
|
|
1338
|
+
getQueue(): QueueInfo;
|
|
1339
|
+
|
|
1340
|
+
/**
|
|
1341
|
+
* Toggle loop mode between off, track, and queue
|
|
1342
|
+
* @returns Loop result with new mode
|
|
1343
|
+
* @example
|
|
1344
|
+
* ```typescript
|
|
1345
|
+
* const result = bot.music.toggleLoop();
|
|
1346
|
+
* await bot.message.send(`Loop mode: ${result.newMode}`);
|
|
1347
|
+
* ```
|
|
1348
|
+
*/
|
|
1349
|
+
toggleLoop(): LoopResult;
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* Shuffle the current queue
|
|
1353
|
+
* @returns Shuffle result
|
|
1354
|
+
* @example
|
|
1355
|
+
* ```typescript
|
|
1356
|
+
* const result = bot.music.shuffle();
|
|
1357
|
+
* if (result.success) {
|
|
1358
|
+
* await bot.message.send('Queue shuffled!');
|
|
1359
|
+
* }
|
|
1360
|
+
* ```
|
|
1361
|
+
*/
|
|
1362
|
+
shuffle(): ShuffleResult;
|
|
1363
|
+
|
|
1364
|
+
/**
|
|
1365
|
+
* Remove a track from queue by position (1-based index)
|
|
1366
|
+
* @param position - Position in queue (1 = next track)
|
|
1367
|
+
* @returns Removed track or null if position invalid
|
|
1368
|
+
* @example
|
|
1369
|
+
* ```typescript
|
|
1370
|
+
* const removed = bot.music.removeFromQueue(1);
|
|
1371
|
+
* if (removed) {
|
|
1372
|
+
* await bot.message.send(`Removed: ${removed.title}`);
|
|
1373
|
+
* }
|
|
1374
|
+
* ```
|
|
1375
|
+
*/
|
|
1376
|
+
removeFromQueue(position: number): Track | null;
|
|
1377
|
+
|
|
1378
|
+
/**
|
|
1379
|
+
* Move a track from one position to another in the queue
|
|
1380
|
+
* @tutorial 1 being the top
|
|
1381
|
+
* @param fromPosition - Current position (1-based index)
|
|
1382
|
+
* @param toPosition - Target position (1-based index)
|
|
1383
|
+
* @returns true if move succeeded, false if invalid positions
|
|
1384
|
+
* @example
|
|
1385
|
+
* ```typescript
|
|
1386
|
+
* const success = bot.music.moveInQueue(3, 1);
|
|
1387
|
+
* if (success) {
|
|
1388
|
+
* await bot.message.send('Moved track to top of queue!');
|
|
1389
|
+
* }
|
|
1390
|
+
* ```
|
|
1391
|
+
*/
|
|
1392
|
+
moveInQueue(fromPosition: number, toPosition: number): boolean;
|
|
1393
|
+
|
|
1394
|
+
/**
|
|
1395
|
+
* Clear the entire queue (keeps currently playing track)
|
|
1396
|
+
* @returns Number of tracks removed
|
|
1397
|
+
* @example
|
|
1398
|
+
* ```typescript
|
|
1399
|
+
* const count = bot.music.clearQueue();
|
|
1400
|
+
* await bot.message.send(`Cleared ${count} tracks from queue`);
|
|
1401
|
+
* ```
|
|
1402
|
+
*/
|
|
1403
|
+
clearQueue(): number;
|
|
1404
|
+
|
|
1405
|
+
/**
|
|
1406
|
+
* Get system health status
|
|
1407
|
+
* @returns Health information including stream status, latency, and errors
|
|
1408
|
+
* @example
|
|
1409
|
+
* ```typescript
|
|
1410
|
+
* const health = bot.music.getHealth();
|
|
1411
|
+
* if (health.streamer.status === 'error') {
|
|
1412
|
+
* await bot.message.send(`⚠️ Music system error: ${health.streamer.lastError}`);
|
|
1413
|
+
* }
|
|
1414
|
+
* ```
|
|
1415
|
+
*/
|
|
1416
|
+
getHealth(): MusicHealthInfo;
|
|
1417
|
+
|
|
1418
|
+
/**
|
|
1419
|
+
* Check if string is a valid URL
|
|
1420
|
+
* @param string - String to check
|
|
1421
|
+
* @returns Whether string is a valid URL
|
|
1422
|
+
*/
|
|
1423
|
+
isValidUrl(string: string): boolean;
|
|
1424
|
+
|
|
1425
|
+
/**
|
|
1426
|
+
* Format duration in seconds to human-readable string
|
|
1427
|
+
* @param seconds - Duration in seconds
|
|
1428
|
+
* @returns Formatted duration string in `M:SS` format (e.g. `"0:00"`, `"1:05"`, `"12:30"`)
|
|
1429
|
+
*/
|
|
1430
|
+
formatDuration(seconds: number): string;
|
|
1431
|
+
|
|
1432
|
+
/**
|
|
1433
|
+
* Clean up and destroy music instance
|
|
1434
|
+
* @returns Whether cleanup was successful
|
|
1435
|
+
*/
|
|
1436
|
+
destroy(): boolean;
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* Register event listener for music events
|
|
1440
|
+
* @param event - Event name
|
|
1441
|
+
* @param listener - Event handler function
|
|
1442
|
+
*/
|
|
1443
|
+
on<K extends keyof MusicEventMap>(
|
|
1444
|
+
event: K,
|
|
1445
|
+
listener: (...args: MusicEventMap[K]) => void
|
|
1446
|
+
): void;
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* Remove event listener
|
|
1450
|
+
* @param event - Event name
|
|
1451
|
+
* @param listener - Event handler function to remove
|
|
1452
|
+
*/
|
|
1453
|
+
off<K extends keyof MusicEventMap>(
|
|
1454
|
+
event: K,
|
|
1455
|
+
listener: (...args: MusicEventMap[K]) => void
|
|
1456
|
+
): void;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
986
1459
|
declare class RoleManager {
|
|
987
1460
|
/**
|
|
988
1461
|
* Create a new custom role
|
|
@@ -1716,10 +2189,6 @@ declare class CooldownManager {
|
|
|
1716
2189
|
static formatTime(ms: number): string;
|
|
1717
2190
|
}
|
|
1718
2191
|
|
|
1719
|
-
/**
|
|
1720
|
-
* Hidden channel system for bot-to-bot communication
|
|
1721
|
-
* Messages are broadcast to all bots in the same room
|
|
1722
|
-
*/
|
|
1723
2192
|
declare class Channel {
|
|
1724
2193
|
/**
|
|
1725
2194
|
* Send a message to the hidden channel
|
|
@@ -2613,7 +3082,6 @@ declare class WebApi {
|
|
|
2613
3082
|
}
|
|
2614
3083
|
}
|
|
2615
3084
|
|
|
2616
|
-
|
|
2617
3085
|
declare class MovementCache {
|
|
2618
3086
|
/**
|
|
2619
3087
|
* Get user data by either userId or username
|
|
@@ -2974,7 +3442,6 @@ declare class WhisperClass {
|
|
|
2974
3442
|
send(user_id: string, message: string): Promise<boolean>;
|
|
2975
3443
|
}
|
|
2976
3444
|
|
|
2977
|
-
|
|
2978
3445
|
declare class DirectClass {
|
|
2979
3446
|
|
|
2980
3447
|
/**
|
|
@@ -3345,7 +3812,7 @@ declare class Logger {
|
|
|
3345
3812
|
debug(method: string, message: string, data?: any): void;
|
|
3346
3813
|
}
|
|
3347
3814
|
|
|
3348
|
-
|
|
3815
|
+
declare class BotUtils {
|
|
3349
3816
|
/**
|
|
3350
3817
|
* Logger instance for structured, color-coded logging throughout the application
|
|
3351
3818
|
* Provides different log levels (SUCCESS, ERROR, WARN, INFO, DEBUG) with timestamps and method tracking
|
|
@@ -3612,52 +4079,6 @@ declare class RoomClass {
|
|
|
3612
4079
|
}
|
|
3613
4080
|
}
|
|
3614
4081
|
|
|
3615
|
-
/**
|
|
3616
|
-
* Logger configuration - controls how bot messages appear in console
|
|
3617
|
-
*/
|
|
3618
|
-
interface LoggerOptions {
|
|
3619
|
-
/** Show time in logs? (true = [2023-10-05T14:30:00.68a7dd5eecae68acca580f41Z] [INFO]) */
|
|
3620
|
-
showTimestamp?: boolean;
|
|
3621
|
-
/** Show method name? (true = [connect]: Connected) */
|
|
3622
|
-
showMethodName?: boolean;
|
|
3623
|
-
/** Use colors? (true = green success, red errors) */
|
|
3624
|
-
colors?: boolean;
|
|
3625
|
-
}
|
|
3626
|
-
|
|
3627
|
-
/**
|
|
3628
|
-
* Bot connection settings - controls how bot handles disconnections
|
|
3629
|
-
*/
|
|
3630
|
-
interface HighriseOptions {
|
|
3631
|
-
/** How logs look in console */
|
|
3632
|
-
LoggerOptions?: LoggerOptions;
|
|
3633
|
-
/** Wait time between reconnect tries (milliseconds) */
|
|
3634
|
-
reconnectDelay: number;
|
|
3635
|
-
/** Auto-reconnect if disconnected? */
|
|
3636
|
-
autoReconnect: boolean;
|
|
3637
|
-
/** Custom roles to create on startup */
|
|
3638
|
-
customRoles?: string[];
|
|
3639
|
-
}
|
|
3640
|
-
|
|
3641
|
-
/**
|
|
3642
|
-
* Configuration options for request senders
|
|
3643
|
-
*/
|
|
3644
|
-
interface SenderConfig {
|
|
3645
|
-
/**
|
|
3646
|
-
* Default timeout for requests waiting in milliseconds (default: 10000ms)
|
|
3647
|
-
*/
|
|
3648
|
-
defaultTimeout?: number;
|
|
3649
|
-
|
|
3650
|
-
/**
|
|
3651
|
-
* Maximum number of retry attempts for failed requests (default: 2)
|
|
3652
|
-
*/
|
|
3653
|
-
maxRetries?: number;
|
|
3654
|
-
|
|
3655
|
-
/**
|
|
3656
|
-
* Delay between retry attempts in milliseconds (default: 100)
|
|
3657
|
-
*/
|
|
3658
|
-
retryDelay?: number;
|
|
3659
|
-
}
|
|
3660
|
-
|
|
3661
4082
|
declare class Highrise {
|
|
3662
4083
|
/**
|
|
3663
4084
|
* Creates a new Highrise bot instance
|
|
@@ -3713,6 +4134,9 @@ declare class Highrise {
|
|
|
3713
4134
|
*/
|
|
3714
4135
|
public channel: Channel;
|
|
3715
4136
|
|
|
4137
|
+
/** Music streaming and management */
|
|
4138
|
+
public music: MusicClass | null;
|
|
4139
|
+
|
|
3716
4140
|
/**
|
|
3717
4141
|
* Cache management system for efficient data storage and retrieval
|
|
3718
4142
|
* Provides optimized memory usage and fast lookups for frequently accessed data
|