-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdump_manifest.py
executable file
·149 lines (126 loc) · 4.85 KB
/
dump_manifest.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
#!/usr/bin/env python
import os
import shutil
import subprocess
import sys
import json
import glob
import urllib.request
import time
INIT_SCRIPT = """#!/bin/sh
#export WINEDEBUG=-all
export RUST_BACKTRACE=1
export WINEDLLOVERRIDES=rsaenh.dll=n
export WINEPREFIX="/tmp/prefix"
timeout 300 wine64 wineboot
rm -rf /share/lol/meta/
mkdir -p /share/lol/meta/
cp /share/lol/rsaenh.dll $WINEPREFIX/drive_c/windows/system32/
cp -r /share/lol $WINEPREFIX/drive_c/
cd $WINEPREFIX/drive_c/lol
timeout 300 wine64 League\ of\ Legends.exe foo.rofl
echo $? > /share/lol/exitcode
cp $WINEPREFIX/drive_c/lol/meta/* /share/lol/meta/
exit 0
"""
JSON_URL = "https://sieve.services.riotcdn.net/api/v1/products/lol/version-sets/{region}?q[platform]=windows&q[artifact_type_id]=lol-game-client&q[published]=true"
USER_AGENT = 'Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/88.0'
DELAY = 5
# Ensure destination filename has folder path
def ensure_folder(dst_filepath):
dst_dir = os.path.dirname(dst_filepath)
os.makedirs(dst_dir, exist_ok=True)
# Runs a process
def run(name, *args):
print(f"Running {name}")
process = subprocess.call([ name, *args], bufsize=1, stdout=sys.stdout, stderr=sys.stderr)
return not process
# Copy file
def copy_file(src_filepath, dst_filepath):
print(f"Copying file {src_filepath} to {dst_filepath}")
ensure_folder(dst_filepath)
shutil.copyfile(src_filepath, dst_filepath)
# Prune folder
def prune_folder(dirname):
if os.path.exists(dirname):
shutil.rmtree(dirname)
# Generate executable script
def generate_script_file(dst_filepath, contents):
print(f"Generating {dst_filepath}")
ensure_folder(dst_filepath)
with open(dst_filepath, "w") as dst_file:
dst_file.write(INIT_SCRIPT)
os.chmod(dst_filepath, 0o755)
def read_txt_file_or_empty(src_filepath):
if not os.path.exists(src_filepath):
return ""
with open(src_filepath, 'r') as inf:
return inf.read().rstrip()
def write_txt_file(dst_filepath, contents):
ensure_folder(dst_filepath)
with open(dst_filepath, "w") as dst_file:
dst_file.write(contents)
# Download league files
def download_files(downloader, manifest, dst_dir, namefilter):
print(f"Downloading {manifest} to {dst_dir}")
os.makedirs(dst_dir, exist_ok=True)
extension = '.exe' if os.name == 'nt' else ''
assert(run(f'{downloader}{extension}', manifest, '-o', dst_dir, '-f', namefilter))
# Runs qemu
def run_qemu(bindir, workdir):
print("Starting qemu")
accel = []
if os.path.exists("/dev/kvm"):
print("Using KVM (might need sudo or user group)!")
accel.append("-enable-kvm")
else:
print("No acceleration aveilable this might take a while!")
assert(run("qemu-system-x86_64", *[
*accel,
"-cpu", "qemu64,-hypervisor",
"-m", "4G",
"-kernel", f"{workdir}/vmlinuz",
"-initrd", f"{workdir}/initrd",
"-append", "console=ttyS0 quiet",
"-nographic",
"-nodefaults",
"-no-user-config",
"-serial", "mon:stdio",
"-virtfs", f"local,path={workdir}/share,mount_tag=host0,security_model=mapped-xattr,id=host0",
]))
# Dump meta
def dump_meta(bindir, manifest, workdir, dst_dir):
download_files(f'{bindir}/ManifestDownloader', manifest, f'{workdir}/share/lol', '\.dll|\.exe|Bootstrap\.windows')
copy_file(f'{bindir}/rsaenh.dll', f'{workdir}/share/lol/rsaenh.dll')
generate_script_file(f"{workdir}/share/init.sh", INIT_SCRIPT)
prune_folder("f'{workdir}/share/lol/meta")
run_qemu(bindir, workdir)
exitcode = int(open(f"{workdir}/share/lol/exitcode").read())
assert(exitcode == 0)
def fetch_latest_version(region):
url = JSON_URL.format(region = region)
print(f"Fetching releases from: {url}")
request = urllib.request.Request(url, headers={'User-Agent':USER_AGENT})
response = urllib.request.urlopen(request, timeout=15)
data = response.read().decode('utf-8')
newversions = []
for release in json.loads(data)["releases"]:
version, name = release["compat_version"]["id"].split('+')
manifest = release["download"]["url"]
print(f'Version manifest: {version} manifest')
newversions.append((version, manifest))
assert(len(newversions) == 1)
return newversions[0]
# Dump new version
def dump_meta_latest(bindir, region, workdir, dst_dir):
version, manifest = fetch_latest_version(region)
last_dumped_version = read_txt_file_or_empty(f'{dst_dir}/version.txt')
print(f'Last dumped version is: {last_dumped_version}')
if version == last_dumped_version:
print(f'Up to date!')
return
dump_meta('bin', manifest, 'tmp', 'meta')
meta_json, = list(glob.iglob(f'{workdir}/share/lol/meta/meta_*.json'))
copy_file(meta_json, f'{dst_dir}/meta.json')
write_txt_file(f'{dst_dir}/version.txt', version)
dump_meta_latest('bin', "EUW1", 'tmp', 'meta')