-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.py
164 lines (145 loc) · 5.37 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import argparse
import json
from pathlib import Path
from rich import print
from utils import compress, compress_raw, decompress, decompress_raw, encode, decode
def get_args():
parser = argparse.ArgumentParser(description="Balatro save manager")
subparsers = parser.add_subparsers(help="Subcommands", dest="command")
view_subparser = subparsers.add_parser(
"view", help="View a save file", aliases=["v"]
)
view_subparser.add_argument("file", type=str, help="The file to view")
view_subparser.add_argument(
"--format",
"-f",
type=str,
help="The format to output (json or lua)",
choices=["json", "lua"],
default="json",
)
merge_subparser = subparsers.add_parser(
"merge", help="Merge two save files", aliases=["m"]
)
merge_subparser.add_argument("left", type=str, help="The first file to merge")
merge_subparser.add_argument("right", type=str, help="The second file to merge")
merge_subparser.add_argument(
"--output",
"-o",
type=str,
help="The file to save the merged data to",
default="merged.jkr",
)
merge_subparser.add_argument(
"--prefer",
"-p",
type=str,
help="The file to prefer when merging. Left or right means not to overwrite the data with the other file. Latest means to prefer the data from the file with the most progress.",
choices=["left", "right", "latest"],
default="latest",
)
export_subparser = subparsers.add_parser(
"export", help="Export a save file to JSON", aliases=["e"]
)
export_subparser.add_argument("file", type=str, help="The .jkr file to export")
export_subparser.add_argument(
"--output",
"-o",
type=str,
help="The file to save the exported data to",
default="exported.json",
)
import_subparser = subparsers.add_parser(
"import", help="Import a save file from JSON", aliases=["i"]
)
import_subparser.add_argument("file", type=str, help="The .json file to import")
import_subparser.add_argument(
"--output",
"-o",
type=str,
help="The file to save the imported data to",
default="imported.jkr",
)
return parser.parse_args()
def parse(file: Path) -> dict:
"""Try to parse the file and return the result."""
if not file.suffix == ".jkr":
raise ValueError(f"{file} is not a valid file")
if file.parts[-1] == "version.jkr":
raise ValueError("version.jkr is not a save file")
return decompress(file)
def save(file: Path, data: dict) -> None:
"""Try to save the data to the file."""
compress(data, file)
def merge(left: dict, right: dict, prefer: str) -> dict:
"""Merge the two dictionaries and return the result."""
result = {}
all_keys = set(left.keys()) | set(right.keys())
for key in all_keys:
if key not in left:
result[key] = right[key]
elif key not in right:
result[key] = left[key]
else:
lv, rv = left[key], right[key]
if isinstance(lv, dict) and isinstance(rv, dict):
result[key] = merge(lv, rv, prefer)
else:
if prefer == "left":
result[key] = left[key]
elif prefer == "right":
result[key] = right[key]
elif prefer == "latest":
if left[key] > right[key]:
result[key] = left[key]
else:
result[key] = right[key]
return result
def export(file: Path, output: Path) -> None:
"""Export the save file to a JSON/lua file."""
output_file = Path(output)
if output_file.suffix == ".json":
data = encode(parse(file))
output_file.write_text(
json.dumps(data, indent=4).replace(r"\"", r"\\\""), encoding="UTF-8"
)
elif output_file.suffix == ".lua":
data = decompress_raw(file)
output_file.write_text(data, encoding="UTF-8")
else:
raise ValueError(
f"{output_file.parts[-1]} is not a valid file (should be .json or.lua)"
)
def import_(file: Path, output: Path) -> None:
"""Import the save file from a JSON/lua file."""
data = file.read_text(encoding="UTF-8")
if file.suffix == ".json":
save(output, decode(json.loads(data)))
elif file.suffix == ".lua":
compress_raw(data, output)
else:
raise ValueError(
f"{output.parts[-1]} is not a valid file (should be .json or.lua)"
)
def main():
args = get_args()
if args.command in {"view", "v"}:
file = Path(args.file)
if args.format == "json":
print(parse(file))
elif args.format == "lua":
print(decompress_raw(file))
elif args.command in {"merge", "m"}:
left = parse(Path(args.left))
right = parse(Path(args.right))
result = merge(left, right, args.prefer)
save(Path(args.output), result)
print(f"Merged data saved to {args.output}")
elif args.command in {"export", "e"}:
export(Path(args.file), Path(args.output))
print(f"Exported data saved to {args.output}")
elif args.command in {"import", "i"}:
import_(Path(args.file), Path(args.output))
print(f"Imported data saved to {args.output}")
if __name__ == "__main__":
main()