feat: wrap all objects on /resource endpoint
This commit is contained in:
parent
891cf71aa7
commit
69a53da8ae
@ -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
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user