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:20 +0000

1import os 

2import unicodedata 

3from os.path import join 

4 

5from lanraragi_api import LANraragiAPI 

6from lanraragi_api.enhanced.server_side import compute_id, is_archive 

7from lanraragi_api.entity.archive import ArchiveMetadata, ArchiveTags 

8 

9 

10def subfolders_to_artists(api: LANraragiAPI, dirname: str): 

11 """Set the artist tag of archives to the name of their parent folder. 

12 

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. 

16 

17 This function is similar to Subfolders to Categories, but has better 

18 performance. 

19 

20 Args: 

21 api: LANraragiAPI instance used to read and update the archives. 

22 dirname: Content folder whose subfolders give the artist tags. 

23 

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] 

57 

58 at = ArchiveTags(a.tags) 

59 

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}") 

69 

70 

71def remove_all_categories(api: LANraragiAPI): 

72 """Remove every archive from every category, then delete the categories. 

73 

74 For every category, all the archives it contains are removed from it. After 

75 that, all the categories are removed. 

76 

77 Args: 

78 api: LANraragiAPI instance used to read and modify the categories. 

79 

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")