feat: wrap all objects on /resource endpoint

This commit is contained in:
tretrauit 2023-06-30 20:55:30 +07:00
parent 891cf71aa7
commit 69a53da8ae
2 changed files with 188 additions and 16 deletions

View File

@ -4,11 +4,35 @@ Class wrapper for API endpoint /resource
class Segment:
"""
A segment of the game archive.
Attributes:
path (str): Segment download path.
md5 (str): Segment md5 checksum.
package_size (int | None): Segment package size.
"""
path: str
md5: str
# str -> int and checked if int is 0 then None
package_size: int | None
def __init__(self, path: str, md5: str, package_size: int | None) -> None:
self.path = path
self.md5 = md5
self.package_size = package_size
@staticmethod
def from_dict(data: dict) -> "Segment":
return Segment(
data["path"],
data["md5"],
int(data["package_size"])
if data["package_size"] and data["package_size"] != "0"
else None,
)
class VoicePack:
"""
@ -17,7 +41,12 @@ class VoicePack:
`name` maybe converted from `path` if the server returns empty string.
Attributes:
TODO
language (str): Language of the voice pack.
name (str): Voice pack archive name.
path (str): Voice pack download path.
size (int): Voice pack size.
md5 (str): Voice pack md5 checksum.
package_size (int): Voice pack package size.
"""
language: str
@ -29,6 +58,33 @@ class VoicePack:
# str -> int
package_size: int
def __init__(
self,
language: str,
name: str,
path: str,
size: int,
md5: str,
package_size: int,
) -> None:
self.language = language
self.name = name
self.path = path
self.size = size
self.md5 = md5
self.package_size = package_size
@staticmethod
def from_dict(data: dict) -> "VoicePack":
return VoicePack(
data["language"],
data["name"],
data["path"],
int(data["size"]),
data["md5"],
int(data["package_size"]),
)
class Diff:
"""
@ -49,6 +105,39 @@ class Diff:
# str -> int
package_size: int
def __init__(
self,
name: str,
version: str,
path: str,
size: int,
md5: str,
is_recommended_update: bool,
voice_packs: list[VoicePack],
package_size: int,
) -> None:
self.name = name
self.version = version
self.path = path
self.size = size
self.md5 = md5
self.is_recommended_update = is_recommended_update
self.voice_packs = voice_packs
self.package_size = package_size
@staticmethod
def from_dict(data: dict) -> "Diff":
return Diff(
data["name"],
data["version"],
data["path"],
int(data["size"]),
data["md5"],
data["is_recommended_update"],
[VoicePack.from_dict(i) for i in data["voice_packs"]],
int(data["package_size"]),
)
class Latest:
"""
@ -58,13 +147,35 @@ class Latest:
and if `path` is empty too then it'll convert the name from the first
segment of `segments` list.
`path` maybe None if the server returns empty string, in that case
you'll have to download the game using `segments` list and merge them.
`voice_packs` will be empty for Star Rail, they force you to download
in-game instead.
`decompressed_path` is useful for repairing game files by only having
to re-download the corrupted files.
`segments` is a list of game archive segments, you'll have to download
them and merge them together to get the full game archive. Not available
on Star Rail.
Attributes:
TODO
name (str): Game archive name.
version (str): Game version in the archive.
path (str | None): Game archive download path.
size (int): Game archive size in bytes.
md5 (str): Game archive MD5 checksum.
entry (str): Game entry file (e.g. GenshinImpact.exe).
voice_packs (list[VoicePack]): Game voice packs.
decompressed_path (str | None): Game archive decompressed path.
segments (list[Segment]): Game archive segments.
package_size (int): Game archive package size in bytes.
"""
name: str
version: str
path: str
path: str | None
# str -> int
size: int
md5: str
@ -110,14 +221,14 @@ class Latest:
return Latest(
data["name"],
data["version"],
data["path"],
data["size"],
data["path"] if data["path"] != "" else None,
int(data["size"]),
data["md5"],
data["entry"],
[VoicePack.from_dict(i) for i in data["voice_packs"]],
data["decompressed_path"],
data["decompressed_path"] if data["decompressed_path"] != "" else None,
[Segment.from_dict(i) for i in data["segments"]],
data["package_size"],
int(data["package_size"]),
)
@ -149,27 +260,96 @@ class Plugin:
# str -> int
package_size: int
def __init__(
self,
name: str,
version: str | None,
path: str,
size: int,
md5: str,
entry: str | None,
package_size: int,
) -> None:
self.name = name
self.version = version
self.path = path
self.size = size
self.md5 = md5
self.entry = entry
self.package_size = package_size
@staticmethod
def from_dict(data: dict) -> "Plugin":
return Plugin(
data["name"],
data["version"] if data["version"] != "" else None,
data["path"],
int(data["size"]),
data["md5"],
data["entry"] if data["entry"] != "" else None,
int(data["package_size"]),
)
class LauncherPlugin:
plugins: list[Plugin]
# str -> int
version: int
def __init__(self, plugins: list[Plugin], version: int) -> None:
self.plugins = plugins
self.version = version
@staticmethod
def from_dict(data: dict) -> "LauncherPlugin":
return LauncherPlugin(
[Plugin.from_dict(i) for i in data["plugins"]], int(data["version"])
)
class DeprecatedPackage:
name: str
md5: str
def __init__(self, name: str, md5: str) -> None:
self.name = name
self.md5 = md5
@staticmethod
def from_dict(data: dict) -> "DeprecatedPackage":
return DeprecatedPackage(data["name"], data["md5"])
class DeprecatedFile:
path: str
# str but checked for empty string
md5: str | None
def __init__(self, path: str, md5: str | None) -> None:
self.path = path
self.md5 = md5
@staticmethod
def from_dict(data: dict) -> "DeprecatedFile":
return DeprecatedFile(data["path"], data["md5"] if data["md5"] != "" else None)
class Resource:
"""
Data class for /resource endpoint
I'm still unclear about `force_update` and `sdk` attributes, so I'll
leave them as None for now.
Attributes:
game (Game): Game resource information.
plugin (LauncherPlugin): Launcher plugin information.
web_url (str): Game official launcher web URL.
force_update (None): Not used by official launcher I guess?
pre_download_game (Game | None): Pre-download game resource information.
deprecated_packages (list[DeprecatedPackage]): Deprecated game packages.
sdk (None): Maybe for Bilibili version of Genshin?
deprecated_files (list[DeprecatedFile]): Deprecated game files.
"""
# I'm generous enough to convert the string into int
@ -198,14 +378,6 @@ class Resource:
sdk: None,
deprecated_files: list[DeprecatedFile],
) -> None:
# Fixups
game_latest_path = game.latest.path
if game.latest.name == "":
print("A")
if game_latest_path == "":
game.latest.name = game.latest.segments[0].path.split("/")[-1]
else:
game.latest.name = game_latest_path.split("/")[-1]
self.game = game
self.plugin = plugin
self.web_url = web_url

View File

@ -10,7 +10,7 @@ def get_resource(channel: GameChannel = GameChannel.Overseas) -> Resource:
Get game resource information from the launcher API.
Args:
channel: Game channel to get the resource information from. (os, cn)
channel: Game channel to get the resource information from.
Returns:
Resource: Game resource information.