Compare commits

..

2 Commits

Author SHA1 Message Date
a7d763d847 feat(hsr): add voicepack related commands 2024-02-06 14:24:44 +07:00
fa011a11a1 fix(cli): fix 416 response code 2024-02-06 14:24:15 +07:00
3 changed files with 115 additions and 4 deletions

View File

@ -75,6 +75,113 @@ def callback(
command.add_style("warn", fg="yellow") command.add_style("warn", fg="yellow")
class VoicepackListInstalled(Command):
name = "hsr voicepack list-installed"
description = "Get the installed voicepacks"
options = default_options
def handle(self):
callback(command=self)
installed_voicepacks_str = [
f"<comment>{str(x.name)}</comment>"
for x in State.game.get_installed_voicepacks()
]
self.line(f"Installed voicepacks: {", ".join(installed_voicepacks_str)}")
class VoicepackUpdateAll(Command):
name = "hsr voicepack update-all"
description = "Updates all installed voicepacks"
options = default_options + [
option(
"auto-repair", "R", description="Automatically repair the game if needed"
),
option("pre-download", description="Pre-download the game if available"),
option(
"from-version", description="Update from a specific version", flag=False
),
]
def handle(self):
callback(command=self)
auto_repair = self.option("auto-repair")
pre_download = self.option("pre-download")
from_version = self.option("from-version")
if auto_repair:
self.line("<comment>Auto-repair is enabled.</comment>")
if from_version:
self.line(f"Updating from version: <comment>{from_version}</comment>")
State.game.version_override = from_version
# Get installed voicepacks
installed_voicepacks = State.game.get_installed_voicepacks()
installed_voicepacks_str = [
f"<comment>{str(x.name)}</comment>" for x in installed_voicepacks
]
self.line(f"Installed voicepacks: {", ".join(installed_voicepacks_str)}")
progress = utils.ProgressIndicator(self)
progress.start("Checking for updates... ")
try:
update_diff = State.game.get_update(pre_download=pre_download)
game_info = State.game.get_remote_game(pre_download=pre_download)
except Exception as e:
progress.finish(
f"<error>Update checking failed with following error: {e} ({e.__context__})</error>"
)
return
if update_diff is None:
progress.finish("<comment>Game is already updated.</comment>")
return
progress.finish("<comment>Update available.</comment>")
self.line(
f"The current version is: <comment>{State.game.get_version_str()}</comment>"
)
self.line(
f"The latest version is: <comment>{game_info.latest.version}</comment>"
)
if not self.confirm("Do you want to update the game?"):
self.line("<error>Update aborted.</error>")
return
# Voicepack update
for remote_voicepack in update_diff.voice_packs:
if remote_voicepack.language not in installed_voicepacks:
continue
# Voicepack is installed, update it
self.line(
f"Downloading update package for language: <comment>{remote_voicepack.language.name}</comment>... "
)
archive_file = State.game.cache.joinpath(remote_voicepack.name)
try:
download_result = utils.download(
remote_voicepack.path, archive_file, file_len=update_diff.size
)
except Exception as e:
self.line_error(f"<error>Couldn't download update: {e}</error>")
return
if not download_result:
self.line_error("<error>Download failed.</error>")
return
self.line("Download completed.")
progress = utils.ProgressIndicator(self)
progress.start("Applying update package...")
try:
State.game.apply_update_archive(
archive_file=archive_file, auto_repair=auto_repair
)
except Exception as e:
progress.finish(
f"<error>Couldn't apply update: {e} ({e.__context__})</error>"
)
return
progress.finish(
f"<comment>Update applied for language {remote_voicepack.language.name}.</comment>"
)
self.line("Setting version config... ")
State.game.set_version_config()
self.line(
f"The game has been updated to version: <comment>{State.game.get_version_str()}</comment>"
)
class PatchTypeCommand(Command): class PatchTypeCommand(Command):
name = "hsr patch type" name = "hsr patch type"
description = "Get the patch type of the game" description = "Get the patch type of the game"
@ -285,7 +392,9 @@ class UpdateCommand(Command):
"auto-repair", "R", description="Automatically repair the game if needed" "auto-repair", "R", description="Automatically repair the game if needed"
), ),
option("pre-download", description="Pre-download the game if available"), option("pre-download", description="Pre-download the game if available"),
option("from-version", description="Update from a specific version"), option(
"from-version", description="Update from a specific version", flag=False
),
] ]
def handle(self): def handle(self):
@ -436,4 +545,6 @@ commands = [
PatchTypeCommand, PatchTypeCommand,
UpdatePatchCommand, UpdatePatchCommand,
UpdateCommand, UpdateCommand,
VoicepackListInstalled,
VoicepackUpdateAll,
] ]

View File

@ -74,9 +74,9 @@ def download(url, out: Path, file_len: int = None, overwrite: bool = False) -> b
out.touch() out.touch()
# Streaming, so we can iterate over the response. # Streaming, so we can iterate over the response.
response = requests.get(url=url, headers=headers, stream=True) response = requests.get(url=url, headers=headers, stream=True)
response.raise_for_status()
if response.status_code == 416: if response.status_code == 416:
return return True
response.raise_for_status()
# Sizes in bytes. # Sizes in bytes.
total_size = int(response.headers.get("content-length", 0)) total_size = int(response.headers.get("content-length", 0))
block_size = 32768 block_size = 32768

View File

@ -300,7 +300,7 @@ class Game(GameABC):
): ):
if child.is_dir(): if child.is_dir():
try: try:
voicepacks.append(VoicePackLanguage(child.name)) voicepacks.append(VoicePackLanguage[child.name])
except ValueError: except ValueError:
pass pass
return voicepacks return voicepacks