Coverage for src/lanraragi_api/enhanced/script.py: 0%
50 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-22 23:19 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-22 23:19 +0000
1import os
2import unicodedata
3from os.path import join
5from lanraragi_api import LANraragiAPI
6from lanraragi_api.enhanced.server_side import compute_id, is_archive
7from lanraragi_api.entity.archive import ArchiveMetadata, ArchiveTags
10def subfolders_to_artists(api: LANraragiAPI, dirname: str):
11 """Set the artist tag of archives to the name of their parent folder.
13 Walks through ``dirname`` and, for every archive that has no artist tag
14 yet, sets its artist tag to the name of the subfolder holding it. Archives
15 that already have an artist tag are skipped.
17 This function is similar to Subfolders to Categories, but has better
18 performance.
20 Args:
21 api: LANraragiAPI instance used to read and update the archives.
22 dirname: Content folder whose subfolders give the artist tags.
24 Note:
25 This function modifies archive metadata on the server. Archives are
26 looked up by title, and the archive ID is computed from the file only
27 when several archives share the same title. A summary of the skipped
28 and updated archives is printed.
29 """
30 archives = api.archives.get_all_archives()
31 map: dict[str, list[ArchiveMetadata]] = {}
32 # possibly duplicate archive names
33 for a in archives:
34 k = unicodedata.normalize("NFC", a.title)
35 if k not in map:
36 map[k] = []
37 map[k].append(a)
38 skip_count = 0
39 update_count = 0
40 for root, _dirs, files in os.walk(dirname):
41 for f in files:
42 if not is_archive(f):
43 continue
44 f = unicodedata.normalize("NFC", f)
45 f2 = f[: f.rfind(".")].strip() # remove file extension
46 if f2 not in map:
47 continue
48 if len(map[f2]) > 1:
49 # only call compute_id if there are duplicates to improve performance
50 id = compute_id(join(root, f))
51 a = [a for a in map[f2] if a.arcid == id]
52 if len(a) == 0:
53 continue
54 a = a[0]
55 else:
56 a = map[f2][0]
58 at = ArchiveTags(a.tags)
60 if len(at.get_artists()) > 0:
61 skip_count += 1
62 continue
63 _, subfolder = os.path.split(root)
64 update_count += 1
65 at.set_artists([subfolder])
66 a.tags = at.tags
67 _ = api.archives.update_archive_metadata(a.arcid, a)
68 print(f"archives skipped count: {skip_count} , updated count: {update_count}")
71def remove_all_categories(api: LANraragiAPI):
72 """Remove every archive from every category, then delete the categories.
74 For every category, all the archives it contains are removed from it. After
75 that, all the categories are removed.
77 Args:
78 api: LANraragiAPI instance used to read and modify the categories.
80 Note:
81 Every category of the server is deleted. Removing the archives from a
82 category does not delete the archives themselves. The number of removed
83 archives and categories is printed.
84 """
85 cs = api.categories.get_all_categories()
86 for c in cs:
87 for aid in c.archives:
88 _ = api.categories.remove_archive_from_category(c.id, aid)
89 print(f"remove {len(c.archives)} from category {c.id}:{c.name}")
90 for c in cs:
91 _ = api.categories.delete_category(c.id)
92 print(f"remove {len(cs)} categories")