mirror of
https://github.com/PaiGramTeam/SIMNet.git
synced 2024-11-22 22:37:24 +00:00
223 lines
7.6 KiB
Python
223 lines
7.6 KiB
Python
|
"""Daily reward component."""
|
||
|
import asyncio
|
||
|
from typing import Optional, Dict, Any, List
|
||
|
|
||
|
from simnet.client.base import BaseClient
|
||
|
from simnet.utils.ds import hex_digest
|
||
|
from simnet.client.routes import REWARD_URL
|
||
|
from simnet.models.lab.daily import DailyRewardInfo, DailyReward, ClaimedDailyReward
|
||
|
from simnet.utils.enum_ import Game, Region
|
||
|
|
||
|
__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.
|
||
|
"""
|
||
|
new_ds: bool = False
|
||
|
headers: Optional[Dict[str, str]] = None
|
||
|
if self.region == Region.CHINESE:
|
||
|
headers = {}
|
||
|
if challenge is not None and validate is not None:
|
||
|
headers["x-rpc-challenge"] = challenge
|
||
|
headers["x-rpc-validate"] = validate
|
||
|
headers["x-rpc-seccode"] = f"{validate}|jordan"
|
||
|
headers["Referer"] = (
|
||
|
"https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?"
|
||
|
"bbs_auth_required=true&act_id=e202009291139501&utm_source=bbs&utm_medium=mys&utm_campaign=icon"
|
||
|
)
|
||
|
|
||
|
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"
|
||
|
device_id = self.device_id
|
||
|
hash_value = hex_digest(device_id)
|
||
|
headers["x-rpc-device_fp"] = hash_value[:13]
|
||
|
new_ds = endpoint == "sign"
|
||
|
|
||
|
base_url = REWARD_URL.get_url(self.region, self.game or game)
|
||
|
url = (base_url / endpoint).update_query(**base_url.query)
|
||
|
|
||
|
return await self.request_lab(
|
||
|
method, url, params=params, headers=headers, lang=lang, new_ds=new_ds
|
||
|
)
|
||
|
|
||
|
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,
|
||
|
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, 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, 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.
|
||
|
"""
|
||
|
await self.request_daily_reward(
|
||
|
"sign",
|
||
|
method="POST",
|
||
|
game=game,
|
||
|
lang=lang,
|
||
|
challenge=challenge,
|
||
|
validate=validate,
|
||
|
)
|
||
|
|
||
|
if not reward:
|
||
|
return None
|
||
|
|
||
|
info, rewards = await asyncio.gather(
|
||
|
self.get_reward_info(game=game, lang=lang),
|
||
|
self.get_monthly_rewards(game=game, lang=lang),
|
||
|
)
|
||
|
return rewards[info.claimed_rewards - 1]
|