Add minimum peer upload speed setting and fix quality scoring tiers

New dropdown in Soulseek settings lets users filter out slow peers at
search time (Any/1/2/3/4/5/10 Mbps). Passes minimumPeerUploadSpeed
to slskd API in bytes/sec.

Also fixes quality scoring tiers which were using wrong units — old
thresholds (5000, 1000, 500) treated bytes/sec values as kbps,
making speed scoring effectively meaningless. Now uses correct
bytes/sec thresholds based on real peer data.
pull/253/head
Broque Thomas 2 months ago
parent b4da777bdc
commit 4a7f297b2c

@ -51,14 +51,14 @@ class SearchResult:
elif self.free_upload_slots > 0:
base_score += 0.05
# Upload speed (tiered)
if self.upload_speed >= 5000:
# Upload speed in bytes/sec (tiered)
if self.upload_speed >= 5_000_000: # ~5 MB/s / 40 Mbps
base_score += 0.15
elif self.upload_speed >= 1000:
elif self.upload_speed >= 1_000_000: # ~1 MB/s / 8 Mbps
base_score += 0.10
elif self.upload_speed >= 500:
elif self.upload_speed >= 500_000: # ~500 KB/s / 4 Mbps
base_score += 0.05
elif self.upload_speed < 100:
elif self.upload_speed < 100_000: # ~100 KB/s / 800 kbps
base_score -= 0.05
# Queue length (graduated penalty)
@ -184,14 +184,14 @@ class AlbumResult:
elif self.free_upload_slots > 0:
base_score += 0.05
# Upload speed (tiered)
if self.upload_speed >= 5000:
# Upload speed in bytes/sec (tiered)
if self.upload_speed >= 5_000_000: # ~5 MB/s / 40 Mbps
base_score += 0.15
elif self.upload_speed >= 1000:
elif self.upload_speed >= 1_000_000: # ~1 MB/s / 8 Mbps
base_score += 0.10
elif self.upload_speed >= 500:
elif self.upload_speed >= 500_000: # ~500 KB/s / 4 Mbps
base_score += 0.05
elif self.upload_speed < 100:
elif self.upload_speed < 100_000: # ~100 KB/s / 800 kbps
base_score -= 0.05
# Queue length (graduated penalty)
@ -478,7 +478,7 @@ class SoulseekClient:
upload_speed=response_data.get('uploadSpeed', 0),
queue_length=response_data.get('queueLength', 0)
)
all_tracks.append(track)
# Group tracks by album path for album detection
@ -646,8 +646,8 @@ class SoulseekClient:
return [], []
# Get timeout from config if not specified
from config.settings import config_manager
if timeout is None:
from config.settings import config_manager
timeout = config_manager.get('soulseek.search_timeout', 60)
# Apply rate limiting before search
@ -656,12 +656,16 @@ class SoulseekClient:
try:
logger.info(f"Starting search for: '{query}' (slskd timeout: {timeout}s)")
# Get minimum peer upload speed from config (stored as Mbps, API expects bytes/sec)
min_speed_mbps = config_manager.get('soulseek.min_peer_upload_speed', 0) or 0
min_speed_bytes = int(min_speed_mbps) * 125000 # 1 Mbps = 125000 bytes/sec
search_data = {
'searchText': query,
'timeout': timeout * 1000, # slskd expects milliseconds
'filterResponses': True,
'minimumResponseFileCount': 1,
'minimumPeerUploadSpeed': 0
'minimumPeerUploadSpeed': min_speed_bytes
}
logger.debug(f"Search data: {search_data}")

@ -3921,6 +3921,19 @@
<small class="settings-hint">Extra time to wait
for late results (5-60 seconds)</small>
</div>
<div class="form-group">
<label>Minimum Peer Upload Speed:</label>
<select id="soulseek-min-peer-speed">
<option value="0">Any speed</option>
<option value="1">1 Mbps</option>
<option value="2">2 Mbps</option>
<option value="3">3 Mbps</option>
<option value="4">4 Mbps</option>
<option value="5">5 Mbps</option>
<option value="10">10 Mbps</option>
</select>
<small class="settings-hint">Ignore search results from peers with upload speed below this threshold</small>
</div>
<div class="form-actions" style="margin-top: 8px;">
<button class="test-button" onclick="testConnection('soulseek')">Test Soulseek Connection</button>
</div>

@ -4829,6 +4829,7 @@ async function loadSettingsData() {
document.getElementById('soulseek-api-key').value = settings.soulseek?.api_key || '';
document.getElementById('soulseek-search-timeout').value = settings.soulseek?.search_timeout || 60;
document.getElementById('soulseek-search-timeout-buffer').value = settings.soulseek?.search_timeout_buffer || 15;
document.getElementById('soulseek-min-peer-speed').value = settings.soulseek?.min_peer_upload_speed || 0;
// Populate ListenBrainz settings
document.getElementById('listenbrainz-base-url').value = settings.listenbrainz?.base_url || '';
@ -5675,7 +5676,8 @@ async function saveSettings(quiet = false) {
download_path: document.getElementById('download-path').value,
transfer_path: document.getElementById('transfer-path').value,
search_timeout: parseInt(document.getElementById('soulseek-search-timeout').value) || 60,
search_timeout_buffer: parseInt(document.getElementById('soulseek-search-timeout-buffer').value) || 15
search_timeout_buffer: parseInt(document.getElementById('soulseek-search-timeout-buffer').value) || 15,
min_peer_upload_speed: parseInt(document.getElementById('soulseek-min-peer-speed').value) || 0
},
listenbrainz: {
base_url: document.getElementById('listenbrainz-base-url').value,

Loading…
Cancel
Save