Implement per-file import for in-progress torrents

Files within a downloading torrent are now imported as soon as their
individual progress reaches 100%, without waiting for the full torrent
to complete. A new processed_files table (info_hash, file_name) tracks
which files have been handled to avoid redundant re-hashing each poll.

- db.py: add processed_files table, is_file_processed, record_processed_file
- qbit_client.py: replace get_completed_torrents with get_torrents(filter, category)
- stash_handler.py: extract process_torrent_files helper, daemon now polls
  both downloading and completed torrents each cycle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-18 21:51:52 -05:00
parent 6adfd77236
commit 5bcb35e737
4 changed files with 134 additions and 42 deletions
+29 -2
View File
@@ -23,6 +23,14 @@ def init_db(db_path):
processed_at TEXT NOT NULL
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS processed_files (
info_hash TEXT NOT NULL,
file_name TEXT NOT NULL,
processed_at TEXT NOT NULL,
PRIMARY KEY (info_hash, file_name)
)
""")
conn.commit()
return conn
@@ -50,16 +58,35 @@ def increment_seen(conn, file_hash):
def is_torrent_processed(conn, info_hash):
"""Check if a torrent has already been processed."""
"""Check if a torrent has already been fully processed."""
row = conn.execute("SELECT 1 FROM processed_torrents WHERE info_hash = ?", (info_hash,)).fetchone()
return row is not None
def record_torrent(conn, info_hash, torrent_name):
"""Record a torrent as processed."""
"""Record a torrent as fully processed."""
now = datetime.now(timezone.utc).isoformat()
conn.execute(
"INSERT OR IGNORE INTO processed_torrents (info_hash, torrent_name, processed_at) VALUES (?, ?, ?)",
(info_hash, torrent_name, now),
)
conn.commit()
def is_file_processed(conn, info_hash, file_name):
"""Check if an individual file within a torrent has already been processed."""
row = conn.execute(
"SELECT 1 FROM processed_files WHERE info_hash = ? AND file_name = ?",
(info_hash, file_name),
).fetchone()
return row is not None
def record_processed_file(conn, info_hash, file_name):
"""Record an individual file within a torrent as processed."""
now = datetime.now(timezone.utc).isoformat()
conn.execute(
"INSERT OR IGNORE INTO processed_files (info_hash, file_name, processed_at) VALUES (?, ?, ?)",
(info_hash, file_name, now),
)
conn.commit()