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.

๐ŸŽ‰ What's New in v0.2.0

Smart search with automatic source detection, enhanced error handling with retry logic, performance monitoring, automatic memory management, and comprehensive queue analytics.

๐Ÿš€ Getting Started

Installation

Terminal
npm install teralink

Basic Setup

JavaScript
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');
โœจ Automatic Features

Performance monitoring and memory management start automatically. No additional configuration needed!

๐ŸŒŸ Key Features

๐Ÿง 
Smart Search
Automatic source detection, query enhancement, and intelligent search optimization for better results.
๐Ÿ›ก๏ธ
Enhanced Error Handling
Intelligent retry logic with exponential backoff and automatic error recovery for network issues.
๐Ÿ“Š
Performance Monitoring
Real-time metrics tracking including cache hit rates, memory usage, and response times.
๐Ÿงน
Memory Management
Automatic memory cleanup, leak prevention, and intelligent garbage collection.
๐Ÿ”
Advanced Queue Analytics
Comprehensive queue statistics, search functionality, and duplicate detection.
โšก
Enhanced Caching
2.5x larger cache size with longer TTL for improved hit rates and performance.

๐Ÿ“ˆ Performance Monitoring

Getting Performance Metrics

JavaScript
// 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

JavaScript
// 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

๐Ÿ›ก๏ธ Enhanced Error Handling

Automatic Retry Logic

JavaScript
// 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

JavaScript
// 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);
๐Ÿ”„ Automatic Retry Conditions

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

JavaScript
// 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

JavaScript
// 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

JavaScript
// 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

JavaScript
// 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

TypeScript
// Performance & Memory Management
getPerformanceMetrics(): PerformanceMetrics
resetPerformanceMetrics(): void
getMemoryUsage(): MemoryUsage
performMemoryCleanup(): void
startMemoryManagement(): void
stopMemoryManagement(): void

// Smart Search
smartSearch(query: string, requester: any, options?: SmartSearchOptions): Promise
batchSearch(queries: string[], requester: any, options?: BatchSearchOptions): Promise

Player Class

TypeScript
// Enhanced Play & Error Handling
play(retryAttempt?: number): Promise
restart(): 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

TypeScript
// 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

TypeScript
// Health Monitoring
getHealthStatus(): NodeHealthStatus
isHealthy(): boolean

๐Ÿ’ก Examples

Complete Music Bot Example

JavaScript
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

โœ… No Breaking Changes

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

JavaScript
// 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

JavaScript
// 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
});
๐Ÿ“– Need Help?

Join our Discord server for support, or check out the GitHub repository for examples and issues.