feat: verify_game_file, rename verify_game to verify_game_files
You can now use verify_game_file to verify a game file from a pkg_version (either parsed pkg_version or a path to pkg_version is fine), and verify_game_files to verify all game files from a pkg_version
This commit is contained in:
parent
f61e4a39cf
commit
208b34c9df
|
@ -6,7 +6,7 @@ import json
|
|||
import hashlib
|
||||
import logging
|
||||
from os import PathLike
|
||||
from pathlib import Path
|
||||
from pathlib import Path, PurePath
|
||||
|
||||
from worthless import constants
|
||||
from worthless.launcher import Launcher
|
||||
|
@ -24,6 +24,28 @@ from worthless.game.launcherconfig import LauncherConfig
|
|||
_logger = logging.getLogger("worthless.Game")
|
||||
|
||||
|
||||
def _calculate_md5(file: str | bytes | PathLike):
|
||||
file = Path(file)
|
||||
if not file.exists():
|
||||
return ""
|
||||
with file.open("rb") as f:
|
||||
file_hash = hashlib.md5()
|
||||
while chunk := f.read(8196):
|
||||
file_hash.update(chunk)
|
||||
return file_hash.hexdigest()
|
||||
|
||||
|
||||
def _parse_pkg_version(pkg_version: str | bytes | PathLike):
|
||||
contents = Path(pkg_version).read_text()
|
||||
pkg_version = []
|
||||
for content in contents.split("\r\n"):
|
||||
if not content.strip():
|
||||
continue
|
||||
info = json.loads(content)
|
||||
pkg_version.append(info)
|
||||
return pkg_version
|
||||
|
||||
|
||||
def voicepack_lang_translate(lang: str, base_language="game") -> str | None:
|
||||
"""
|
||||
Translates the voicepack language to the language code used by the game (and reverse)
|
||||
|
@ -58,7 +80,9 @@ def voicepack_lang_translate(lang: str, base_language="game") -> str | None:
|
|||
return
|
||||
|
||||
|
||||
def get_voicepack_archive_language(archive: str | bytes | PathLike) -> VoicepackArchiveLanguage:
|
||||
def get_voicepack_archive_language(
|
||||
archive: str | bytes | PathLike,
|
||||
) -> VoicepackArchiveLanguage:
|
||||
"""
|
||||
Gets voicepack archive language.
|
||||
|
||||
|
@ -100,6 +124,27 @@ def get_voicepack_archive_type(archive: str | bytes | PathLike) -> VoicepackArch
|
|||
return VoicepackArchiveType.FULL
|
||||
|
||||
|
||||
def verify_game_file(
|
||||
file: str | bytes | PathLike,
|
||||
pkg_version: list[dict] | str | bytes | PathLike,
|
||||
ignore_mismatch=True,
|
||||
):
|
||||
file = Path(file)
|
||||
if not isinstance(pkg_version, list):
|
||||
pkg_version = _parse_pkg_version(pkg_version=pkg_version)
|
||||
for info in pkg_version:
|
||||
if PurePath(info["remoteName"]).name != file.name:
|
||||
continue
|
||||
file_md5 = _calculate_md5(file)
|
||||
if file_md5 == info["md5"]:
|
||||
return None
|
||||
if ignore_mismatch:
|
||||
return file, info["md5"], file_md5
|
||||
raise ValueError(
|
||||
f"MD5 does not match for {file}, expected md5: {info['md5']}, actual md5: {file_md5}"
|
||||
)
|
||||
|
||||
|
||||
class Game:
|
||||
"""
|
||||
Manages game & voicepacks installation.
|
||||
|
@ -191,18 +236,8 @@ class Game:
|
|||
async def _verify_from_pkg_version(self, pkg_version: Path, ignore_mismatch=False):
|
||||
contents = pkg_version.read_text()
|
||||
|
||||
def calculate_md5(file_to_calculate):
|
||||
file_to_calculate = Path(file_to_calculate)
|
||||
if not file_to_calculate.exists():
|
||||
return ""
|
||||
with file_to_calculate.open("rb") as f:
|
||||
file_hash = hashlib.md5()
|
||||
while chunk := f.read(8196):
|
||||
file_hash.update(chunk)
|
||||
return file_hash.hexdigest()
|
||||
|
||||
def verify_file(file_to_verify, md5):
|
||||
file_md5 = calculate_md5(file_to_verify)
|
||||
file_md5 = _calculate_md5(file_to_verify)
|
||||
if file_md5 == md5:
|
||||
return None
|
||||
if ignore_mismatch:
|
||||
|
@ -270,14 +305,18 @@ class Game:
|
|||
return voicepack_lang_translate(lang=lang, base_language=base_language)
|
||||
|
||||
@staticmethod
|
||||
def get_voicepack_archive_language(archive: str | bytes | PathLike) -> VoicepackArchiveLanguage:
|
||||
def get_voicepack_archive_language(
|
||||
archive: str | bytes | PathLike,
|
||||
) -> VoicepackArchiveLanguage:
|
||||
"""
|
||||
This function is an alias to worthless.game.get_voicepack_archive_language
|
||||
"""
|
||||
return get_voicepack_archive_language(archive=archive)
|
||||
|
||||
@staticmethod
|
||||
def get_voicepack_archive_type(archive: str | bytes | PathLike) -> VoicepackArchiveType:
|
||||
def get_voicepack_archive_type(
|
||||
archive: str | bytes | PathLike,
|
||||
) -> VoicepackArchiveType:
|
||||
"""
|
||||
This function is an alias to worthless.game.get_voicepack_archive_type
|
||||
"""
|
||||
|
@ -307,7 +346,9 @@ class Game:
|
|||
"""
|
||||
return self._game_dir.joinpath(self.get_game_data_name())
|
||||
|
||||
def get_archive_game_version(self, game_archive: str | bytes | PathLike) -> str | None:
|
||||
def get_archive_game_version(
|
||||
self, game_archive: str | bytes | PathLike
|
||||
) -> str | None:
|
||||
"""
|
||||
Gets the game version in the archive
|
||||
|
||||
|
@ -493,7 +534,10 @@ class Game:
|
|||
self._extract_game_file(archive)
|
||||
|
||||
async def install_game(
|
||||
self, game_archive: str | bytes | PathLike, force_reinstall: bool = False, callback=None
|
||||
self,
|
||||
game_archive: str | bytes | PathLike,
|
||||
force_reinstall: bool = False,
|
||||
callback=None,
|
||||
):
|
||||
"""Installs the game to the current directory
|
||||
|
||||
|
@ -547,7 +591,24 @@ class Game:
|
|||
if v.version == from_version:
|
||||
return v
|
||||
|
||||
async def verify_game(self, pkg_version: str | bytes | PathLike = None, ignore_mismatch=None):
|
||||
def verify_game_file(
|
||||
self,
|
||||
file: str | bytes | PathLike,
|
||||
pkg_version: list[dict] | str | bytes | PathLike = None,
|
||||
ignore_mismatch=True,
|
||||
):
|
||||
"""
|
||||
This function is an alias to worthless.game.get_voicepack_archive_type
|
||||
"""
|
||||
if pkg_version is None:
|
||||
pkg_version = self._game_dir.joinpath("pkg_version")
|
||||
return verify_game_file(
|
||||
file=file, pkg_version=pkg_version, ignore_mismatch=ignore_mismatch
|
||||
)
|
||||
|
||||
async def verify_game_files(
|
||||
self, pkg_version: str | bytes | PathLike = None, ignore_mismatch=True
|
||||
):
|
||||
"""
|
||||
Verifies the current game installation
|
||||
|
||||
|
@ -561,8 +622,6 @@ class Game:
|
|||
"""
|
||||
if pkg_version is None:
|
||||
pkg_version = self._game_dir.joinpath("pkg_version")
|
||||
if ignore_mismatch is None:
|
||||
ignore_mismatch = True
|
||||
return await self._verify_from_pkg_version(pkg_version, ignore_mismatch)
|
||||
|
||||
def delete_game(self):
|
||||
|
|
|
@ -85,7 +85,9 @@ class Helper(Game):
|
|||
game = await self._game._get_game(pre_download=pre_download)
|
||||
if self._game.version == game.latest.version:
|
||||
raise ValueError("Game is already up to date.")
|
||||
diff_archive = await self._game.get_game_diff_archive(from_version, pre_download)
|
||||
diff_archive = await self._game.get_game_diff_archive(
|
||||
from_version, pre_download
|
||||
)
|
||||
if diff_archive is None:
|
||||
raise ValueError(
|
||||
"Game diff archive is not available for this version, please reinstall."
|
||||
|
|
Loading…
Reference in New Issue