Files
MusicServer/app/sdk/platforms/apple/lyric.py
T
snowy-yang dfc06bf4de feat(python): 完成 Python 全量迁移——剩余平台、登录通道与公共层修复
- 新增 5sing/apple/xm/me/qt/lr 平台包与取流实现(含 xm-sign、MissEvan 签名、蜻蜓 HMAC、Apple developer token)
- 新增 wy/kg/tx/lr 登录:扫码、手机号、账密(kg 20028 风控指纹)、cookie 绑定、kg/tx 续期
- request 层:保留多值 Set-Cookie;JSON body 紧凑化(修复 kg 网关验签);直连不经系统代理(对齐 Node)
- 登录路由统一 Body(embed=True),修复扫码轮询 422;lifespan 接入登录续期调度
- ruff/format/pyright 全绿;14 平台真实联网与 HTTP 路由验证通过
2026-10-23 21:55:45 +08:00

46 lines
1.9 KiB
Python

"""Apple Music 歌词(对应 sdk/apple/lyric.ts,上游 apple.go GetLyrics)。
通道:amp-api /v1/catalog/<sf>/songs/<id>?include=lyrics&extend=extendedAssetUrls
→ data[0].relationships.lyrics.data[*].attributes.ttml
上游取到的是 TTML(Apple 逐字歌词格式,非 LRC),原样放入 lyric 字段返回;没有则忠实返回空串。
注意(2026-10 实测):匿名 developer token 请求时 Apple 不返回 lyrics relationship
(即使 attributes.hasLyrics=true,歌单/搜索接口也一样),歌词需要 media-user-token(订阅态);
本实现保持上游行为:拿不到就返回 ``{lyric: '', tlyric: ''}``,不抛错。
"""
from __future__ import annotations
from typing import Any
from app.sdk.common.utils import as_dict, as_list
from app.sdk.platforms.apple.util import apple_amp_get_tracked, extract_apple_id, get_apple_config
async def get_lyric(song_info: dict[str, Any]) -> dict[str, str]:
song_id = extract_apple_id(str(song_info.get("songmid") or song_info.get("id") or ""), "song")
if not song_id:
raise RuntimeError("apple 歌曲 id 无效")
cfg = get_apple_config()
body = as_dict(
await apple_amp_get_tracked(
f"/v1/catalog/{cfg['storefront']}/songs/{song_id}",
{"include": "lyrics", "extend": "extendedAssetUrls"},
)
)
data = as_list(body.get("data"))
first = as_dict(data[0]) if data else {}
relationships = as_dict(first.get("relationships"))
lyrics = as_list(as_dict(relationships.get("lyrics")).get("data"))
for rel in lyrics:
text = str(as_dict(as_dict(rel).get("attributes")).get("ttml") or "")
if text:
return {"lyric": text, "tlyric": ""}
return {"lyric": "", "tlyric": ""}
async def get_lyrics_text(song_id: str) -> str:
"""非取消句柄版:直接返回歌词文本(内部/测试用)。"""
result = await get_lyric({"songmid": song_id})
return result.get("lyric") or ""