worthless-launcher/worthless/launcher.py

149 lines
5.0 KiB
Python

import locale
import aiohttp
from worthless import constants
from worthless.classes import launcher, installer
from worthless.game.gameenums import Variant
def _get_system_language() -> str:
"""Gets system language compatible with server parameters.
Return:
System language with format xx-xx (e.g. en-us).
"""
try:
lang = locale.getdefaultlocale()[0]
lowercase_lang = lang.lower().replace("_", "-")
return lowercase_lang
except ValueError:
return "en-us" # Fallback to English if locale is not supported
class Launcher:
"""
Contains functions to get information from server and client like the official launcher.
"""
def __init__(
self,
language: str = None,
variant: Variant = None,
):
"""Initialize the launcher API"""
if not variant:
variant = Variant.INTERNATIONAL
if not language:
language = _get_system_language()
self._variant = variant
match variant:
case Variant.INTERNATIONAL:
self._api = constants.LAUNCHER_API_URL_OS
self._params = {
"key": "gcStgarh",
"launcher_id": "10",
}
self._lang = language.lower().replace("_", "-")
case Variant.CHINESE:
self._api = constants.LAUNCHER_API_URL_CN
self._params = {
"key": "eYd89JmJ",
"launcher_id": "18",
"channel_id": "1",
}
self._lang = (
"zh-cn" # Uses Chinese language because this is Chinese version
)
case Variant.BILIBILI:
self._api = constants.LAUNCHER_API_URL_CN
self._params = {
"key": "KAtdSsoQ",
"launcher_id": "17",
"channel_id": "14",
}
self._lang = (
"zh-cn" # Use Chinese language because this is Chinese version
)
# There is one for beta version too, but I don't have access to that version
self._session = aiohttp.ClientSession()
async def _get(self, url, **kwargs) -> dict:
# Workaround because miHoYo uses retcode for their API instead of HTTP status code (always 200)
rsp = await self._session.get(url, **kwargs)
rsp_json = await rsp.json()
if rsp_json["retcode"] != 0:
# TODO: Add more information to the error message
raise aiohttp.ClientResponseError(
message=rsp_json["message"],
history=rsp.history,
request_info=rsp.request_info,
headers=rsp.headers,
status=rsp_json["retcode"],
)
return rsp_json
@property
def lang(self):
return self._lang
async def _get_launcher_info(self, adv=True) -> launcher.Info:
params = self._params | {"filter_adv": str(adv).lower(), "language": self._lang}
rsp = await self._get(self._api + "/content", params=params)
if rsp["data"]["adv"] is None:
params["language"] = "en-us"
rsp = await self._get(self._api + "/content", params=params)
lc_info = launcher.Info.from_dict(rsp["data"])
return lc_info
@lang.setter
def lang(self, language: str) -> None:
"""Sets current language to another language in xx-xx format.
This method will automatically convert language with xx_XX to xx-xx (e.g. en_US to en-us)
Args:
language (str): Language to override with.
"""
self._lang = language.lower().replace("_", "-")
async def get_resource_info(self) -> installer.Resource:
"""Gets version info from the server.
This function gets version info including audio pack and their download url from the server.
Returns:
A dict containing version info from the server.
Raises:
aiohttp.ClientResponseError: An error occurred while fetching the information.
"""
rsp = await self._get(self._api + "/resource", params=self._params)
return installer.Resource.from_dict(rsp["data"])
async def get_launcher_info(self) -> launcher.Info:
"""Gets short launcher info from the server
This function only gets background image and the FAQ url from the server.
Returns:
A dict containing short launcher info from the server.
Raises:
aiohttp.ClientResponseError: An error occurred while fetching the information.
"""
return await self._get_launcher_info(adv=True)
async def get_launcher_full_info(self) -> launcher.Info:
"""Gets full launcher info from the server.
Returns:
A dict containing full launcher info from the server.
Raises:
aiohttp.ClientResponseError: An error occurred while fetching the information.
"""
return await self._get_launcher_info(adv=False)