> ## Documentation Index
> Fetch the complete documentation index at: https://salad-ffed6391.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Searching

> Search for tracks across different platforms and handle various search result types

## Searching

Search for tracks across different platforms and handle various search result types.

## Basic Search

```python theme={null}
result = await bot.salad.resolve(
    'Rick Astley Never Gonna Give You Up',
    requester=interaction.user
)

print('Search results:')
print(f'Type: {result.get("loadType")}')
print(f'Tracks found: {len(result.get("tracks", []))}')

if result.get('tracks'):
    track = result['tracks'][0]
    print(f'First result: {track.title} by {track.author}')
```

## Platform-Specific Searches

```python theme={null}
yt_result = await bot.salad.resolve(
    'Imagine Dragons Believer',
    source='ytsearch',
    requester=interaction.user
)

spotify_result = await bot.salad.resolve(
    'https://open.spotify.com/track/...',
    source='ytsearch',
    requester=interaction.user
)

sc_result = await bot.salad.resolve(
    'Lofi Hip Hop',
    source='scsearch',
    requester=interaction.user
)

ytmusic_result = await bot.salad.resolve(
    'Classical Music',
    source='ytmsearch',
    requester=interaction.user
)
```

## Search Result Types

### Handling Different Result Types

```python theme={null}
result = await bot.salad.resolve(query, requester=interaction.user)

load_type = result.get('loadType')

if load_type == 'track':
    track = result['tracks'][0]
    player.addToQueue(track)
    await interaction.followup.send(f'🎵 Added **{track.title}** to queue')
    
elif load_type == 'playlist':
    tracks = result['tracks']
    for track in tracks:
        player.addToQueue(track)
    
    playlist_info = result.get('playlistInfo', {})
    playlist_name = playlist_info.get('name', 'Unknown')
    await interaction.followup.send(
        f'📋 Added **{len(tracks)}** tracks from **{playlist_name}**'
    )
    
elif load_type == 'search':
    if not result.get('tracks'):
        await interaction.followup.send('❌ No tracks found!')
    else:
        track = result['tracks'][0]
        player.addToQueue(track)
        await interaction.followup.send(f'🎵 Added **{track.title}** to queue')
        
elif load_type == 'empty':
    await interaction.followup.send('❌ No results found for your search.')
    
elif load_type == 'error':
    error = result.get('exception', {})
    await interaction.followup.send(f'❌ Search error: {error.get("message", "Unknown error")}')
```

## Advanced Search Options

### Search with Selection Menu

```python theme={null}
import discord
from discord.ui import Select, View

result = await bot.salad.resolve('epic music', requester=interaction.user)

if result.get('tracks') and len(result['tracks']) > 1:
    options = []
    for i, track in enumerate(result['tracks'][:5]):
        options.append(discord.SelectOption(
            label=track.title[:100],
            description=f'By {track.author}'[:100],
            value=str(i)
        ))
    
    select = Select(
        placeholder='Choose a track',
        options=options
    )
    
    async def select_callback(interaction: discord.Interaction):
        index = int(select.values[0])
        selected_track = result['tracks'][index]
        
        player = bot.salad.getPlayer(interaction.guild.id)
        if player:
            player.addToQueue(selected_track)
            await interaction.response.send_message(
                f'✅ Added **{selected_track.title}** to queue'
            )
    
    select.callback = select_callback
    
    view = View()
    view.add_item(select)
    
    await interaction.followup.send('Select a track:', view=view)
```

### Direct URL Resolution

```python theme={null}
url_result = await bot.salad.resolve(
    'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
    requester=interaction.user
)

load_type = url_result.get('loadType')

if load_type == 'track':
    track = url_result['tracks'][0]
    player.addToQueue(track)
    await interaction.followup.send(f'🔗 Added track from URL: **{track.title}**')
    
elif load_type == 'playlist':
    tracks = url_result['tracks']
    for track in tracks:
        player.addToQueue(track)
    await interaction.followup.send(f'🔗 Added **{len(tracks)}** tracks from playlist URL')
```

## Error Handling

### Search Error Management

```python theme={null}
async def safe_search(query: str, requester, interaction: discord.Interaction):
    try:
        result = await bot.salad.resolve(query, requester=requester)
        
        if not result or not result.get('tracks'):
            await interaction.followup.send('❌ No tracks found for your search.')
            return None
        
        return result
        
    except Exception as error:
        print(f'Search error: {error}')
        
        error_msg = str(error)
        
        if 'timeout' in error_msg.lower():
            await interaction.followup.send('⏱️ Search timed out. Please try again.')
        elif 'unavailable' in error_msg.lower():
            await interaction.followup.send('❌ This track is not available in your region.')
        else:
            await interaction.followup.send('❌ An error occurred while searching. Please try again.')
        
        return None

result = await safe_search('some query', interaction.user, interaction)
if result:
    pass
```

## Complete Search Command Example

```python theme={null}
from discord import app_commands
import discord

@bot.tree.command(name='search')
@app_commands.describe(query='Search query or URL')
async def search_command(interaction: discord.Interaction, query: str):
    await interaction.response.defer()
    
    if not interaction.user.voice:
        await interaction.followup.send('❌ Join a voice channel first!')
        return
    
    player = bot.salad.getPlayer(interaction.guild.id)
    if not player:
        player = await bot.salad.createConnection({
            'guildId': interaction.guild.id,
            'voiceChannel': interaction.user.voice.channel.id,
            'textChannel': interaction.channel.id
        })
        await interaction.user.voice.channel.connect()
    
    try:
        result = await bot.salad.resolve(query, requester=interaction.user)
        
        load_type = result.get('loadType')
        
        if load_type == 'empty':
            await interaction.followup.send('❌ No results found!')
            return
        
        if load_type == 'error':
            error = result.get('exception', {})
            await interaction.followup.send(f'❌ Error: {error.get("message", "Unknown error")}')
            return
        
        tracks = result.get('tracks', [])
        if not tracks:
            await interaction.followup.send('❌ No tracks found!')
            return
        
        if load_type == 'playlist':
            for track in tracks:
                player.addToQueue(track)
            
            playlist_info = result.get('playlistInfo', {})
            playlist_name = playlist_info.get('name', 'Unknown Playlist')
            
            embed = discord.Embed(
                title='📋 Playlist Added',
                description=f'Added **{len(tracks)}** tracks from **{playlist_name}**',
                color=discord.Color.green()
            )
            
            if not player.playing:
                await player.play()
            
            await interaction.followup.send(embed=embed)
            
        else:
            track = tracks[0]
            player.addToQueue(track)
            
            embed = discord.Embed(
                title='🎵 Track Added',
                description=f'**{track.title}**\nBy {track.author}',
                color=discord.Color.blue()
            )
            
            if hasattr(track, 'duration'):
                duration = track.duration
                duration_str = f'{duration // 60000}:{(duration // 1000) % 60:02d}'
                embed.add_field(name='Duration', value=duration_str)
            
            if not player.playing:
                await player.play()
                embed.title = '▶️ Now Playing'
            else:
                embed.add_field(name='Position', value=f'#{len(player.queue)}')
            
            await interaction.followup.send(embed=embed)
            
    except Exception as e:
        await interaction.followup.send(f'❌ Search failed: {str(e)}')
```

## Multi-Result Search Command

```python theme={null}
from discord.ui import Button, View

@bot.tree.command(name='find')
@app_commands.describe(query='Search for multiple results')
async def find_command(interaction: discord.Interaction, query: str):
    await interaction.response.defer()
    
    try:
        result = await bot.salad.resolve(query, source='ytsearch', requester=interaction.user)
        
        tracks = result.get('tracks', [])
        if not tracks:
            await interaction.followup.send('❌ No results found!')
            return
        
        embed = discord.Embed(
            title='🔍 Search Results',
            description='',
            color=discord.Color.blue()
        )
        
        for i, track in enumerate(tracks[:5], 1):
            duration = track.duration if hasattr(track, 'duration') else 0
            duration_str = f'{duration // 60000}:{(duration // 1000) % 60:02d}'
            embed.add_field(
                name=f'{i}. {track.title[:50]}',
                value=f'By {track.author} • {duration_str}',
                inline=False
            )
        
        class SearchView(View):
            def __init__(self, tracks):
                super().__init__(timeout=60)
                self.tracks = tracks
                
                for i in range(min(5, len(tracks))):
                    button = Button(label=str(i + 1), style=discord.ButtonStyle.primary)
                    button.callback = self.create_callback(i)
                    self.add_item(button)
            
            def create_callback(self, index):
                async def callback(interaction: discord.Interaction):
                    player = bot.salad.getPlayer(interaction.guild.id)
                    if player:
                        track = self.tracks[index]
                        player.addToQueue(track)
                        
                        if not player.playing:
                            await player.play()
                        
                        await interaction.response.send_message(
                            f'✅ Added **{track.title}** to queue',
                            ephemeral=True
                        )
                    else:
                        await interaction.response.send_message(
                            '❌ No active player!',
                            ephemeral=True
                        )
                return callback
        
        view = SearchView(tracks)
        await interaction.followup.send(embed=embed, view=view)
        
    except Exception as e:
        await interaction.followup.send(f'❌ Search failed: {str(e)}')
```

## Search Sources

Available search sources in Salada:

* `ytsearch` - YouTube search
* `ytmsearch` - YouTube Music search
* `scsearch` - SoundCloud search

Direct URLs are automatically detected and don't need a source prefix.

<Tip>
  Use `ytsearch` for general searches. It will return the most relevant results from YouTube.
</Tip>

<Warning>
  Always handle empty results and errors gracefully. Network issues or API rate limits can cause search failures.
</Warning>
