Teralink Documentation
Welcome to Teralink v0.2.0 - the next-generation Lavalink client designed for modern Discord music bots. This major update brings intelligent features, enhanced performance, and production-ready monitoring to make your music bot more reliable and efficient than ever.
Smart search with automatic source detection, enhanced error handling with retry logic, performance monitoring, automatic memory management, and comprehensive queue analytics.
๐ Getting Started
Installation
npm install teralink
Basic Setup
const { Teralink } = require('teralink'); const { Client, GatewayIntentBits } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.MessageContent ] }); const nodes = [ { name: 'Main', host: 'localhost', port: 2333, password: 'youshallnotpass', secure: false } ]; const tera = new Teralink(client, nodes, { send: (packet) => { const guild = client.guilds.cache.get(packet.d?.guild_id); if (guild?.shard) guild.shard.send(packet); }, source: { default: 'ytmsearch' }, autopauseOnEmpty: true }); client.once('ready', () => { tera.init(client.user.id); console.log('๐ต Teralink is ready!'); }); client.login('your-bot-token');
Performance monitoring and memory management start automatically. No additional configuration needed!
๐ Key Features
๐ Performance Monitoring
Getting Performance Metrics
// Get comprehensive performance metrics const metrics = tera.getPerformanceMetrics(); console.log('Cache Hit Rate:', metrics.cacheHitRate + '%'); console.log('Memory Usage:', metrics.memoryUsage.heapUsagePercentage + '%'); console.log('Searches/min:', metrics.averageSearchesPerMinute); // Memory usage details const memory = tera.getMemoryUsage(); console.log('Heap Used:', memory.heapUsed + 'MB'); console.log('Heap Total:', memory.heapTotal + 'MB');
Memory Management
// Manual memory cleanup (automatic by default) tera.performMemoryCleanup(); // Control automatic memory management tera.stopMemoryManagement(); // Stop automatic cleanup tera.startMemoryManagement(); // Restart automatic cleanup // Reset performance metrics tera.resetPerformanceMetrics();
Metric | Description | Good Value |
---|---|---|
cacheHitRate |
Percentage of search requests served from cache | > 60% |
heapUsagePercentage |
Memory heap usage percentage | < 85% |
averageSearchesPerMinute |
Search requests processed per minute | Varies |
activeConnections |
Number of active node connections | = Node count |
๐ง Smart Search
Enhanced Search with Auto-Detection
// Smart search automatically detects source from URLs const results = await tera.smartSearch('https://open.spotify.com/track/xyz', user); // Query enhancement removes interfering words const enhanced = await tera.smartSearch('lofi hip hop official music video', user, { limit: 5, smartSearch: true // default: true }); // Batch search for multiple queries const queries = ['song1', 'song2', 'song3']; const batchResults = await tera.batchSearch(queries, user, { limit: 10 });
URL Pattern Detection
Platform | Auto-detected Sources | Example |
---|---|---|
YouTube | ytsearch |
youtube.com/watch, youtu.be |
Spotify | spsearch |
open.spotify.com, spotify: |
SoundCloud | scsearch |
soundcloud.com |
Bandcamp | bcsearch |
bandcamp.com |
๐ก๏ธ Enhanced Error Handling
Automatic Retry Logic
// Player operations now include automatic retry try { await player.play(); // Automatically retries on network errors } catch (error) { console.log('Play failed after retries:', error.message); } // Check if an error is retryable const isRetryable = player.shouldRetryError(error); console.log('Error is retryable:', isRetryable);
Node Health Monitoring
// Get detailed node health status const healthStatus = node.getHealthStatus(); console.log('Node stability:', healthStatus.connectionStability); console.log('Consecutive failures:', healthStatus.consecutiveFailures); console.log('Average ping:', healthStatus.averagePing + 'ms'); // Check if node is healthy const isHealthy = node.isHealthy(); console.log('Node is healthy:', isHealthy);
Retries are triggered for: timeout, network errors, ECONNRESET, ENOTFOUND, ETIMEDOUT, and socket hang up errors. Maximum 3 attempts with exponential backoff.
๐ Advanced Queue Management
Queue Analytics
// Get comprehensive queue statistics const stats = player.queue.getStats(); console.log('Total tracks:', stats.totalTracks); console.log('Estimated playtime:', stats.estimatedPlaytime); console.log('Unique artists:', stats.uniqueArtists); console.log('Sources:', stats.sources); // Search within queue with scoring const searchResults = player.queue.searchAdvanced('lofi', { limit: 5, fuzzy: true }); searchResults.forEach(result => { console.log(`${result.track.info.title} (Score: ${result.score})`); });
Queue Optimization
// Remove duplicate tracks const removedCount = player.queue.removeDuplicates('uri'); console.log('Removed', removedCount, 'duplicates'); // Filter queue by criteria const filtered = player.queue.filter({ source: 'youtube', minDuration: 60000, // 1 minute minimum maxDuration: 600000 // 10 minutes maximum }); // Async shuffle for large queues await player.queue.shuffleAsync();
Queue Statistics
Property | Type | Description |
---|---|---|
totalTracks |
number | Total number of tracks in queue |
totalDuration |
number | Total duration in milliseconds |
estimatedPlaytime |
string | Human-readable total playtime |
uniqueArtists |
number | Number of unique artists |
uniqueRequesters |
number | Number of different users who added tracks |
๐ Production Monitoring
System Health Overview
// Get overall system health const systemHealth = tera.getSystemHealth(); console.log('Connected nodes:', systemHealth.connectedNodes); console.log('Total players:', systemHealth.totalPlayers); console.log('Average ping:', systemHealth.averagePing + 'ms'); // Individual node health const nodesHealth = tera.getNodesHealth(); Object.entries(nodesHealth).forEach(([name, health]) => { console.log(`${name}: ${health.connected ? 'Online' : 'Offline'}`); });
Monitoring Dashboard Example
// Create a simple monitoring function function monitorTeralink() { const metrics = tera.getPerformanceMetrics(); const memory = tera.getMemoryUsage(); console.log('๐ Teralink Status Report'); console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโ'); console.log(`๐ฏ Cache Hit Rate: ${metrics.cacheHitRate}%`); console.log(`๐พ Memory Usage: ${memory.heapUsagePercentage}%`); console.log(`๐ Searches/min: ${metrics.averageSearchesPerMinute}`); console.log(`๐ต Active Players: ${tera.players.size}`); console.log(`๐ Connected Nodes: ${[...tera.nodeMap.values()].filter(n => n.connected).length}`); // Alert if memory usage is high if (memory.heapUsagePercentage > 85) { console.log('โ ๏ธ High memory usage detected!'); tera.performMemoryCleanup(); } } // Run monitoring every 5 minutes setInterval(monitorTeralink, 5 * 60 * 1000);
๐ API Reference
New Methods in v0.2.0
Teralink Class
// Performance & Memory Management getPerformanceMetrics(): PerformanceMetrics resetPerformanceMetrics(): void getMemoryUsage(): MemoryUsage performMemoryCleanup(): void startMemoryManagement(): void stopMemoryManagement(): void // Smart Search smartSearch(query: string, requester: any, options?: SmartSearchOptions): PromisebatchSearch(queries: string[], requester: any, options?: BatchSearchOptions): Promise
Player Class
// Enhanced Play & Error Handling play(retryAttempt?: number): Promiserestart(): Promise shouldRetryError(error: Error): boolean delay(ms: number): Promise // Auto-Resume State saveAutoResumeState(): void clearAutoResumeState(): void // Lyrics (Enhanced) getLyrics(queryOverride?: { track_name: string; artist_name: string; album_name?: string }): Promise
Queue Class
// Advanced Queue Features getStats(): QueueStats searchAdvanced(query: string, options?: { limit?: number; fuzzy?: boolean }): QueueSearchResult[] removeDuplicates(criteria?: 'uri' | 'title' | 'identifier'): number shuffleAsync(): Promise formatDuration(ms: number): string // Enhanced Filtering filter(criteria: ((track: T, index: number) => boolean) | FilterCriteria): Array<{ track: T; index: number }>
Node Class
// Health Monitoring getHealthStatus(): NodeHealthStatus isHealthy(): boolean
๐ก Examples
Complete Music Bot Example
const { Client, GatewayIntentBits, SlashCommandBuilder } = require('discord.js'); const { Teralink } = require('teralink'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.MessageContent ] }); const tera = new Teralink(client, [ { name: 'Main', host: 'localhost', port: 2333, password: 'youshallnotpass' } ], { send: (packet) => { const guild = client.guilds.cache.get(packet.d?.guild_id); if (guild?.shard) guild.shard.send(packet); } }); // Play command with smart search client.on('interactionCreate', async (interaction) => { if (!interaction.isChatInputCommand()) return; if (interaction.commandName === 'play') { const query = interaction.options.getString('song'); const member = interaction.member; if (!member.voice.channel) { return interaction.reply('โ You must be in a voice channel!'); } try { // Create or get player const player = tera.get(interaction.guildId) || tera.createConnection({ guildId: interaction.guildId, voiceChannel: member.voice.channelId, textChannel: interaction.channelId }); // Smart search with automatic source detection const results = await tera.smartSearch(query, member.user, { limit: 1 }); if (!results.tracks.length) { return interaction.reply('โ No tracks found!'); } const track = results.tracks[0]; player.queue.add(track); if (!player.playing) { await player.play(); } interaction.reply(`๐ต Added **${track.info.title}** to the queue!`); } catch (error) { console.error('Play command error:', error); interaction.reply('โ An error occurred while playing the track.'); } } // Queue stats command if (interaction.commandName === 'queue') { const player = tera.get(interaction.guildId); if (!player) return interaction.reply('โ No music playing!'); const stats = player.queue.getStats(); const embed = { title: '๐ Queue Statistics', fields: [ { name: 'Total Tracks', value: stats.totalTracks.toString(), inline: true }, { name: 'Estimated Playtime', value: stats.estimatedPlaytime, inline: true }, { name: 'Unique Artists', value: stats.uniqueArtists.toString(), inline: true }, { name: 'Sources', value: stats.sources.join(', '), inline: false } ], color: 0x5865F2 }; interaction.reply({ embeds: [embed] }); } // Performance monitoring command if (interaction.commandName === 'stats') { const metrics = tera.getPerformanceMetrics(); const memory = tera.getMemoryUsage(); const embed = { title: '๐ Teralink Performance', fields: [ { name: 'Cache Hit Rate', value: `${metrics.cacheHitRate}%`, inline: true }, { name: 'Memory Usage', value: `${memory.heapUsagePercentage}%`, inline: true }, { name: 'Searches/min', value: metrics.averageSearchesPerMinute.toString(), inline: true }, { name: 'Active Players', value: tera.players.size.toString(), inline: true }, { name: 'Connected Nodes', value: [...tera.nodeMap.values()].filter(n => n.connected).length.toString(), inline: true } ], color: memory.heapUsagePercentage > 85 ? 0xFF0000 : 0x00FF00 }; interaction.reply({ embeds: [embed] }); } }); client.once('ready', () => { tera.init(client.user.id); console.log('๐ต Music bot is ready with Teralink v0.2.0!'); // Register slash commands const commands = [ new SlashCommandBuilder() .setName('play') .setDescription('Play a song') .addStringOption(option => option.setName('song') .setDescription('Song name or URL') .setRequired(true) ), new SlashCommandBuilder() .setName('queue') .setDescription('Show queue statistics'), new SlashCommandBuilder() .setName('stats') .setDescription('Show Teralink performance stats') ]; client.application.commands.set(commands); }); client.login('your-bot-token');
๐ Migration Guide
Upgrading from v0.1.x to v0.2.0
All existing code continues to work. New features are automatically enabled or opt-in.
New Features Available Immediately
- โ Performance monitoring - starts automatically
- โ Memory management - enables automatic cleanup
- โ Enhanced error handling - retry logic on play operations
- โ Improved caching - 2.5x larger cache with longer TTL
Opt-in Features
// Replace tera.search() with tera.smartSearch() for enhanced results const results = await tera.smartSearch(query, user, { limit: 5 }); // Use new queue analytics const stats = player.queue.getStats(); // Access performance metrics const metrics = tera.getPerformanceMetrics();
Recommended Configuration Updates
// Updated configuration with new nested structure const tera = new Teralink(client, nodes, { send, source: { default: 'ytmsearch' }, rest: { version: 'v4', retryCount: 3, timeout: 5000 }, node: { dynamicSwitching: true, autoReconnect: true, ws: { reconnectTries: 5, reconnectInterval: 5000 } }, resume: { key: 'teralink-resume', timeout: 60000 }, autopauseOnEmpty: true });
Join our Discord server for support, or check out the GitHub repository for examples and issues.