mirror of
https://github.com/PaiGramTeam/SIMNet.git
synced 2024-11-22 14:28:08 +00:00
252 lines
9.1 KiB
Python
252 lines
9.1 KiB
Python
"""Daily reward component."""
|
|
import asyncio
|
|
from typing import Optional, Dict, Any, List
|
|
|
|
from httpx import QueryParams
|
|
|
|
from simnet.client.base import BaseClient
|
|
from simnet.client.routes import REWARD_URL
|
|
from simnet.errors import GeetestTriggered
|
|
from simnet.models.lab.daily import DailyRewardInfo, DailyReward, ClaimedDailyReward
|
|
from simnet.utils.enums import Game, Region
|
|
from simnet.utils.player import recognize_genshin_server, recognize_starrail_server
|
|
|
|
__all__ = ("DailyRewardClient",)
|
|
|
|
|
|
class DailyRewardClient(BaseClient):
|
|
"""A client for interacting with the daily reward system."""
|
|
|
|
async def request_daily_reward(
|
|
self,
|
|
endpoint: str,
|
|
*,
|
|
method: str = "GET",
|
|
challenge: Optional[str] = None,
|
|
validate: Optional[str] = None,
|
|
game: Optional[Game] = None,
|
|
lang: Optional[str] = None,
|
|
params: Optional[Dict[str, Any]] = None,
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Makes a request to the daily reward endpoint.
|
|
|
|
Args:
|
|
endpoint (str): The endpoint to request.
|
|
method (str): The HTTP method to use. Defaults to "GET".
|
|
challenge (str): A challenge string for validating the request. Defaults to None.
|
|
validate (str): A validation string for validating the request. Defaults to None.
|
|
game (Game): The game to request data for. Defaults to None.
|
|
lang (str): The language to use. Defaults to None.
|
|
params (Dict[str, Any]): Any parameters to include in the request.
|
|
|
|
Returns:
|
|
A dictionary containing the response data.
|
|
"""
|
|
headers: Dict[str, str] = {}
|
|
params = QueryParams(params)
|
|
|
|
base_url = REWARD_URL.get_url(self.region, self.game or game)
|
|
params = params.merge(base_url.params)
|
|
params = params.set("lang", lang or self.lang)
|
|
|
|
if challenge is not None:
|
|
headers["x-rpc-challenge"] = challenge
|
|
if validate is not None:
|
|
headers["x-rpc-validate"] = validate
|
|
headers["x-rpc-seccode"] = f"{validate}|jordan"
|
|
|
|
if self.region == Region.CHINESE:
|
|
headers["x-rpc-device_name"] = "Chrome 20 2023"
|
|
headers["x-rpc-channel"] = "chrome"
|
|
headers["x-rpc-device_model"] = "Chrome 2023"
|
|
headers["x-rpc-sys_version"] = "13"
|
|
headers["x-rpc-platform"] = "android"
|
|
if self.game == Game.GENSHIN:
|
|
headers["x-rpc-signgame"] = "hk4e"
|
|
headers["referer"] = (
|
|
"https://act.mihoyo.com/bbs/event/signin/hk4e/index.html?"
|
|
"bbs_auth_required=true&act_id=e202311201442471&"
|
|
"bbs_auth_required=true&bbs_presentation_style=fullscreen&"
|
|
"utm_source=bbs&utm_medium=mys&utm_campaign=icon"
|
|
)
|
|
params = params.set("uid", self.player_id)
|
|
params = params.set("region", recognize_genshin_server(self.player_id))
|
|
if self.game == Game.STARRAIL:
|
|
headers["referer"] = (
|
|
"https://webstatic.mihoyo.com/bbs/event/signin/hkrpg/index.html?"
|
|
"bbs_auth_required=true&act_id=e202304121516551&"
|
|
"bbs_auth_required=true&bbs_presentation_style=fullscreen&"
|
|
"utm_source=bbs&utm_medium=mys&utm_campaign=icon"
|
|
)
|
|
params = params.set("uid", self.player_id)
|
|
params = params.set("region", recognize_starrail_server(self.player_id))
|
|
|
|
url = base_url / endpoint
|
|
|
|
return await self.request_lab(
|
|
url,
|
|
method,
|
|
params=params,
|
|
headers=headers,
|
|
lang=lang,
|
|
)
|
|
|
|
async def get_reward_info(
|
|
self,
|
|
*,
|
|
game: Optional[Game] = None,
|
|
lang: Optional[str] = None,
|
|
) -> DailyRewardInfo:
|
|
"""Gets the daily reward info for the current user.
|
|
|
|
Args:
|
|
game (Game): The game to request data for. Defaults to None.
|
|
lang (str): The language to use. Defaults to None.
|
|
|
|
Returns:
|
|
A DailyRewardInfo object containing information about the user's daily reward status.
|
|
"""
|
|
data = await self.request_daily_reward("info", game=game, lang=lang)
|
|
return DailyRewardInfo(data["is_sign"], data["total_sign_day"])
|
|
|
|
async def get_monthly_rewards(
|
|
self,
|
|
*,
|
|
game: Optional[Game] = None,
|
|
lang: Optional[str] = None,
|
|
) -> List[DailyReward]:
|
|
"""Gets a list of all available rewards for the current month.
|
|
|
|
Args:
|
|
game (Game): The game to request data for. Defaults to None.
|
|
lang (str): The language to use. Defaults to None.
|
|
|
|
Returns:
|
|
A list of DailyReward objects representing the available rewards for the current month.
|
|
"""
|
|
data = await self.request_daily_reward(
|
|
"home",
|
|
game=game or self.game,
|
|
lang=lang,
|
|
)
|
|
return [DailyReward(**i) for i in data["awards"]]
|
|
|
|
async def _get_claimed_rewards_page(
|
|
self,
|
|
page: int,
|
|
*,
|
|
game: Optional[Game] = None,
|
|
lang: Optional[str] = None,
|
|
) -> List[ClaimedDailyReward]:
|
|
"""Gets a single page of claimed rewards for the current user.
|
|
|
|
Args:
|
|
page (int): The page number to retrieve.
|
|
game (Game): The game to request data for. Defaults to None.
|
|
lang (str): The language to use. Defaults to None.
|
|
|
|
Returns:
|
|
A list of ClaimedDailyReward objects representing the claimed rewards for the current user on the specified
|
|
page.
|
|
"""
|
|
data = await self.request_daily_reward(
|
|
"award", params=dict(current_page=page), game=game or self.game, lang=lang
|
|
)
|
|
return [ClaimedDailyReward(**i) for i in data["list"]]
|
|
|
|
async def claimed_rewards(
|
|
self,
|
|
*,
|
|
limit: Optional[int] = None,
|
|
game: Optional[Game] = None,
|
|
lang: Optional[str] = None,
|
|
) -> List[ClaimedDailyReward]:
|
|
"""Gets all claimed rewards for the current user.
|
|
|
|
Args:
|
|
limit (int): The maximum number of rewards to return. Defaults to None.
|
|
game (Game): The game to request data for. Defaults to None.
|
|
lang (str): The language to use. Defaults to None.
|
|
|
|
Returns:
|
|
A list of ClaimedDailyReward objects representing the claimed rewards for the current user.
|
|
"""
|
|
result = []
|
|
index = 0
|
|
page = 1
|
|
|
|
while True:
|
|
if page >= 10:
|
|
break
|
|
|
|
fetched_items = await self._get_claimed_rewards_page(page, game=game or self.game, lang=lang)
|
|
if not fetched_items:
|
|
break
|
|
|
|
# Calculate how many items should be added
|
|
items_to_add = (
|
|
limit - index if limit is not None and limit - index < len(fetched_items) else len(fetched_items)
|
|
)
|
|
|
|
result.extend(fetched_items[:items_to_add])
|
|
index += items_to_add
|
|
|
|
if limit is not None and index >= limit:
|
|
break
|
|
|
|
page += 1
|
|
|
|
return result
|
|
|
|
async def claim_daily_reward(
|
|
self,
|
|
*,
|
|
challenge: Optional[str] = None,
|
|
validate: Optional[str] = None,
|
|
game: Optional[Game] = None,
|
|
lang: Optional[str] = None,
|
|
reward: bool = True,
|
|
) -> Optional[DailyReward]:
|
|
"""
|
|
Signs into lab and claims the daily reward.
|
|
|
|
Args:
|
|
challenge (str): A challenge string for validating the request. Defaults to None.
|
|
validate (str): A validation string for validating the request. Defaults to None.
|
|
game (Game): The game to claim the reward for. Defaults to None.
|
|
lang (str): The language to use. Defaults to None.
|
|
reward (bool): Whether to return the claimed reward. Defaults to True.
|
|
|
|
Returns:
|
|
If `reward` is True, a DailyReward object representing the claimed reward. Otherwise, None.
|
|
"""
|
|
daily_reward = await self.request_daily_reward(
|
|
"sign",
|
|
method="POST",
|
|
game=game or self.game,
|
|
lang=lang,
|
|
challenge=challenge,
|
|
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:
|
|
return None
|
|
|
|
info, rewards = await asyncio.gather(
|
|
self.get_reward_info(game=game or self.game, lang=lang),
|
|
self.get_monthly_rewards(game=game or self.game, lang=lang),
|
|
)
|
|
return rewards[info.claimed_rewards - 1]
|