From c3d12bde46ca11f8610133f2327ade809b2f5417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Tue, 5 May 2026 15:25:33 +0200 Subject: [PATCH] smart queue fix --- pytorrent/services/smart_queue.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/pytorrent/services/smart_queue.py b/pytorrent/services/smart_queue.py index e121fc9..12969d2 100644 --- a/pytorrent/services/smart_queue.py +++ b/pytorrent/services/smart_queue.py @@ -304,10 +304,12 @@ def _is_smart_queue_hold(torrent: dict[str, Any] | None, manage_stopped: bool = return False if str(torrent.get('label') or '') == SMART_QUEUE_LABEL: return True - # Note: Gdy manage_stopped=False, techniczne labele Smart Queue dotyczą tylko paused, a nie całkiem zatrzymanych torrentów. - if bool(torrent.get('paused')) and not int(torrent.get('state') or 0): + # Note: Paused w rTorrent zwykle ma state=1 i active=0, więc nie wolno wymagać state=0. + # Dzięki temu Smart Queue widzi pauzowane torrenty jako oczekujące i może później dobić target kolejki. + if bool(torrent.get('paused')): return True - if not manage_stopped and not int(torrent.get('state') or 0): + # Note: Całkiem zatrzymane pozycje są zarządzane tylko po włączeniu opcji Use stopped torrents. + if not manage_stopped: return False return not int(torrent.get('state') or 0) @@ -352,14 +354,17 @@ def _cleanup_auto_labels(client: Any, profile_id: int, torrents: list[dict[str, def _is_running_download_slot(t: dict[str, Any]) -> bool: - """Return True for torrents already started by rTorrent.""" - # Note: Nie używamy d.is_active/paused do liczenia slotów Smart Queue. - # active=0 może oznaczać brak transferu/peerów, a nie wolny slot. Liczenie po active - # powodowało startowanie kolejki po 1 sztuce mimo targetu 100. - return ( - not int(t.get('complete') or 0) - and bool(int(t.get('state') or 0)) - ) + """Return True only for incomplete torrents that are currently allowed to run.""" + # Note: Samo state=1 nie wystarcza, bo d.pause w rTorrent zostawia state=1. + # Poprzednia logika traktowała pauzowane torrenty jako aktywne sloty, przez co Smart Queue + # nie dobijał do targetu i nie wybierał ich jako kandydatów do wznowienia. + if int(t.get('complete') or 0): + return False + if bool(t.get('paused')) or str(t.get('status') or '').lower() == 'paused': + return False + if str(t.get('status') or '').lower() == 'checking': + return False + return bool(int(t.get('state') or 0)) def _is_waiting_download_candidate(t: dict[str, Any], manage_stopped: bool) -> bool: @@ -368,8 +373,10 @@ def _is_waiting_download_candidate(t: dict[str, Any], manage_stopped: bool) -> b return False if str(t.get('label') or '') == SMART_QUEUE_LABEL: return True - if bool(t.get('paused')): + # Note: Paused jest podstawowym źródłem dobijania kolejki, niezależnie od opcji manage_stopped. + if bool(t.get('paused')) or str(t.get('status') or '').lower() == 'paused': return True + # Note: Stopped dokładamy tylko wtedy, gdy użytkownik zaznaczył Use stopped torrents. return bool(manage_stopped) and not int(t.get('state') or 0)