mirror of
https://github.com/PaiGramTeam/SIMNet.git
synced 2024-11-22 06:17:57 +00:00
✨ Add NeedChallenge
and NotSupported
exception
This commit is contained in:
parent
888c729e1f
commit
e6ec72272b
@ -8,6 +8,7 @@ from simnet.client.routes import (
|
|||||||
GET_COOKIES_TOKEN_BY_STOKEN_URL,
|
GET_COOKIES_TOKEN_BY_STOKEN_URL,
|
||||||
GET_LTOKEN_BY_STOKEN_URL,
|
GET_LTOKEN_BY_STOKEN_URL,
|
||||||
)
|
)
|
||||||
|
from simnet.errors import RegionNotSupported
|
||||||
from simnet.utils.enum_ import Region
|
from simnet.utils.enum_ import Region
|
||||||
|
|
||||||
__all__ = ("AuthClient",)
|
__all__ = ("AuthClient",)
|
||||||
@ -36,11 +37,11 @@ class AuthClient(BaseClient):
|
|||||||
Optional[str]: The retrieved super ticket (`stoken`).
|
Optional[str]: The retrieved super ticket (`stoken`).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: This method is only available for the Chinese region.
|
RegionNotSupported: This method is only available for the Chinese region.
|
||||||
ValueError: If the `login_ticket` argument is `None`, or if the `account_id` argument is `None`.
|
ValueError: If the `login_ticket` argument is `None`, or if the `account_id` argument is `None`.
|
||||||
"""
|
"""
|
||||||
if self.region != Region.CHINESE:
|
if self.region != Region.CHINESE:
|
||||||
raise RuntimeError("This method is only available for the Chinese region.")
|
raise RegionNotSupported("This method is only available for the Chinese region.")
|
||||||
url = AUTH_URL.get_url(Region.CHINESE) / "getMultiTokenByLoginTicket"
|
url = AUTH_URL.get_url(Region.CHINESE) / "getMultiTokenByLoginTicket"
|
||||||
login_ticket = login_ticket or self.cookies.get("login_ticket")
|
login_ticket = login_ticket or self.cookies.get("login_ticket")
|
||||||
account_id = account_id or self.account_id
|
account_id = account_id or self.account_id
|
||||||
@ -82,11 +83,11 @@ class AuthClient(BaseClient):
|
|||||||
Optional[str]: The retrieved cookie token (`cookie_token`).
|
Optional[str]: The retrieved cookie token (`cookie_token`).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: This method is only available for the Chinese region.
|
RegionNotSupported: This method is only available for the Chinese region.
|
||||||
ValueError: If the `login_ticket` argument is `None`, or if the `account_id` argument is `None`.
|
ValueError: If the `login_ticket` argument is `None`, or if the `account_id` argument is `None`.
|
||||||
"""
|
"""
|
||||||
if self.region != Region.CHINESE:
|
if self.region != Region.CHINESE:
|
||||||
raise RuntimeError("This method is only available for the Chinese region.")
|
raise RegionNotSupported("This method is only available for the Chinese region.")
|
||||||
stoken = stoken or self.cookies.get("stoken")
|
stoken = stoken or self.cookies.get("stoken")
|
||||||
account_id = account_id or self.account_id
|
account_id = account_id or self.account_id
|
||||||
if stoken is None:
|
if stoken is None:
|
||||||
@ -121,11 +122,11 @@ class AuthClient(BaseClient):
|
|||||||
Optional[str]: The retrieved cookie token (`cookie_token`).
|
Optional[str]: The retrieved cookie token (`cookie_token`).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: This method is only available for the Chinese region.
|
RegionNotSupported: This method is only available for the Chinese region.
|
||||||
ValueError: If the `login_ticket` argument is `None`, or if the `account_id` argument is `None`.
|
ValueError: If the `login_ticket` argument is `None`, or if the `account_id` argument is `None`.
|
||||||
"""
|
"""
|
||||||
if self.region != Region.CHINESE:
|
if self.region != Region.CHINESE:
|
||||||
raise RuntimeError("This method is only available for the Chinese region.")
|
raise RegionNotSupported("This method is only available for the Chinese region.")
|
||||||
stoken = stoken or self.cookies.get("stoken")
|
stoken = stoken or self.cookies.get("stoken")
|
||||||
account_id = account_id or self.account_id
|
account_id = account_id or self.account_id
|
||||||
if stoken is None:
|
if stoken is None:
|
||||||
@ -158,11 +159,11 @@ class AuthClient(BaseClient):
|
|||||||
Optional[str]: The authentication key, or None if not found.
|
Optional[str]: The authentication key, or None if not found.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: This method is only available for the Chinese region.
|
RegionNotSupported: This method is only available for the Chinese region.
|
||||||
ValueError: If `stoken` is not found in the cookies or `player_id` not found.
|
ValueError: If `stoken` is not found in the cookies or `player_id` not found.
|
||||||
"""
|
"""
|
||||||
if self.region != Region.CHINESE:
|
if self.region != Region.CHINESE:
|
||||||
raise RuntimeError("This method is only available for the Chinese region.")
|
raise RegionNotSupported("This method is only available for the Chinese region.")
|
||||||
stoken = self.cookies.get("stoken")
|
stoken = self.cookies.get("stoken")
|
||||||
if stoken is None:
|
if stoken is None:
|
||||||
raise ValueError("stoken not found in cookies.")
|
raise ValueError("stoken not found in cookies.")
|
||||||
|
@ -6,6 +6,7 @@ from httpx import QueryParams
|
|||||||
|
|
||||||
from simnet.client.base import BaseClient
|
from simnet.client.base import BaseClient
|
||||||
from simnet.client.routes import REWARD_URL
|
from simnet.client.routes import REWARD_URL
|
||||||
|
from simnet.errors import GeetestTriggered
|
||||||
from simnet.models.lab.daily import DailyRewardInfo, DailyReward, ClaimedDailyReward
|
from simnet.models.lab.daily import DailyRewardInfo, DailyReward, ClaimedDailyReward
|
||||||
from simnet.utils.ds import hex_digest
|
from simnet.utils.ds import hex_digest
|
||||||
from simnet.utils.enum_ import Game, Region
|
from simnet.utils.enum_ import Game, Region
|
||||||
@ -219,7 +220,7 @@ class DailyRewardClient(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
If `reward` is True, a DailyReward object representing the claimed reward. Otherwise, None.
|
If `reward` is True, a DailyReward object representing the claimed reward. Otherwise, None.
|
||||||
"""
|
"""
|
||||||
await self.request_daily_reward(
|
daily_reward = await self.request_daily_reward(
|
||||||
"sign",
|
"sign",
|
||||||
method="POST",
|
method="POST",
|
||||||
game=game or self.game,
|
game=game or self.game,
|
||||||
@ -228,6 +229,17 @@ class DailyRewardClient(BaseClient):
|
|||||||
validate=validate,
|
validate=validate,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.region == Region.CHINESE and daily_reward.get("success", 0) == 1:
|
||||||
|
gt = daily_reward.get("gt", "")
|
||||||
|
challenge = daily_reward.get("challenge", "")
|
||||||
|
raise GeetestTriggered(gt, challenge)
|
||||||
|
if self.region == Region.OVERSEAS:
|
||||||
|
gt_result = daily_reward.get("gt_result")
|
||||||
|
if gt_result is not None and gt_result["success"] != 0:
|
||||||
|
gt = gt_result.get("gt", "")
|
||||||
|
challenge = gt_result.get("challenge", "")
|
||||||
|
raise GeetestTriggered(gt, challenge)
|
||||||
|
|
||||||
if not reward:
|
if not reward:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ from urllib.parse import urljoin
|
|||||||
|
|
||||||
from httpx import URL as _URL
|
from httpx import URL as _URL
|
||||||
|
|
||||||
|
from simnet.errors import RegionNotSupported, NotSupported
|
||||||
from simnet.utils.enum_ import Region, Game
|
from simnet.utils.enum_ import Region, Game
|
||||||
|
|
||||||
URLTypes = Union["URL", str]
|
URLTypes = Union["URL", str]
|
||||||
@ -121,11 +122,11 @@ class InternationalRoute(BaseRoute):
|
|||||||
URL: The URL for the given region.
|
URL: The URL for the given region.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: If the given region is not supported.
|
RegionNotSupported: If the given region is not supported.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not self.urls[region]:
|
if not self.urls[region]:
|
||||||
raise RuntimeError(f"URL does not support {region.name} region.")
|
raise RegionNotSupported(f"URL does not support {region.name} region.")
|
||||||
|
|
||||||
return self.urls[region]
|
return self.urls[region]
|
||||||
|
|
||||||
@ -165,21 +166,21 @@ class GameRoute(BaseRoute):
|
|||||||
URL: The URL for the given region and game.
|
URL: The URL for the given region and game.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: If the given region or game is not supported.
|
RegionNotSupported: If the given region is not supported.
|
||||||
|
GameNotSupported: If the given game is not supported.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not self.urls[region]:
|
if not self.urls[region]:
|
||||||
raise RuntimeError(f"URL does not support {region.name} region.")
|
raise RegionNotSupported(f"URL does not support {region.name} region.")
|
||||||
|
|
||||||
if not self.urls[region][game]:
|
if not self.urls[region][game]:
|
||||||
raise RuntimeError(f"URL does not support {game.name} game for {region.name} region.")
|
raise NotSupported(f"URL does not support {game.name} game for {region.name} region.")
|
||||||
|
|
||||||
return self.urls[region][game]
|
return self.urls[region][game]
|
||||||
|
|
||||||
|
|
||||||
PASSPORT_HOST = "passport-api.mihoyo.com"
|
PASSPORT_HOST = "passport-api.mihoyo.com"
|
||||||
|
|
||||||
|
|
||||||
RECORD_URL = InternationalRoute(
|
RECORD_URL = InternationalRoute(
|
||||||
overseas="https://bbs-api-os.hoyolab.com/game_record",
|
overseas="https://bbs-api-os.hoyolab.com/game_record",
|
||||||
chinese="https://api-takumi-record.mihoyo.com/game_record/app",
|
chinese="https://api-takumi-record.mihoyo.com/game_record/app",
|
||||||
@ -263,5 +264,4 @@ YSULOG_URL = InternationalRoute(
|
|||||||
|
|
||||||
HK4E_URL = Route("https://sg-hk4e-api.hoyoverse.com/common/hk4e_global/")
|
HK4E_URL = Route("https://sg-hk4e-api.hoyoverse.com/common/hk4e_global/")
|
||||||
|
|
||||||
|
|
||||||
CODE_URL = Route("https://sg-hk4e-api.hoyoverse.com/common/apicdkey/api/webExchangeCdkey")
|
CODE_URL = Route("https://sg-hk4e-api.hoyoverse.com/common/apicdkey/api/webExchangeCdkey")
|
||||||
|
@ -23,15 +23,26 @@ class BadRequest(ApiHelperException):
|
|||||||
message (str): The formatted error message of the response.
|
message (str): The formatted error message of the response.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
status_code: int = 200
|
||||||
|
ret_code: int = 0
|
||||||
|
original: str = ""
|
||||||
|
message: str = ""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
response: Optional[Dict[str, Any]] = None,
|
response: Optional[Dict[str, Any]] = None,
|
||||||
message: Optional[str] = None,
|
message: Optional[str] = None,
|
||||||
status_code: Optional[int] = None,
|
status_code: Optional[int] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.status_code = status_code or 0
|
if status_code is not None:
|
||||||
self.ret_code = response.get("retcode", 0) if response else 0
|
self.status_code = status_code
|
||||||
self.original = response.get("message", "") if response else ""
|
ret_code = response.get("ret_code")
|
||||||
|
if ret_code is not None:
|
||||||
|
self.ret_code = ret_code
|
||||||
|
response_message = response.get("message")
|
||||||
|
if response_message is not None:
|
||||||
|
self.original = response_message
|
||||||
|
if message is not None or self.original is not None:
|
||||||
self.message = message or self.original
|
self.message = message or self.original
|
||||||
|
|
||||||
display_code = self.ret_code or self.status_code
|
display_code = self.ret_code or self.status_code
|
||||||
@ -139,6 +150,61 @@ class RedemptionCooldown(RedemptionException):
|
|||||||
message = "Redemption is on cooldown."
|
message = "Redemption is on cooldown."
|
||||||
|
|
||||||
|
|
||||||
|
class NeedChallenge(BadRequest):
|
||||||
|
"""Need to complete a captcha challenge."""
|
||||||
|
|
||||||
|
ret_code = 1034
|
||||||
|
message = "Need to complete a captcha challenge."
|
||||||
|
|
||||||
|
|
||||||
|
class GeetestTriggered(NeedChallenge):
|
||||||
|
"""Geetest triggered during daily reward claim."""
|
||||||
|
|
||||||
|
ret_code = 0
|
||||||
|
message = "Geetest triggered during daily reward claim."
|
||||||
|
|
||||||
|
def __init__(self, gt: str, challenge: str, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.gt = gt
|
||||||
|
self.challenge = challenge
|
||||||
|
|
||||||
|
|
||||||
|
class GeetestChallengeFailed(NeedChallenge):
|
||||||
|
"""Geetest challenge failed."""
|
||||||
|
|
||||||
|
message = "Geetest challenge failed."
|
||||||
|
|
||||||
|
|
||||||
|
class NotSupported(ApiHelperException):
|
||||||
|
"""API not supported."""
|
||||||
|
|
||||||
|
def __init__(self, message: str = "API not supported."):
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
class RegionNotSupported(NotSupported):
|
||||||
|
"""API not supported for this region."""
|
||||||
|
|
||||||
|
def __init__(self, message: str = "API not supported for this region."):
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
class GameNotSupported(NotSupported):
|
||||||
|
"""API not supported for this game."""
|
||||||
|
|
||||||
|
def __init__(self, message: str = "API not supported for this game."):
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
class RequestNotSupported(BadRequest):
|
||||||
|
"""Service not supported for this request."""
|
||||||
|
|
||||||
|
ret_code = -520
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(message="service not supported for this request.", *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class RedemptionClaimed(RedemptionException):
|
class RedemptionClaimed(RedemptionException):
|
||||||
"""Redemption code has been claimed already."""
|
"""Redemption code has been claimed already."""
|
||||||
|
|
||||||
@ -191,9 +257,9 @@ _errors: Dict[int, Union[_TBR, str, Tuple[_TBR, Optional[str]]]] = {
|
|||||||
# chinese
|
# chinese
|
||||||
1008: AccountNotFound,
|
1008: AccountNotFound,
|
||||||
-1104: "This action must be done in the app.",
|
-1104: "This action must be done in the app.",
|
||||||
|
1034: NeedChallenge,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ERRORS: Dict[int, Tuple[_TBR, Optional[str]]] = {
|
ERRORS: Dict[int, Tuple[_TBR, Optional[str]]] = {
|
||||||
ret_code: ((exc, None) if isinstance(exc, type) else (BadRequest, exc) if isinstance(exc, str) else exc)
|
ret_code: ((exc, None) if isinstance(exc, type) else (BadRequest, exc) if isinstance(exc, str) else exc)
|
||||||
for ret_code, exc in _errors.items()
|
for ret_code, exc in _errors.items()
|
||||||
|
Loading…
Reference in New Issue
Block a user