happy right now
This commit is contained in:
parent
93994d5995
commit
48463f8eaf
4 changed files with 6922 additions and 28 deletions
|
|
@ -1 +1 @@
|
||||||
{"access_token": "BQAMCHC8-xUmBuvLsfPGL-cTN8YH_moz_up1xx8fMIxqQTqSXlwo2R0samLLNnq6qM31CfLC_2XM7SkGjCxCSbGOUs0qaVDO3f2Dv7fbsFSuNmR3pFKfICDJdUCxjR3BA6jlJD_03emn8-mgVQx605QTFmNlK8uOTrwBAjaY_Pxww3XSLnpTm3coHDrc8astutR0MeEUlm9894AI3GXh-F0g7IDKdGHiKQhd2sVHgCm41Q355igboNTBMdAVkVGW", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1752637352, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"}
|
{"access_token": "BQBnvqMpOwqMzo5WbMGTkdmXGAnz-XQH7yfzsmlMIOyjdT1HG9HS6x8XtEfZ65F90RTO948crkDprgcqdP7Ryh54wxWxK-b6bNB2K9InQOXeVHUEwCwaO7fQ3H-PMVGYr0EGXp_EhkEYn4l3H_ps6MWr2r4sPfPw5lTP8o4qvIjHe8AYttlffxA2exNMrN2S2Ed668PYyvCwu4b2THNXsBH73EJHXP55bwg0Mo35i9PjdGgdJs30MbKcFZfdfbOS", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1752649260, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"}
|
||||||
6838
logs/app.log
6838
logs/app.log
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -4453,12 +4453,9 @@ class TabbedDownloadManager(QTabWidget):
|
||||||
|
|
||||||
def move_to_finished(self, download_item):
|
def move_to_finished(self, download_item):
|
||||||
"""Move a download item from active to finished queue"""
|
"""Move a download item from active to finished queue"""
|
||||||
print(f"[DEBUG] move_to_finished() called for '{download_item.title}' with status '{download_item.status}'")
|
|
||||||
print(f"[DEBUG] Finished queue currently has {len(self.finished_queue.download_items)} items")
|
|
||||||
|
|
||||||
if download_item in self.active_queue.download_items:
|
if download_item in self.active_queue.download_items:
|
||||||
# Remove from active queue
|
# Remove from active queue
|
||||||
print(f"[DEBUG] Removing '{download_item.title}' from active queue...")
|
|
||||||
self.active_queue.remove_download_item(download_item)
|
self.active_queue.remove_download_item(download_item)
|
||||||
|
|
||||||
# Ensure completed downloads have 100% progress
|
# Ensure completed downloads have 100% progress
|
||||||
|
|
@ -4468,7 +4465,6 @@ class TabbedDownloadManager(QTabWidget):
|
||||||
print(f"[DEBUG] Ensuring completed download '{download_item.title}' has 100% progress")
|
print(f"[DEBUG] Ensuring completed download '{download_item.title}' has 100% progress")
|
||||||
|
|
||||||
# Add to finished queue
|
# Add to finished queue
|
||||||
print(f"[DEBUG] Adding '{download_item.title}' to finished queue with status '{download_item.status}'...")
|
|
||||||
finished_item = self.finished_queue.add_download_item(
|
finished_item = self.finished_queue.add_download_item(
|
||||||
title=download_item.title,
|
title=download_item.title,
|
||||||
artist=download_item.artist,
|
artist=download_item.artist,
|
||||||
|
|
@ -4481,33 +4477,42 @@ class TabbedDownloadManager(QTabWidget):
|
||||||
username=download_item.username,
|
username=download_item.username,
|
||||||
soulseek_client=download_item.soulseek_client
|
soulseek_client=download_item.soulseek_client
|
||||||
)
|
)
|
||||||
print(f"[DEBUG] Finished queue now has {len(self.finished_queue.download_items)} items")
|
|
||||||
|
|
||||||
# Signal API that download is complete (only for completed downloads)
|
# Signal API that download is complete (only for completed downloads)
|
||||||
# Note: Cancelled downloads already have their API signal sent by cancel_download()
|
# Note: Cancelled downloads already have their API signal sent by cancel_download()
|
||||||
try:
|
try:
|
||||||
if (download_item.status == 'completed' and
|
if (download_item.status == 'completed' and
|
||||||
download_item.download_id and download_item.username and download_item.soulseek_client):
|
download_item.download_id and download_item.username and download_item.soulseek_client):
|
||||||
import asyncio
|
|
||||||
|
|
||||||
# Run the async API call to signal completion
|
# PERFORMANCE FIX: Run API cleanup in background thread to prevent UI blocking
|
||||||
loop = asyncio.new_event_loop()
|
def cleanup_completed_download():
|
||||||
asyncio.set_event_loop(loop)
|
try:
|
||||||
success = loop.run_until_complete(
|
import asyncio
|
||||||
download_item.soulseek_client.signal_download_completion(
|
loop = asyncio.new_event_loop()
|
||||||
download_item.download_id,
|
asyncio.set_event_loop(loop)
|
||||||
download_item.username,
|
success = loop.run_until_complete(
|
||||||
remove=True # Remove completed downloads from transfer list
|
download_item.soulseek_client.signal_download_completion(
|
||||||
)
|
download_item.download_id,
|
||||||
)
|
download_item.username,
|
||||||
loop.close()
|
remove=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print(f"✓ Successfully signaled completion for download {download_item.download_id}")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Failed to signal completion for download {download_item.download_id}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Error signaling download completion: {e}")
|
||||||
|
|
||||||
|
# Run in background thread to prevent UI blocking
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
with ThreadPoolExecutor(max_workers=1) as executor:
|
||||||
|
executor.submit(cleanup_completed_download)
|
||||||
|
|
||||||
if success:
|
|
||||||
print(f"✓ Successfully signaled completion for download {download_item.download_id}")
|
|
||||||
else:
|
|
||||||
print(f"⚠️ Failed to signal completion for download {download_item.download_id}")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Error signaling download completion: {e}")
|
print(f"⚠️ Error setting up download completion cleanup: {e}")
|
||||||
|
|
||||||
self.update_tab_counts()
|
self.update_tab_counts()
|
||||||
return finished_item
|
return finished_item
|
||||||
|
|
@ -8968,7 +8973,6 @@ class DownloadsPage(QWidget):
|
||||||
download_ext = os.path.splitext(download_item.file_path)[1].lower()
|
download_ext = os.path.splitext(download_item.file_path)[1].lower()
|
||||||
transfer_ext = os.path.splitext(basename)[1].lower()
|
transfer_ext = os.path.splitext(basename)[1].lower()
|
||||||
|
|
||||||
print(f"[DEBUG] Comparing extensions: download='{download_ext}' vs transfer='{transfer_ext}' for '{basename}'")
|
|
||||||
|
|
||||||
# Strategy 1: Direct filename match (most reliable)
|
# Strategy 1: Direct filename match (most reliable)
|
||||||
if basename_lower == download_title_lower + '.mp3' or basename_lower == download_title_lower + '.flac':
|
if basename_lower == download_title_lower + '.mp3' or basename_lower == download_title_lower + '.flac':
|
||||||
|
|
@ -9043,10 +9047,9 @@ class DownloadsPage(QWidget):
|
||||||
if matches:
|
if matches:
|
||||||
matching_transfer = transfer
|
matching_transfer = transfer
|
||||||
matched_transfer_ids.add(transfer_id)
|
matched_transfer_ids.add(transfer_id)
|
||||||
print(f"[DEBUG] ✅ Found filename match: {match_reason}")
|
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print(f"[DEBUG] ❌ No match: download_title='{download_title_lower}' vs filename='{basename_lower}'")
|
pass # No match found, continue to next transfer
|
||||||
|
|
||||||
if not matching_transfer:
|
if not matching_transfer:
|
||||||
print(f"[DEBUG] ⚠️ No matching transfer found for download_title='{download_item.title}' by artist='{download_item.artist}'")
|
print(f"[DEBUG] ⚠️ No matching transfer found for download_title='{download_item.title}' by artist='{download_item.artist}'")
|
||||||
|
|
@ -9064,7 +9067,6 @@ class DownloadsPage(QWidget):
|
||||||
if 'Completed' in state or 'Succeeded' in state:
|
if 'Completed' in state or 'Succeeded' in state:
|
||||||
progress = 100
|
progress = 100
|
||||||
|
|
||||||
print(f"[DEBUG] Found transfer for '{download_item.title}': {state} - {progress:.1f}%")
|
|
||||||
|
|
||||||
# Map slskd states to our download states (handle compound states)
|
# Map slskd states to our download states (handle compound states)
|
||||||
if 'InProgress' in state:
|
if 'InProgress' in state:
|
||||||
|
|
@ -9151,6 +9153,35 @@ class DownloadsPage(QWidget):
|
||||||
download_speed=0, # No speed for failed
|
download_speed=0, # No speed for failed
|
||||||
file_path=download_item.file_path
|
file_path=download_item.file_path
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# IMMEDIATE CLEANUP: Remove errored download from API immediately
|
||||||
|
if download_item.download_id and download_item.username and download_item.soulseek_client:
|
||||||
|
def cleanup_errored_download():
|
||||||
|
try:
|
||||||
|
import asyncio
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
asyncio.set_event_loop(loop)
|
||||||
|
success = loop.run_until_complete(
|
||||||
|
download_item.soulseek_client.cancel_download(
|
||||||
|
download_item.download_id,
|
||||||
|
download_item.username,
|
||||||
|
remove=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print(f"✓ Immediately cleaned up errored download {download_item.download_id}")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Failed to clean up errored download {download_item.download_id}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Error cleaning up errored download: {e}")
|
||||||
|
|
||||||
|
# Run cleanup in background thread
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
with ThreadPoolExecutor(max_workers=1) as executor:
|
||||||
|
executor.submit(cleanup_errored_download)
|
||||||
|
|
||||||
print(f"[DEBUG] Moving failed download '{download_item.title}' to finished queue")
|
print(f"[DEBUG] Moving failed download '{download_item.title}' to finished queue")
|
||||||
self.download_queue.move_to_finished(download_item)
|
self.download_queue.move_to_finished(download_item)
|
||||||
continue
|
continue
|
||||||
|
|
@ -9159,6 +9190,10 @@ class DownloadsPage(QWidget):
|
||||||
else:
|
else:
|
||||||
new_status = state.lower()
|
new_status = state.lower()
|
||||||
|
|
||||||
|
# Reset API missing counter since we found the download
|
||||||
|
if hasattr(download_item, 'api_missing_count'):
|
||||||
|
download_item.api_missing_count = 0
|
||||||
|
|
||||||
# Update the download item with real-time data
|
# Update the download item with real-time data
|
||||||
download_item.update_status(
|
download_item.update_status(
|
||||||
status=new_status,
|
status=new_status,
|
||||||
|
|
@ -9189,13 +9224,34 @@ class DownloadsPage(QWidget):
|
||||||
# Remove from finished queue since it's no longer in slskd
|
# Remove from finished queue since it's no longer in slskd
|
||||||
self.download_queue.finished_queue.remove_download_item(download_item)
|
self.download_queue.finished_queue.remove_download_item(download_item)
|
||||||
continue
|
continue
|
||||||
|
# CRITICAL FIX: Handle active downloads that disappeared from API (errored/cancelled in backend)
|
||||||
|
elif download_item in self.download_queue.active_queue.download_items:
|
||||||
|
# Add grace period to avoid false positives during API delays
|
||||||
|
if not hasattr(download_item, 'api_missing_count'):
|
||||||
|
download_item.api_missing_count = 0
|
||||||
|
|
||||||
|
download_item.api_missing_count += 1
|
||||||
|
print(f"[DEBUG] ⚠️ Active download '{download_item.title}' not found in API (count: {download_item.api_missing_count}/3)")
|
||||||
|
|
||||||
|
# Only mark as failed after 3 consecutive misses (3 seconds with 1s polling)
|
||||||
|
if download_item.api_missing_count >= 3:
|
||||||
|
print(f"[DEBUG] ⚠️ Active download '{download_item.title}' consistently missing from API - marking as failed")
|
||||||
|
# Update status to failed since it's gone from API (likely errored or cancelled)
|
||||||
|
download_item.update_status(
|
||||||
|
status='failed',
|
||||||
|
progress=download_item.progress,
|
||||||
|
download_speed=0,
|
||||||
|
file_path=download_item.file_path
|
||||||
|
)
|
||||||
|
# Move to finished queue so user can see it failed
|
||||||
|
self.download_queue.move_to_finished(download_item)
|
||||||
|
continue
|
||||||
|
|
||||||
# After processing all download items, check for any that weren't found in the API
|
# After processing all download items, check for any that weren't found in the API
|
||||||
# This handles the case where downloads were removed from slskd externally
|
# This handles the case where downloads were removed from slskd externally
|
||||||
|
|
||||||
# Update download counters after processing all transfers
|
# Update download counters after processing all transfers
|
||||||
self.download_queue.update_tab_counts()
|
self.download_queue.update_tab_counts()
|
||||||
print(f"[DEBUG] Updated tab counts - Active: {len(self.download_queue.active_queue.download_items)}, Finished: {len(self.download_queue.finished_queue.download_items)}")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] Error processing transfer status update: {e}")
|
print(f"[ERROR] Error processing transfer status update: {e}")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue