feature: support including NCM metadata

* Fix type mark
This commit is contained in:
Puqns67 2024-10-15 22:00:20 +08:00
parent 2580e4cbfe
commit 6e64fd0b34
Signed by: Puqns67
GPG Key ID: 9669DF042554F536
2 changed files with 42 additions and 15 deletions

View File

@ -113,4 +113,3 @@ class NCMApi:
request = self._httpClient.build_request("GET", "/song/lyric/v1", params=params) request = self._httpClient.build_request("GET", "/song/lyric/v1", params=params)
return NCMLyrics.fromApi(self._fetch(request)).withId(trackId) return NCMLyrics.fromApi(self._fetch(request)).withId(trackId)

View File

@ -24,8 +24,14 @@ class Lrc:
# metaType: lrcType: metaContent # metaType: lrcType: metaContent
self.metadata: dict[LrcMetaType, dict[LrcType, str]] = {} self.metadata: dict[LrcMetaType, dict[LrcType, str]] = {}
# timestamp: lrcType/String: lrcContent # timestamp: lrcType: lrcContent
self.lyrics: dict[int, dict[LrcType | str, str]] = {} self.lyrics: dict[int, dict[LrcType, str]] = {}
# specials: timestamp/metaType: lrcContent/metaContent
self.specials: dict[str, list[tuple[int | LrcMetaType, str]]] = {
"metadata": [],
"timestamp": [],
}
@classmethod @classmethod
def fromNCMLyrics(cls, lyrics: NCMLyrics) -> Self: def fromNCMLyrics(cls, lyrics: NCMLyrics) -> Self:
@ -53,8 +59,8 @@ class Lrc:
if LRC_RE_COMMIT.match(lrcRow) is not None: if LRC_RE_COMMIT.match(lrcRow) is not None:
return return
# Skip NCM special metadata lines
if LRC_RE_META_NCM_SPECIAL.match(lrcRow) is not None: if LRC_RE_META_NCM_SPECIAL.match(lrcRow) is not None:
self.appendSpecialNCMMetaDataRow(lrcRow)
return return
matchedMetaDataRow = LRC_RE_META.match(lrcRow) matchedMetaDataRow = LRC_RE_META.match(lrcRow)
@ -74,6 +80,23 @@ class Lrc:
else: else:
self.lyrics[timestamp] = {lrcType: lyric} self.lyrics[timestamp] = {lrcType: lyric}
def appendSpecialNCMMetaDataRow(self, lrcRow: str) -> None:
try:
data = loadJson(lrcRow)
except JSONDecodeError:
return
try:
key: str = data["c"][0]["tx"]
value: str = data["c"][1]["tx"]
except KeyError:
return
key = key.strip(" :")
value = value.strip()
self.specials["metadata"].append((LrcMetaType.Author, f"{key}/{value}"))
def appendMatchedMetaDataRow(self, lrcType: LrcType, matchedLine: Match[str]) -> None: def appendMatchedMetaDataRow(self, lrcType: LrcType, matchedLine: Match[str]) -> None:
metaType, metaContent = matchedLine.groups() metaType, metaContent = matchedLine.groups()
@ -111,21 +134,26 @@ class Lrc:
return "\n".join(list(self.deserializeLyricRows())) return "\n".join(list(self.deserializeLyricRows()))
def deserializeLyricRows(self) -> Generator[str, None, None]: def deserializeLyricRows(self) -> Generator[str, None, None]:
yield from self.generateLyricMetaDataRows() yield from self.generateMetaDataRows()
yield from self.generateLyricRows()
def generateMetaDataRows(self) -> Generator[str, None, None]:
for metaType in LrcMetaType:
if metaType in self.metadata:
for lrcType in self.metadata[metaType].keys():
yield f"[{metaType.value}:{lrcType.pretty()}/{self.metadata[metaType][lrcType]}]"
for metaType, content in self.specials["metadata"]:
yield f"[{metaType.value}:{content}]"
def generateLyricRows(self) -> Generator[str, None, None]:
for timestamp in sorted(self.lyrics.keys()): for timestamp in sorted(self.lyrics.keys()):
yield from self.generateLyricRows(timestamp)
def generateLyricMetaDataRows(self) -> Generator[str, None, None]:
for type in LrcMetaType:
if type in self.metadata:
for lrcType in self.metadata[type].keys():
yield f"[{type.value}: {lrcType.pretty()}/{self.metadata[type][lrcType]}]"
def generateLyricRows(self, timestamp: int) -> Generator[str, None, None]:
for lrcType in self.lyrics[timestamp].keys(): for lrcType in self.lyrics[timestamp].keys():
yield self._timestamp2TimeLabel(timestamp) + self.lyrics[timestamp][lrcType] yield self._timestamp2TimeLabel(timestamp) + self.lyrics[timestamp][lrcType]
for timestamp, content in self.specials["timestamp"]:
yield self._timestamp2TimeLabel(timestamp) + content
def saveAs(self, path: Path) -> None: def saveAs(self, path: Path) -> None:
with path.open("w+") as fs: with path.open("w+") as fs:
for row in self.deserializeLyricRows(): for row in self.deserializeLyricRows():