Coverage for src/lanraragi_api/entity/archive.py: 61%
41 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-22 23:20 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-22 23:20 +0000
1from typing import Any
3from pydantic import BaseModel, Field
5ARCHIVE_TAG_VALUES_SET = "ONLY_VALUES"
8class ArchiveMetadata(BaseModel):
9 """Metadata of a single Archive.
11 Attributes:
12 arcid: Unique identifier for the archive, a 40 character SHA1 hash.
13 extension: File extension of the archive.
14 filename: Filename of the archive.
15 isnew: Whether the archive is newly added. Defaults to None.
16 lastreadtime: Unix timestamp of when the archive was last read.
17 pagecount: Total number of pages in the archive.
18 progress: Reading progress, as a page number.
19 size: Size of the archive in bytes.
20 summary: Summary description of the archive. Defaults to None.
21 toc: Table of contents for the archive, as objects holding the ``page``
22 where a chapter starts and its ``name``. Defaults to None.
23 tags: Comma-separated list of tags associated with the archive, with
24 namespaced tags in ``namespace:value`` form.
25 title: Title of the archive.
26 """
28 arcid: str = Field(...)
29 extension: str = Field(...)
30 filename: str = Field(...)
31 isnew: bool | str | None = Field(default=None)
32 lastreadtime: int = Field(...)
33 pagecount: int = Field(...)
34 progress: int = Field(...)
35 size: int = Field(...)
36 summary: str | None = Field(default=None)
37 toc: list[dict[Any, Any]] | None = Field(default=None)
39 # k1:v1, k2:v21, k2:v22, v3, v4
40 # allow duplicate keys, only values
41 tags: str = Field(...)
42 title: str = Field(...)
45class ArchiveTags:
46 """Offer utility methods to operate ``ArchiveMetadata.tags``"""
48 def __init__(self, tags: str):
49 self._tags: str = tags
51 @property
52 def tags(self):
53 """Get the ``tags`` string represented by this class"""
54 return self._tags
56 def get_tag_list(self) -> list[str]:
57 """Get a list of tags"""
58 tags = [t.strip() for t in self._tags.split(",")]
59 tags = [t for t in tags if t != ""]
60 return tags
62 def set_tag(self, tag_list: list[str]):
63 """Set the inner ``tags`` by a list of tags. Note that there will be
64 a deduplication first.
65 """
66 # deduplicate first
67 tag_list = list(dict.fromkeys(tag_list))
68 self._tags = ",".join(tag_list)
70 def get_artists(self) -> list[str]:
71 """Get all artists in a list from tags prefixed with ``artist:``."""
72 tag_list = self.get_tag_list()
73 return [t[len("artist:") :] for t in tag_list if t.startswith("artist:")]
75 def set_artists(self, artists: list[str]):
76 """Set/Overwrite existing artists.
78 Consider using ``append_artists`` method if you want to add some new
79 artists.
81 """
82 tag_list = self.get_tag_list()
83 tag_list = [t for t in tag_list if not t.startswith("artist:")]
84 self.set_tag(tag_list)
86 self.append_artists(artists)
88 def append_artists(self, artists: list[str]):
89 """Add some new artists to the existing ones."""
90 tag_list = self.get_tag_list()
91 tag_list += [f"artist:{a}" for a in artists]
92 self.set_tag(tag_list)