mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-03-19 19:37:14 +08:00
fix(database): clean up torrent records on bangumi deletion
When a bangumi was deleted, its associated Torrent records remained in the database. This prevented re-downloading the same torrents if the user re-added the anime, because check_new() deduplicates by URL and would filter out the orphaned records. Now delete_rule() removes Torrent records before deleting the Bangumi, so re-adding the same anime correctly treats those torrents as new. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -70,6 +70,22 @@ class TorrentDatabase:
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
def delete_by_bangumi_id(self, bangumi_id: int) -> int:
|
||||
"""Delete all torrent records associated with a bangumi.
|
||||
|
||||
Returns the number of deleted records.
|
||||
"""
|
||||
statement = select(Torrent).where(Torrent.bangumi_id == bangumi_id)
|
||||
result = self.session.execute(statement)
|
||||
torrents = list(result.scalars().all())
|
||||
count = len(torrents)
|
||||
for t in torrents:
|
||||
self.session.delete(t)
|
||||
if count > 0:
|
||||
self.session.commit()
|
||||
logger.debug("Deleted %s torrent records for bangumi_id %s.", count, bangumi_id)
|
||||
return count
|
||||
|
||||
def search_by_url(self, url: str) -> Torrent | None:
|
||||
"""Find torrent by URL."""
|
||||
result = self.session.execute(select(Torrent).where(Torrent.url == url))
|
||||
|
||||
@@ -46,6 +46,8 @@ class TorrentManager(Database):
|
||||
if isinstance(data, Bangumi):
|
||||
async with DownloadClient() as client:
|
||||
self.rss.delete(data.official_title)
|
||||
# Clean up torrent records so re-adding the same anime can re-download
|
||||
self.torrent.delete_by_bangumi_id(int(_id))
|
||||
self.bangumi.delete_one(int(_id))
|
||||
torrent_message = None
|
||||
if file:
|
||||
|
||||
@@ -440,6 +440,66 @@ def test_add_with_semantic_duplicate_creates_alias(db_session):
|
||||
assert "Frieren Beyond Journey's End" in aliases
|
||||
|
||||
|
||||
class TestDeleteByBangumiId:
|
||||
"""Tests for TorrentDatabase.delete_by_bangumi_id."""
|
||||
|
||||
def test_deletes_matching_torrents(self, db_session):
|
||||
db = TorrentDatabase(db_session)
|
||||
for i in range(3):
|
||||
db.add(Torrent(name=f"torrent_{i}", url=f"https://example.com/{i}", bangumi_id=10))
|
||||
assert len(db.search_all()) == 3
|
||||
|
||||
count = db.delete_by_bangumi_id(10)
|
||||
assert count == 3
|
||||
assert len(db.search_all()) == 0
|
||||
|
||||
def test_leaves_other_bangumi_torrents(self, db_session):
|
||||
db = TorrentDatabase(db_session)
|
||||
db.add(Torrent(name="keep", url="https://example.com/keep", bangumi_id=20))
|
||||
db.add(Torrent(name="delete", url="https://example.com/delete", bangumi_id=30))
|
||||
|
||||
count = db.delete_by_bangumi_id(30)
|
||||
assert count == 1
|
||||
remaining = db.search_all()
|
||||
assert len(remaining) == 1
|
||||
assert remaining[0].name == "keep"
|
||||
|
||||
def test_no_match_returns_zero(self, db_session):
|
||||
db = TorrentDatabase(db_session)
|
||||
db.add(Torrent(name="unrelated", url="https://example.com/1", bangumi_id=5))
|
||||
|
||||
count = db.delete_by_bangumi_id(999)
|
||||
assert count == 0
|
||||
assert len(db.search_all()) == 1
|
||||
|
||||
def test_skips_null_bangumi_id(self, db_session):
|
||||
db = TorrentDatabase(db_session)
|
||||
db.add(Torrent(name="orphan", url="https://example.com/orphan", bangumi_id=None))
|
||||
db.add(Torrent(name="target", url="https://example.com/target", bangumi_id=7))
|
||||
|
||||
count = db.delete_by_bangumi_id(7)
|
||||
assert count == 1
|
||||
remaining = db.search_all()
|
||||
assert len(remaining) == 1
|
||||
assert remaining[0].bangumi_id is None
|
||||
|
||||
def test_check_new_finds_urls_after_cleanup(self, db_session):
|
||||
"""Core scenario: after deleting torrent records, check_new should treat those URLs as new."""
|
||||
db = TorrentDatabase(db_session)
|
||||
db.add(Torrent(name="ep01", url="https://mikan.me/t/001", bangumi_id=42))
|
||||
db.add(Torrent(name="ep02", url="https://mikan.me/t/002", bangumi_id=42))
|
||||
|
||||
# Before cleanup: check_new filters them out
|
||||
incoming = [Torrent(name="ep01", url="https://mikan.me/t/001")]
|
||||
assert db.check_new(incoming) == []
|
||||
|
||||
# After cleanup: same URLs are now "new"
|
||||
db.delete_by_bangumi_id(42)
|
||||
new = db.check_new(incoming)
|
||||
assert len(new) == 1
|
||||
assert new[0].url == "https://mikan.me/t/001"
|
||||
|
||||
|
||||
def test_groups_are_similar():
|
||||
"""Test group name similarity detection."""
|
||||
from module.database.bangumi import _groups_are_similar
|
||||
|
||||
Reference in New Issue
Block a user