跳转至

login

登录相关 API

check_expired async

check_expired(credential: Credential) -> bool

检查凭据是否过期

PARAMETER DESCRIPTION
credential

用户凭证

TYPE: Credential

Source code in qqmusic_api/login.py
async def check_expired(credential: Credential) -> bool:
    """检查凭据是否过期

    Args:
        credential: 用户凭证
    """
    api = ApiRequest(
        "music.UserInfo.userInfoServer",
        "GetLoginUserInfo",
        params={},
        credential=credential,
        cacheable=False,
    )

    try:
        await api()
        return False
    except CredentialExpiredError:
        return True

refresh_cookies async

refresh_cookies(credential: Credential) -> bool

刷新 Cookies

Note

刷新无效 cookie 需要 refresh_keyrefresh_token 字段

PARAMETER DESCRIPTION
credential

用户凭证

TYPE: Credential

RETURNS DESCRIPTION
bool

是否刷新成功

Source code in qqmusic_api/login.py
async def refresh_cookies(credential: Credential) -> bool:
    """刷新 Cookies

    Note:
        刷新无效 cookie 需要 `refresh_key` 和 `refresh_token` 字段

    Args:
        credential: 用户凭证

    Returns:
        是否刷新成功
    """
    params = {
        "refresh_key": credential.refresh_key,
        "refresh_token": credential.refresh_token,
        "musickey": credential.musickey,
        "musicid": credential.musicid,
    }

    api = ApiRequest[[], dict[str, Any]](
        "music.login.LoginServer",
        "Login",
        common={"tmeLoginType": str(credential.login_type)},
        params=params,
        credential=credential,
        cacheable=False,
    )

    try:
        resp = await api()
        c = credential.from_cookies_dict(resp)
        credential.__dict__.update(c.__dict__)
        return True
    except CredentialExpiredError:
        return False

QRCodeLoginEvents

Bases: Enum

二维码登录状态

  • SCAN: 等待扫描二维码
  • CONF: 已扫码未确认登录
  • TIMEOUT: 二维码已过期
  • DONE: 扫码成功
  • REFUSE: 拒绝登录
  • OTHER: 未知情况

get_by_value classmethod

get_by_value(value: int)

根据传入的值查找对应的枚举成员

Source code in qqmusic_api/login.py
@classmethod
def get_by_value(cls, value: int):
    """根据传入的值查找对应的枚举成员"""
    for member in cls:
        if value in member.value:
            return member
    return cls.OTHER

PhoneLoginEvents

Bases: Enum

手机登录状态

  • SEND: 发送成功
  • CAPTCHA: 需要滑块验证
  • FREQUENCY: 频繁操作
  • OTHER: 未知情况

QRLoginType

Bases: Enum

登录类型

  • QQ: QQ登录
  • WX: 微信登录

QR dataclass

QR(data: bytes, qr_type: QRLoginType, mimetype: str, identifier: str)

二维码

ATTRIBUTE DESCRIPTION
data

二维码图像数据

TYPE: bytes

qr_type

二维码类型

TYPE: QRLoginType

mimetype

二维码图像类型

TYPE: str

identitfier

标识符

TYPE: str

save

save(path: str | Path = '.')

保存二维码

PARAMETER DESCRIPTION
path

保存文件夹

TYPE: str | Path DEFAULT: '.'

Source code in qqmusic_api/login.py
def save(self, path: Path | str = "."):
    """保存二维码

    Args:
        path: 保存文件夹
    """
    if not self.data:
        return None
    path = Path(path)
    path.mkdir(parents=True, exist_ok=True)
    file_path = (
        path
        / f"{self.qr_type.value}-{uuid4()}{mimetypes.guess_extension(self.mimetype) if self.mimetype else None or '.png'}"
    )
    file_path.write_bytes(self.data)
    return file_path

get_qrcode async

get_qrcode(login_type: QRLoginType) -> QR

获取登录二维码

Source code in qqmusic_api/login.py
async def get_qrcode(login_type: QRLoginType) -> QR:
    """获取登录二维码"""
    if login_type == QRLoginType.WX:
        return await _get_wx_qr()
    return await _get_qq_qr()

check_qrcode async

check_qrcode(qrcode: QR) -> tuple[QRCodeLoginEvents, Credential | None]

检查二维码状态

Source code in qqmusic_api/login.py
async def check_qrcode(qrcode: QR) -> tuple[QRCodeLoginEvents, Credential | None]:
    """检查二维码状态"""
    if qrcode.qr_type == QRLoginType.WX:
        return await _check_wx_qr(qrcode)
    return await _check_qq_qr(qrcode)

send_authcode async

send_authcode(phone: int, country_code: int = 86) -> tuple[PhoneLoginEvents, str | None]

发送验证码

PARAMETER DESCRIPTION
phone

手机号

TYPE: int

country_code

国家码

TYPE: int DEFAULT: 86

Source code in qqmusic_api/login.py
async def send_authcode(phone: int, country_code: int = 86) -> tuple[PhoneLoginEvents, str | None]:
    """发送验证码

    Args:
        phone: 手机号
        country_code: 国家码
    """
    resp = await ApiRequest[[], dict[str, Any]](
        "music.login.LoginServer",
        "SendPhoneAuthCode",
        common={"tmeLoginMethod": "3"},
        params={
            "tmeAppid": "qqmusic",
            "phoneNo": str(phone),
            "areaCode": str(country_code),
        },
        ignore_code=True,
        cacheable=False,
    )()

    match resp["code"]:
        case 20276:
            return PhoneLoginEvents.CAPTCHA, resp["data"]["securityURL"]
        case 100001:
            return PhoneLoginEvents.FREQUENCY, None
        case 0:
            return PhoneLoginEvents.SEND, None
    return PhoneLoginEvents.OTHER, resp["data"]["errMsg"]

phone_authorize async

phone_authorize(phone: int, auth_code: int, country_code: int = 86) -> Credential

验证码鉴权

PARAMETER DESCRIPTION
phone

手机号

TYPE: int

auth_code

验证码

TYPE: int

country_code

国家码

TYPE: int DEFAULT: 86

Source code in qqmusic_api/login.py
async def phone_authorize(phone: int, auth_code: int, country_code: int = 86) -> Credential:
    """验证码鉴权

    Args:
        phone: 手机号
        auth_code: 验证码
        country_code: 国家码
    """
    resp = await ApiRequest[[], dict[str, Any]](
        "music.login.LoginServer",
        "Login",
        common={"tmeLoginMethod": "3", "tmeLoginType": "0"},
        params={"code": str(auth_code), "phoneNo": str(phone), "areaCode": str(country_code), "loginMode": 1},
        ignore_code=True,
        cacheable=False,
    )()
    match resp["code"]:
        case 20271:
            raise LoginError("[PhoneLogin] 验证码错误或已鉴权")
        case 0:
            return Credential.from_cookies_dict(resp["data"])
    raise LoginError("[PhoneLogin] 未知原因导致鉴权失败")