post-check

This commit is contained in:
Mateusz Gruszczyński
2026-05-24 11:04:42 +02:00
parent 8553615fbf
commit 9caa155324
7 changed files with 47 additions and 16 deletions

View File

@@ -197,8 +197,8 @@ def apply_post_check_policy(profile: dict, rows: list[dict], previous_rows: dict
except Exception:
pass
c.call("d.custom1.set", h, label_value)
row.update({"state": 0, "active": 0, "paused": False, "status": "Stopped", "label": label_value})
changes.append({"hash": h, "action": "stop_and_label_after_check", "complete": False, "label": POST_CHECK_DOWNLOAD_LABEL})
row.update({"state": 0, "active": 0, "paused": False, "post_check": True, "status": "Post-check", "label": label_value})
changes.append({"hash": h, "action": "mark_post_check_waiting", "complete": False, "label": POST_CHECK_DOWNLOAD_LABEL})
_clear_post_check_watch(profile_id, h)
except Exception as exc:
changes.append({"hash": h, "action": "post_check_policy_failed", "error": str(exc)})
@@ -267,8 +267,10 @@ def normalize_row(row: list) -> dict:
complete = int(row[3] or 0)
# Note: d.hashing is authoritative; stale "hash check complete" messages must not keep the UI in Checking forever.
is_checking = bool(hashing) or _message_indicates_active_check(msg_l)
is_paused = bool(state) and not bool(is_active) and not is_checking
status = "Checking" if is_checking else "Paused" if is_paused else "Seeding" if complete and state else "Downloading" if state else "Stopped"
post_check = POST_CHECK_DOWNLOAD_LABEL in _label_names(str(row[17] or "")) and not is_checking and not bool(is_active)
is_paused = bool(state) and not bool(is_active) and not is_checking and not post_check
# Note: Post-check is an application-level state that separates torrents waiting after a recheck from manually stopped torrents.
status = "Checking" if is_checking else "Post-check" if post_check else "Paused" if is_paused else "Seeding" if complete and state else "Downloading" if state else "Stopped"
to_download_bytes = remaining_bytes if not complete else 0
# Note: The To download column is only meaningful for incomplete torrents; complete rows expose an empty display value.
return {
@@ -305,6 +307,7 @@ def normalize_row(row: list) -> dict:
"ratio_group": str(row[18] or ""),
"message": msg,
"status": status,
"post_check": post_check,
"hashing": hashing,
}
@@ -545,12 +548,16 @@ def _download_runtime_state(c: ScgiRtorrentClient, h: str) -> dict:
active = _int_rpc(c, 'd.is_active', h)
opened = _int_rpc(c, 'd.is_open', h)
# Note: In rTorrent, pause does not change d.state. Paused means state=1, open=1, active=0.
label = _str_rpc(c, 'd.custom1', h)
post_check = POST_CHECK_DOWNLOAD_LABEL in _label_names(label) and not bool(active)
return {
'state': state,
'open': opened,
'active': active,
'paused': bool(state and opened and not active),
'paused': bool(state and opened and not active and not post_check),
'stopped': not bool(state),
'post_check': post_check,
'label': label,
'message': _str_rpc(c, 'd.message', h),
}
@@ -590,10 +597,14 @@ def stop_hash(c: ScgiRtorrentClient, torrent_hash: str) -> dict:
return {'hash': h, 'ok': False, 'error': 'missing hash'}
before = _download_runtime_state(c, h)
result = {'hash': h, 'before': before, 'commands': []}
if before.get('stopped'):
if before.get('stopped') and not before.get('post_check'):
result.update({'ok': True, 'skipped': 'already_stopped', 'after': before})
return result
try:
# Note: User Stop converts the app-level Post-check state into a regular stopped torrent.
if before.get('post_check'):
clear_post_check_download_label(c, h, before.get('label'))
result['commands'].append('clear_post_check_label')
# Note: Smart Queue now enforces the queue with d.stop only; user-paused torrents stay untouched.
c.call('d.stop', h)
result['commands'].append('d.stop')
@@ -643,10 +654,13 @@ def start_or_resume_hash(c: ScgiRtorrentClient, torrent_hash: str, prefer_start:
result: dict = {'hash': h, 'before': before, 'commands': []}
if before.get('active'):
if before.get('post_check'):
clear_post_check_download_label(c, h, before.get('label'))
before = _download_runtime_state(c, h)
result.update({'ok': True, 'skipped': 'already_active', 'after': before})
return result
if before.get('paused') and not prefer_start:
if before.get('paused') and not prefer_start and not before.get('post_check'):
# Note: Manual Start keeps the clean pause-to-resume path. Do not classify every
# state=1/active=0 item as paused; after auto-check this can be only a transient
# open/inactive rTorrent state and needs d.open + d.start.
@@ -654,6 +668,13 @@ def start_or_resume_hash(c: ScgiRtorrentClient, torrent_hash: str, prefer_start:
resumed['mode'] = 'resume_paused'
return resumed
if before.get('post_check'):
try:
# Note: Post-check start first forces a clean stopped state, matching the manual Stop -> Start recovery path.
c.call('d.stop', h)
result['commands'].append('d.stop')
except Exception as exc:
result.setdefault('ignored_errors', []).append(f'd.stop: {exc}')
try:
c.call('d.open', h)
result['commands'].append('d.open')
@@ -670,7 +691,13 @@ def start_or_resume_hash(c: ScgiRtorrentClient, torrent_hash: str, prefer_start:
except Exception as exc2:
result.setdefault('ignored_errors', []).append(f'd.try_start: {exc2}')
result['ok'] = False
result['after'] = _download_runtime_state(c, h)
after = _download_runtime_state(c, h)
if before.get('post_check') and after.get('active'):
# Note: The marker stays in place when start fails so the row remains visible in the Post-check filter.
clear_post_check_download_label(c, h, before.get('label'))
result['commands'].append('clear_post_check_label')
after = _download_runtime_state(c, h)
result['after'] = after
result['ok'] = result.get('ok', True)
return result