Skip to main content
The Search class manages file searches across the Soulseek network, handling search queries, results, and wishlist functionality.

Overview

The Search module provides:
  • Global file searches across the network
  • User-specific searches
  • Room-specific searches
  • Wishlist functionality for automatic searches
  • Search result filtering and sorting
  • Search history management

Search Class

Initialization

from pynicotine.search import Search

search = Search()

Core Search Methods

Performs a search across the network.
token = search.do_search(search_term, mode, users=None, room=None)
search_term
str
required
The search query string
mode
str
required
Search mode: “global”, “buddies”, “rooms”, or “user”
users
list
List of specific users to search (for “user” mode)
room
str
Room name to search in (for “rooms” mode)
token
int
Unique search token for tracking results
# Example: Global search
token = search.do_search("electronic music flac", "global")
print(f"Search started with token: {token}")

# Example: User-specific search
token = search.do_search("discography", "user", users=["username1", "username2"])

# Example: Room search
token = search.do_search("album", "rooms", room="Music")

add_allowed_token()

Adds a token to the allowed list for receiving results.
search.add_allowed_token(token)
token
int
required
Search token to allow

remove_allowed_token()

Removes a token from the allowed list.
search.remove_allowed_token(token)
token
int
required
Search token to remove

Search Result Methods

process_search_term()

Processes and normalizes a search term.
processed_term, excluded_words = search.process_search_term(search_term)
search_term
str
required
Raw search query
processed_term
str
Normalized search term
excluded_words
set
Set of words to exclude (words starting with ”-“)
# Example: Process search with exclusions
term, excluded = search.process_search_term("rock music -metal -punk")
print(f"Search: {term}")  # "rock music"
print(f"Exclude: {excluded}")  # {"metal", "punk"}

append_search_results()

Appends new results to an existing search.
search.append_search_results(token, username, results)
token
int
required
Search token
username
str
required
Username who provided the results
results
list
required
List of file results

get_search_results()

Retrieves results for a search token.
results = search.get_search_results(token)
token
int
required
Search token
results
dict
Dictionary mapping usernames to their results

Wishlist Methods

add_wish()

Adds a search term to the wishlist for automatic searches.
search.add_wish(search_term)
search_term
str
required
Search term to add to wishlist
# Add wishlist items
search.add_wish("rare vinyl rip")
search.add_wish("unreleased album")

remove_wish()

Removes a search term from the wishlist.
search.remove_wish(search_term)
search_term
str
required
Search term to remove

get_wishlist()

Retrieves the current wishlist.
wishlist = search.get_wishlist()
wishlist
list
List of wishlist search terms

is_wish()

Checks if a search term is in the wishlist.
is_wishlist = search.is_wish(search_term)
is_wishlist
bool
True if term is in wishlist

Search History

add_search_history()

Adds a search term to the history.
search.add_search_history(search_term)
search_term
str
required
Search term to add to history

get_search_history()

Retrieves recent search history.
history = search.get_search_history()
history
list
List of recent search terms

Search Modes

Searches all users connected to the network:
token = search.do_search("jazz collection", "global")
Searches only users on your buddy list:
token = search.do_search("rare tracks", "buddies")
Searches users in a specific chat room:
token = search.do_search("soundtrack", "rooms", room="Soundtracks")
Searches specific users:
token = search.do_search(
    "complete discography",
    "user",
    users=["user1", "user2", "user3"]
)

Events

The Search module emits events for search lifecycle:
from pynicotine.events import events

# Search started
events.connect("search-started", on_search_started)

# Search results received
events.connect("search-results", on_search_results)

# Search finished
events.connect("search-finished", on_search_finished)

def on_search_started(token, search_term):
    print(f"Search '{search_term}' started (token: {token})")

def on_search_results(token, username, results):
    print(f"Received {len(results)} results from {username}")
    for result in results:
        print(f"  - {result['file']} ({result['size']} bytes)")

def on_search_finished(token):
    print(f"Search {token} completed")

Result Filtering

Filter by File Type

def filter_audio_files(results):
    audio_extensions = {'.mp3', '.flac', '.ogg', '.m4a', '.wav'}
    filtered = []
    
    for username, user_results in results.items():
        for result in user_results:
            file_path = result['file'].lower()
            if any(file_path.endswith(ext) for ext in audio_extensions):
                filtered.append((username, result))
    
    return filtered

# Get and filter results
results = search.get_search_results(token)
audio_files = filter_audio_files(results)

Filter by File Size

def filter_by_size(results, min_size=None, max_size=None):
    filtered = []
    
    for username, user_results in results.items():
        for result in user_results:
            size = result['size']
            
            if min_size and size < min_size:
                continue
            if max_size and size > max_size:
                continue
                
            filtered.append((username, result))
    
    return filtered

# Filter for files between 10MB and 100MB
results = search.get_search_results(token)
filtered = filter_by_size(results, min_size=10*1024*1024, max_size=100*1024*1024)

Complete Example

from pynicotine.search import Search
from pynicotine.events import events
from pynicotine.core import core

# Initialize search
search = Search()

# Track search results
search_results = {}

def on_search_results(token, username, results):
    if token not in search_results:
        search_results[token] = {}
    
    search_results[token][username] = results
    print(f"Got {len(results)} results from {username}")
    
    # Filter for high-quality audio
    for result in results:
        bitrate = result.get('bitrate', 0)
        if bitrate >= 320:  # High quality MP3 or lossless
            print(f"  HQ: {result['file']} ({bitrate} kbps)")

def on_search_finished(token):
    if token in search_results:
        total_results = sum(len(r) for r in search_results[token].values())
        total_users = len(search_results[token])
        print(f"Search complete: {total_results} results from {total_users} users")

# Connect events
events.connect("search-results", on_search_results)
events.connect("search-finished", on_search_finished)

# Perform searches
token1 = search.do_search("electronic music flac", "global")
token2 = search.do_search("ambient", "buddies")

# Add to wishlist for automatic searches
search.add_wish("rare vinyl rip")
search.add_wish("remastered edition")

# Add to search history
search.add_search_history("electronic music flac")

Best Practices

  • Use specific search terms to reduce irrelevant results
  • Leverage exclusion words (prefix with ”-”) to filter unwanted content
  • Use wishlist for ongoing searches of rare content
  • Store search tokens to correlate results with queries
  • Filter results by file attributes (size, bitrate, format) client-side
  • Limit simultaneous searches to avoid server throttling
  • Use room or buddy searches for more targeted results

Build docs developers (and LLMs) love