# Getting Started

This guide will help you create your first Discord music bot using Sonora v1.2.8.

# Prerequisites

Before you begin, make sure you have:

  • Python 3.11 or higher
  • A Discord bot token (from Discord Developer Portal)
  • A Lavalink server running (see Installation guide)

# Table of Contents

  • Basic Bot Setup
  • Adding Music Commands
  • Advanced Features
  • Error Handling
  • Next Steps

# Basic Bot Setup

# 1. Install Sonora

pip install sonora

# 2. Create Your Bot File

Create a new file called bot.py:

import discord
from discord.ext import commands
from sonora import SonoraClient

# Create the bot
bot = commands.Bot(command_prefix='!', intents=discord.Intents.all())

# Create Sonora client
sonora = SonoraClient(
    lavalink_nodes=[{
        "host": "localhost",  # Your Lavalink server host
        "port": 2333,         # Lavalink port
        "password": "youshallnotpass"  # Lavalink password
    }]
)

@bot.event
async def on_ready():
    await sonora.start()
    print(f"🤖 {bot.user} is ready!")
    print(f"đŸŽĩ Sonora connected to {len(sonora.nodes)} Lavalink nodes")

# Run the bot
bot.run('YOUR_BOT_TOKEN_HERE')

# 3. Replace the Bot Token

Replace 'YOUR_BOT_TOKEN_HERE' with your actual Discord bot token from the Developer Portal.

# 4. Run Your Bot

python bot.py

# Adding Music Commands

# Join Command

@bot.command()
async def join(ctx):
    """Join the user's voice channel"""
    if ctx.author.voice:
        channel = ctx.author.voice.channel
        await channel.connect()
        player = await sonora.get_player(ctx.guild.id)
        await ctx.send(f"đŸŽĩ Joined {channel.name}")
    else:
        await ctx.send("❌ You need to be in a voice channel!")

# Play Command

@bot.command()
async def play(ctx, *, query):
    """Play music from a URL or search query"""
    player = await sonora.get_player(ctx.guild.id)

    # Check if user is in voice channel
    if not ctx.author.voice:
        return await ctx.send("❌ You need to be in a voice channel!")

    # Join voice channel if not connected
    if not ctx.voice_client:
        await ctx.author.voice.channel.connect()

    # Search and play
    try:
        track = await player.play(query)
        await ctx.send(f"đŸŽĩ Now playing: **{track.title}**")
    except Exception as e:
        await ctx.send(f"❌ Error: {str(e)}")

# Stop Command

@bot.command()
async def stop(ctx):
    """Stop playback and clear the queue"""
    player = await sonora.get_player(ctx.guild.id)
    await player.stop()
    await ctx.send("âšī¸ Stopped playback")

# Skip Command

@bot.command()
async def skip(ctx):
    """Skip to the next track"""
    player = await sonora.get_player(ctx.guild.id)
    next_track = await player.skip()

    if next_track:
        await ctx.send(f"â­ī¸ Skipped! Now playing: **{next_track.title}**")
    else:
        await ctx.send("â­ī¸ Skipped! (No more tracks in queue)")

# Queue Command

@bot.command()
async def queue(ctx):
    """Show the current queue"""
    player = await sonora.get_player(ctx.guild.id)

    if player.current:
        embed = discord.Embed(title="đŸŽĩ Current Queue", color=0x00ff00)
        embed.add_field(
            name="Now Playing",
            value=f"**{player.current.title}**",
            inline=False
        )

        upcoming = list(player.queue.upcoming)[:5]  # Show first 5
        if upcoming:
            queue_list = "\n".join(
                f"{i+1}. {track.title}" for i, track in enumerate(upcoming)
            )
            embed.add_field(
                name="Up Next",
                value=queue_list,
                inline=False
            )

        embed.set_footer(text=f"Total tracks: {len(player.queue.upcoming) + 1}")
        await ctx.send(embed=embed)
    else:
        await ctx.send("đŸŽĩ No music currently playing")

# Advanced Features

# Audio Filters

@bot.command()
async def bassboost(ctx, level: str = "medium"):
    """Apply bass boost filter"""
    player = await sonora.get_player(ctx.guild.id)

    levels = {
        "low": 0.2,
        "medium": 0.4,
        "high": 0.6,
        "extreme": 0.8
    }

    if level not in levels:
        return await ctx.send("❌ Invalid level! Use: low, medium, high, extreme")

    await player.set_filter("bassboost", gain=levels[level])
    await ctx.send(f"đŸŽ›ī¸ Bass boost set to {level}")

@bot.command()
async def nightcore(ctx):
    """Apply nightcore effect"""
    player = await sonora.get_player(ctx.guild.id)
    await player.set_filter("nightcore")
    await ctx.send("🌙 Nightcore mode activated!")

@bot.command()
async def clearfilters(ctx):
    """Remove all audio filters"""
    player = await sonora.get_player(ctx.guild.id)
    await player.clear_filters()
    await ctx.send("đŸŽ›ī¸ All filters cleared")

# Autoplay

@bot.command()
async def autoplay(ctx, state: str = None):
    """Control autoplay feature"""
    player = await sonora.get_player(ctx.guild.id)

    if state is None:
        # Show current status
        status = "ON" if player.autoplay.enabled else "OFF"
        strategy = player.autoplay.strategy
        await ctx.send(f"đŸŽĩ Autoplay: {status} (Strategy: {strategy})")
        return

    if state.lower() == "on":
        player.autoplay.enabled = True
        await ctx.send("đŸŽĩ Autoplay enabled!")
    elif state.lower() == "off":
        player.autoplay.enabled = False
        await ctx.send("đŸŽĩ Autoplay disabled!")
    else:
        await ctx.send("❌ Use: !autoplay on/off")

# Volume Control

@bot.command()
async def volume(ctx, vol: int = None):
    """Set or show volume (0-100)"""
    player = await sonora.get_player(ctx.guild.id)

    if vol is None:
        # Show current volume
        await ctx.send(f"🔊 Current volume: {player.volume}%")
        return

    if not 0 <= vol <= 100:
        await ctx.send("❌ Volume must be between 0 and 100")
        return

    await player.set_volume(vol * 10)  # Sonora uses 0-1000 scale
    await ctx.send(f"🔊 Volume set to {vol}%")

# Error Handling

# Global Error Handler

@bot.event
async def on_command_error(ctx, error):
    """Handle command errors"""
    if isinstance(error, commands.CommandNotFound):
        return  # Ignore unknown commands

    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("❌ Missing required argument!")
        return

    # Log other errors
    print(f"Error in {ctx.command}: {error}")

    # Send user-friendly message
    await ctx.send("❌ An error occurred while processing your command")

# Voice State Handling

@bot.event
async def on_voice_state_update(member, before, after):
    """Handle voice state changes"""
    if member == bot.user:
        # Bot's voice state changed
        if before.channel and not after.channel:
            # Bot was disconnected
            player = await sonora.get_player(member.guild.id)
            await player.destroy()
            print("đŸŽĩ Bot disconnected from voice")

# Next Steps

Now that you have a basic music bot working, here are some next steps:

# 1. Add More Commands

  • pause / resume commands
  • shuffle command for the queue
  • loop command for repeat modes
  • lyrics command to show song lyrics

# 2. Explore Advanced Features

# 3. Deployment

  • Set up a Lavalink server
  • Deploy your bot to a server
  • Configure environment variables
  • Set up monitoring and logging

# 4. Community

# Troubleshooting

# Common Issues

"No module named 'sonora'"

  • Make sure Sonora is installed: pip install sonora

"Connection refused"

  • Check if your Lavalink server is running
  • Verify the host and port in your configuration

"No audio" or "Robot voice"

  • Check your Lavalink server configuration
  • Ensure proper audio encoding settings

Bot doesn't respond

  • Check your bot token
  • Make sure the bot has proper permissions
  • Verify the command prefix

For more help, check the troubleshooting guide or ask in our Discord server.