Update tests
This commit is contained in:
parent
a7ddd0c49a
commit
048a7ac9d0
@ -1,6 +1,7 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import asyncio
|
import asyncio
|
||||||
import worthless
|
import worthless
|
||||||
|
from worthless.classes import launcher
|
||||||
client = worthless.Launcher()
|
client = worthless.Launcher()
|
||||||
|
|
||||||
|
|
||||||
@ -15,13 +16,13 @@ class LauncherTest(unittest.TestCase):
|
|||||||
launcher_info = asyncio.run(client.get_launcher_info())
|
launcher_info = asyncio.run(client.get_launcher_info())
|
||||||
print("get_launcher_info test.")
|
print("get_launcher_info test.")
|
||||||
print("get_launcher_info: ", launcher_info)
|
print("get_launcher_info: ", launcher_info)
|
||||||
self.assertIsInstance(launcher_info, dict)
|
self.assertIsInstance(launcher_info, launcher.Info)
|
||||||
|
|
||||||
def test_get_launcher_full_info(self):
|
def test_get_launcher_full_info(self):
|
||||||
launcher_info = asyncio.run(client.get_launcher_full_info())
|
launcher_info = asyncio.run(client.get_launcher_full_info())
|
||||||
print("get_launcher_full_info test.")
|
print("get_launcher_full_info test.")
|
||||||
print("get_launcher_full_info: ", launcher_info)
|
print("get_launcher_full_info: ", launcher_info)
|
||||||
self.assertIsInstance(launcher_info, dict)
|
self.assertIsInstance(launcher_info, launcher.Info)
|
||||||
|
|
||||||
def test_get_launcher_background_url(self):
|
def test_get_launcher_background_url(self):
|
||||||
bg_url = asyncio.run(client.get_launcher_background_url())
|
bg_url = asyncio.run(client.get_launcher_background_url())
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
from app import main
|
from worthless import gui
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
gui.main()
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
from worthless.classes.launcher import background, banner, iconbutton, iconotherlink, info, post
|
||||||
|
Background = background.Background
|
||||||
|
Banner = banner.Banner
|
||||||
|
IconButton = iconbutton.IconButton
|
||||||
|
IconOtherLink = iconotherlink.IconOtherLink
|
||||||
|
Info = info.Info
|
||||||
|
Post = post.Post
|
@ -1,4 +1,4 @@
|
|||||||
from worthless.classes.launcher.launchericonotherlink import IconOtherLink
|
from worthless.classes.launcher.iconotherlink import IconOtherLink
|
||||||
|
|
||||||
|
|
||||||
class IconButton:
|
class IconButton:
|
||||||
|
@ -1,3 +1,28 @@
|
|||||||
class LauncherInfo:
|
from worthless.classes.launcher import background, banner, iconbutton, post
|
||||||
def __init__(self):
|
Background = background.Background
|
||||||
pass
|
Banner = banner.Banner
|
||||||
|
IconButton = iconbutton.IconButton
|
||||||
|
Post = post.Post
|
||||||
|
|
||||||
|
|
||||||
|
class Info:
|
||||||
|
def __init__(self, lc_background: Background, lc_banner: list[Banner], icon: list[IconButton], lc_post: list[Post]):
|
||||||
|
self.background = lc_background
|
||||||
|
self.banner = lc_banner
|
||||||
|
self.icon = icon
|
||||||
|
self.post = lc_post
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_dict(data):
|
||||||
|
bg = Background.from_dict(data["adv"])
|
||||||
|
lc_banner = []
|
||||||
|
for b in data["banner"]:
|
||||||
|
lc_banner.append(Banner.from_dict(b))
|
||||||
|
lc_icon = []
|
||||||
|
for i in data["icon"]:
|
||||||
|
lc_icon.append(IconButton.from_dict(i))
|
||||||
|
lc_post = []
|
||||||
|
for p in data["post"]:
|
||||||
|
lc_post.append(Post.from_dict(p))
|
||||||
|
return Info(bg, lc_banner, lc_icon, lc_post)
|
||||||
|
|
||||||
|
@ -1,29 +1,38 @@
|
|||||||
class Banner:
|
class Post:
|
||||||
"""Contains a launcher banner information
|
"""Contains a launcher post information
|
||||||
|
|
||||||
Note that the banner name is in chinese, so you may not find this variable useful.
|
The `type` variable can be POST_TYPE_ANNOUNCE, POST_TYPE_ACTIVITY and POST_TYPE_INFO
|
||||||
Also, the banner has a variable called `order`, you can use that to sort the banner
|
where announce is an announcement, activity is an activity/event and info is an information.
|
||||||
like the official launcher does.
|
|
||||||
|
The `show_time` variable is the time in DD/MM format when the post will be shown.
|
||||||
|
|
||||||
|
Also, `tittle` is not my typo, and it's the server intention (probably there are clients
|
||||||
|
where their developers wrote `tittle` instead of `title`), and the post has a variable
|
||||||
|
called `order`, you can use that to sort the post like the official launcher does.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
|
||||||
- :class:`str` banner_id: The launcher banner id.
|
- :class:`str` post_id: The launcher post id.
|
||||||
- :class:`str` name: The banner name.
|
- :class:`str` type: The post type, as explained above.
|
||||||
- :class:`str` img: The banner image url.
|
- :class:`str` tittle: The post title.
|
||||||
- :class:`str` url: The banner target url.
|
- :class:`str` url: The post target url.
|
||||||
- :class:`str` order: The banner order.
|
- :class:`str` show_time: The time when the post will be shown.
|
||||||
- :class:`str` name: The banner name.
|
- :class:`str` order: The post order.
|
||||||
|
- :class:`str` title: The post title.
|
||||||
- :class:`dict` raw: The banner raw information.
|
- :class:`dict` raw: The banner raw information.
|
||||||
"""
|
"""
|
||||||
def __init__(self, banner_id, name, img, url, order, raw):
|
def __init__(self, post_id, post_type, tittle, url, show_time, order, title, raw):
|
||||||
self.banner_id = banner_id
|
self.post_id = post_id
|
||||||
self.name = name
|
self.type = post_type # Shadow built-in name `type`
|
||||||
self.img = img
|
self.tittle = tittle
|
||||||
self.url = url
|
self.url = url
|
||||||
|
self.show_time = show_time
|
||||||
self.order = order
|
self.order = order
|
||||||
|
self.title = title
|
||||||
self.raw = raw
|
self.raw = raw
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_dict(data) -> 'Banner':
|
def from_dict(data) -> 'Post':
|
||||||
"""Creates a launcher banner from a dictionary."""
|
"""Creates a launcher post from a dictionary."""
|
||||||
return Banner(data["banner_id"], data["name"], data["img"], data["url"], data["order"], data)
|
return Post(data["post_id"], data["type"], data["tittle"], data["url"],
|
||||||
|
data["show_time"], data["order"], data["title"], data)
|
||||||
|
@ -1,28 +1,42 @@
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
import locale
|
import locale
|
||||||
from worthless import constants
|
from worthless import constants
|
||||||
|
from pathlib import Path
|
||||||
|
from worthless.classes import launcher
|
||||||
|
|
||||||
|
|
||||||
class Launcher:
|
class Launcher:
|
||||||
def __init__(self):
|
"""
|
||||||
|
Contains functions to get information from server and client like the official launcher.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, gamedir=Path.cwd()):
|
||||||
|
"""Initialize the launcher API
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gamedir (Path): Path to the game directory.
|
||||||
|
"""
|
||||||
self._api = constants.LAUNCHER_API_URL
|
self._api = constants.LAUNCHER_API_URL
|
||||||
self._lang = self._get_system_language()
|
self._lang = self._get_system_language()
|
||||||
|
if isinstance(gamedir, str):
|
||||||
|
gamedir = Path(gamedir)
|
||||||
|
self._gamedir = gamedir.resolve()
|
||||||
|
|
||||||
# Workaround because miHoYo uses retcode for their API
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _get(url, **kwargs) -> dict:
|
async def _get(url, **kwargs) -> dict:
|
||||||
|
# Workaround because miHoYo uses retcode for their API instead of HTTP status code
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
rsp = await session.get(url, **kwargs)
|
rsp = await session.get(url, **kwargs)
|
||||||
rsp_json = await rsp.json()
|
rsp_json = await rsp.json()
|
||||||
# Why retcode seriously? They can just make the page not returning 200 status code.
|
|
||||||
if rsp_json["retcode"] != 0:
|
if rsp_json["retcode"] != 0:
|
||||||
|
# TODO: Add more information to the error message
|
||||||
raise aiohttp.ClientResponseError(code=rsp_json["retcode"],
|
raise aiohttp.ClientResponseError(code=rsp_json["retcode"],
|
||||||
message=rsp_json["message"],
|
message=rsp_json["message"],
|
||||||
history=rsp.history,
|
history=rsp.history,
|
||||||
request_info=rsp.request_info)
|
request_info=rsp.request_info)
|
||||||
return rsp_json
|
return rsp_json
|
||||||
|
|
||||||
async def _get_launcher_info(self, adv=True) -> dict:
|
async def _get_launcher_info(self, adv=True) -> launcher.Info:
|
||||||
params = {"key": "gcStgarh",
|
params = {"key": "gcStgarh",
|
||||||
"filter_adv": str(adv).lower(),
|
"filter_adv": str(adv).lower(),
|
||||||
"launcher_id": "10",
|
"launcher_id": "10",
|
||||||
@ -31,13 +45,17 @@ class Launcher:
|
|||||||
if rsp["data"]["adv"] is None:
|
if rsp["data"]["adv"] is None:
|
||||||
params["language"] = "en-us"
|
params["language"] = "en-us"
|
||||||
rsp = await self._get(self._api + "/content", params=params)
|
rsp = await self._get(self._api + "/content", params=params)
|
||||||
return rsp
|
lc_info = launcher.Info.from_dict(rsp["data"])
|
||||||
|
return lc_info
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_system_language() -> str:
|
def _get_system_language() -> str:
|
||||||
|
"""Gets system language compatible with server parameters.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
System language with format xx-xx.
|
||||||
"""
|
"""
|
||||||
Get system language compatible with server parameters.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
lang = locale.getdefaultlocale()[0]
|
lang = locale.getdefaultlocale()[0]
|
||||||
lowercase_lang = lang.lower().replace("_", "-")
|
lowercase_lang = lang.lower().replace("_", "-")
|
||||||
@ -45,38 +63,84 @@ class Launcher:
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return "en-us"
|
return "en-us"
|
||||||
|
|
||||||
|
async def override_gamedir(self, gamedir: str) -> None:
|
||||||
|
"""Overrides game directory with another directory.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gamedir (str): New directory to override with.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._gamedir = Path(gamedir).resolve()
|
||||||
|
|
||||||
async def override_language(self, language: str) -> None:
|
async def override_language(self, language: str) -> None:
|
||||||
|
"""Overrides system detected language with another language.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
language (str): Language to override with.
|
||||||
"""
|
"""
|
||||||
Override system detected language with another language.
|
|
||||||
:param language: The language to override with.
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
self._lang = language.lower().replace("_", "-")
|
self._lang = language.lower().replace("_", "-")
|
||||||
|
|
||||||
async def get_version_info(self) -> dict:
|
async def get_version_info(self) -> dict:
|
||||||
|
"""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={"key": "gcStgarh",
|
rsp = await self._get(self._api + "/resource", params={"key": "gcStgarh",
|
||||||
"launcher_id": "10"})
|
"launcher_id": "10"})
|
||||||
return rsp
|
return rsp
|
||||||
|
|
||||||
async def get_launcher_info(self) -> dict:
|
async def get_launcher_info(self) -> launcher.Info:
|
||||||
"""
|
"""Gets short launcher info from the server
|
||||||
This function will get short launcher info from the server (only contains background image and FAQ)
|
|
||||||
:return: dict: 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)
|
return await self._get_launcher_info(adv=True)
|
||||||
|
|
||||||
async def get_launcher_full_info(self) -> dict:
|
async def get_launcher_full_info(self) -> launcher.Info:
|
||||||
"""
|
"""Gets full launcher info from the server.
|
||||||
This function will get full launcher info from the server.
|
|
||||||
Since the server content is very long for a short explanation, you should see it manually.
|
Returns:
|
||||||
:return: dict: Launcher info from the server.
|
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)
|
return await self._get_launcher_info(adv=False)
|
||||||
|
|
||||||
async def get_launcher_background_url(self) -> str:
|
async def get_launcher_background_url(self) -> str:
|
||||||
|
"""Gets launcher background image url from the server.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Background image url.
|
||||||
|
Raises:
|
||||||
|
aiohttp.ClientResponseError: An error occurred while fetching the background image.
|
||||||
"""
|
"""
|
||||||
This function will get launcher background image from the server.
|
|
||||||
:return: str: Background image URL.
|
|
||||||
"""
|
|
||||||
rsp = await self.get_launcher_info()
|
rsp = await self.get_launcher_info()
|
||||||
return rsp["data"]["adv"]["background"]
|
return rsp.background.background
|
||||||
|
|
||||||
|
async def get_system_game_info(self, table_handle, keys, require_all_keys):
|
||||||
|
# TODO: Implement
|
||||||
|
raise NotImplementedError("Not implemented yet.")
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def get_system_game_version(self) -> str:
|
||||||
|
"""Gets the game version from the current system.
|
||||||
|
:return: str: System game version.
|
||||||
|
"""
|
||||||
|
|
||||||
|
rsp = await self.get_version_info()
|
||||||
|
return rsp["data"]["system"]["game_version"]
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
import constants
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class Patcher:
|
||||||
|
def __init__(self, gamedir=Path.cwd()):
|
||||||
|
self._gamedir = gamedir
|
||||||
|
self._patch_url = constants.PATCH_GIT_URL
|
||||||
|
|
||||||
|
def override_patch_url(self, url) -> None:
|
||||||
|
"""
|
||||||
|
Override the patch url.
|
||||||
|
:param url: Patch repository url, the url must be a valid git repository.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._patch_url = url
|
||||||
|
|
||||||
|
def download_patch(self) -> None:
|
||||||
|
"""
|
||||||
|
If `git` exists, this will clone the patch git url and save it to a temporary directory.
|
||||||
|
Else, this will download the patch from the patch url and save it to a temporary directory. (Not reliable)
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def apply_patch(self, crash_fix=False) -> None:
|
||||||
|
"""
|
||||||
|
Patch the game (and optionally patch the login door crash fix if specified)
|
||||||
|
:param crash_fix: Whether to patch the login door crash fix or not
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def revert_patch(self):
|
||||||
|
"""
|
||||||
|
Revert the patch (and revert the login door crash fix if patched)
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
pass
|
Loading…
Reference in New Issue
Block a user