Skip to content

Commit 77e53a2

Browse files
committed
feat: extract files into seperate subfolder using version as name
feat: automatically extract linked versions feat: allow path based extraction using absolute filepaths
1 parent 145c234 commit 77e53a2

6 files changed

Lines changed: 178 additions & 139 deletions

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ azl extract [CLIENT]
7070

7171
Where `CLIENT` is one of EN, CN, JP, KR or TW. Extracted images will be saved in `ClientExtract/[CLIENT]/`. Since only Texture2D assets are exported, it's not desired to try to export from all assetbundles (See [settings section](#settings)).
7272

73-
A single assetbundle can be extracted by passing the filepath to the script:
73+
Using the `-f` or `--filepath` a path for extraction can be passed to the program:
7474
```bash
7575
azl extractor -f [FILEPATH]
7676
```
77+
78+
The path can be either to a single assetbundle or a directory. In the case of a directory, all subdiretories will be recursively extracted as well. The path can be either be an absolute path, or a relative path which needs to be relative to the `AssetBundles` directory of a client.

src/azl.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,10 @@ def add_subparser_download(parser):
7878

7979
def add_subparser_extract(parser):
8080
extract_parser = parser.add_parser("extract", help="Extract image assets as pngs")
81-
extract_parser.add_argument("client", type=str, choices=Client.__members__, help="client to extract files of")
81+
extract_parser.add_argument("client", nargs="?", type=str, choices=Client.__members__, help="client to extract files of")
8282
extract_parser.add_argument(
8383
"-f", "--filepath", type=str, help="Path to the file or directly to extract only single file or all directory content"
8484
)
85-
extract_parser.add_argument(
86-
"-v", "--version", type=str, help="Extract files of a specific version (Currently only applies to AZL Versiontype!)"
87-
)
88-
extract_parser.add_argument(
89-
"-u",
90-
"--until-version",
91-
type=str,
92-
help="Extract files from the latest until a specific version (Currently only applies to AZL Versiontype!)",
93-
)
9485

9586

9687
def add_subparser_import(parser):

src/azlassets/classes.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections.abc import Callable
12
from dataclasses import dataclass, field
23
from enum import Enum
34
from pathlib import Path
@@ -126,33 +127,36 @@ def from_package_name(cls, package_name: str) -> Self | None:
126127
return cls.__package_name_map__.get(package_name)
127128

128129

129-
@dataclass
130+
@dataclass(eq=True, frozen=True)
130131
class HashRow:
131132
filepath: str
132133
size: int
133134
md5hash: str
134135

135136

136-
@dataclass
137+
@dataclass(eq=True)
137138
class CompareResult:
138139
current_hash: HashRow | None
139140
new_hash: HashRow | None
140141
compare_type: CompareType
141142

142143

143-
@dataclass
144+
@dataclass(eq=True, frozen=True)
144145
class SimpleVersionResult:
145146
version: str
146147
version_type: VersionType
147148

149+
def __str__(self):
150+
return f"{self.version_type.name} {self.version}"
148151

149-
@dataclass
152+
153+
@dataclass(eq=True, frozen=True)
150154
class VersionResult(SimpleVersionResult):
151155
vhash: str
152156
rawstring: str
153157

154158

155-
@dataclass
159+
@dataclass(eq=True)
156160
class BundlePath:
157161
full: Path
158162
inner: str
@@ -170,7 +174,7 @@ def construct(parentdir: Path, inner: Path | str) -> "BundlePath":
170174
BundlePath: The constructed BundlePath object
171175
"""
172176
fullpath = Path(parentdir, inner)
173-
return BundlePath(fullpath, str(inner))
177+
return BundlePath(fullpath, str(inner).replace("\\", "/"))
174178

175179
def __hash__(self):
176180
return hash(self.inner)
@@ -221,6 +225,12 @@ def add_linked_version(self, version: SimpleVersionResult):
221225
if version.version not in self.linked_versions[version.version_type]:
222226
self.linked_versions[version.version_type].append(version.version)
223227

228+
def get_success_files(self, filter: Callable[[CompareType], bool] = (lambda *args, **kwargs: True)) -> list[BundlePath]:
229+
return [bpath for bpath, ctype in self.success_files.items() if filter(ctype)]
230+
231+
def get_failed_files(self, filter: Callable[[CompareType], bool] = (lambda *args, **kwargs: True)) -> list[BundlePath]:
232+
return [bpath for bpath, ctype in self.failed_files.items() if filter(ctype)]
233+
224234
def to_json(self) -> dict[str, Any]:
225235
"""
226236
Convert this DiffLog to a JSON-serialisable dict.
@@ -248,28 +258,28 @@ def to_json(self) -> dict[str, Any]:
248258
return data
249259

250260
@staticmethod
251-
def from_json(diffdata: dict[str, Any], vtype: VersionType, client_directory: Path):
261+
def from_json(diffdata: dict[str, Any], vtype: VersionType, client_asset_directory: Path):
252262
"""
253263
Construct a DiffLog object from JSON data.
254264
255265
Args:
256266
diffdata: Dict produced by :meth:``to_json``
257267
vtype: The VersionType that owns this log
258-
client_directory: Root client directory
268+
client_asset_directory: Root client directory
259269
260270
Returns:
261271
DiffLog: The constructed DiffLog object
262272
"""
263273
version = SimpleVersionResult(version=diffdata["version"], version_type=vtype)
264274
major = diffdata.get("major", False)
265275
linked_versions = {VersionType[vt_str]: versions for vt_str, versions in diffdata.get("linked_versions", {}).items()}
266-
assetbasepath = Path(client_directory, "AssetBundles")
276+
client_assetbundle_directory = Path(client_asset_directory, "AssetBundles")
267277
success_files = {
268-
BundlePath.construct(assetbasepath, path_str): CompareType[ctype]
278+
BundlePath.construct(client_assetbundle_directory, path_str): CompareType[ctype]
269279
for path_str, ctype in diffdata.get("success_files", {}).items()
270280
}
271281
failed_files = {
272-
BundlePath.construct(assetbasepath, path_str): CompareType[ctype]
282+
BundlePath.construct(client_assetbundle_directory, path_str): CompareType[ctype]
273283
for path_str, ctype in diffdata.get("failed_files", {}).items()
274284
}
275285

src/azlassets/downloadmgr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async def execute(args):
8686
versioncontroller.set_as_linked(vresult, azl_current)
8787

8888
if args.extract:
89-
extractor.extract_by_client(args.client)
89+
extractor.extract_latest_client(args.client)
9090

9191

9292
def execute_from_args(args):

0 commit comments

Comments
 (0)