#!/usr/bin/env nix-shell
#!nix-shell -i python3.10 -p python310Packages.requests
import json
import subprocess
import requests
from pathlib import Path
def versiontuple(v):
return tuple(map(int, (v.partition("+")[0].split("."))))
ENDPOINT = "https://raw.githubusercontent.com/PrismLauncher/meta-upstream/master/forge"
def get_versions():
print("Fetching all versions")
data = requests.get(f"{ENDPOINT}/promotions_slim.json").json()
versions = []
for key, loader_version in data["promos"].items():
mc = key.split("-")[0]
versions.append((mc, loader_version))
return versions
def fetch_version(game_version, loader_version):
"""
Return the server json for a given game and loader version
"""
print(f"Fetch {ENDPOINT}/version_manifests/{game_version}-{loader_version}.json")
return requests.get(
f"{ENDPOINT}/version_manifests/{game_version}-{loader_version}.json"
).json()
def gen_locks(version, libraries):
"""
Return the lock information for a given server json, returned in the format
{
"mainClass": string,
"libraries": [
{"name": string, "url": string, "sha256": string},
...
]
}
"""
print(version)
ret = {"mainClass": version["mainClass"], "libraries": []}
for library in version["libraries"]:
name, url = library["name"], library["downloads"]["artifact"]["url"]
if not name in libraries or any(not v for k, v in libraries[name].items()):
print(f"- - - Fetching library {name}")
ldir, lname, lversion = name.split(":")
lfilename = f"{lname}-{lversion}.zip"
# lurl = f"{url}{ldir.replace('.', '/')}/{lname}/{lversion}/{lname}-{lversion}.jar"
if url == "":
url = f"https://maven.minecraftforge.net/{ldir.replace('.','/')}/{lname}/{lversion}/{lname}-{lversion}.jar"
lhash = subprocess.run(
["nix-prefetch-url", url], capture_output=True, encoding="UTF-8"
).stdout.rstrip("\n")
libraries[name] = {"name": lfilename, "url": url, "sha256": lhash}
else:
pass
# print(f"- - - Using cached library {name}")
ret["libraries"].append(name)
return ret
def main(versions, libraries, locks, lib_locks):
"""
Fetch the relevant information and update the lockfiles.
`versions` and `libraries` are data from the existing files, while
`locks` and `lib_locks` are file objects to be written to
"""
all_versions = get_versions()
print("Starting fetch")
try:
for (game_version, loader_version) in all_versions:
print(f"- Loader: {loader_version}")
print(f"- - Game: {game_version}")
if not versions.get(loader_version, None):
versions[loader_version] = {}
if not versions[loader_version].get(game_version, None):
data = {}
try:
data = fetch_version(game_version, loader_version)
except json.JSONDecodeError:
versions.pop(loader_version, None)
continue
versions[loader_version][game_version] = gen_locks(data, libraries)
else:
print(f"- - Game: {game_version}: Already locked")
except KeyboardInterrupt:
print("Cancelled fetching, writing and exiting")
json.dump(versions, locks, indent=2)
json.dump(libraries, lib_locks, indent=2)
locks.write("\n")
lib_locks.write("\n")
if __name__ == "__main__":
folder = Path(__file__).parent
lo = folder / "locks.json"
li = folder / "libraries.json"
lo.touch()
li.touch()
with (
open(lo, "r") as locks,
open(li, "r") as lib_locks,
):
versions = {} if lo.stat().st_size == 0 else json.load(locks)
libraries = {} if li.stat().st_size == 0 else json.load(lib_locks)
with (
open(lo, "w") as locks,
open(li, "w") as lib_locks,
):
main(versions, libraries, locks, lib_locks)