99 lines
3.3 KiB
Python
99 lines
3.3 KiB
Python
import argparse
|
|
import sys
|
|
import logging
|
|
import requests
|
|
import json
|
|
import tomllib
|
|
from typing import List, Tuple, Dict, Union
|
|
from pathlib import Path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def main() -> int:
|
|
# Handle program arguments
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--dot", help="Output a graphviz dot file here", type=Path)
|
|
ap.add_argument(
|
|
"-v", "--verbose", help="Enable verbose logging", action="store_true"
|
|
)
|
|
args = ap.parse_args()
|
|
|
|
# Configure logging
|
|
logging.basicConfig(
|
|
level=logging.DEBUG if args.verbose else logging.INFO,
|
|
format="%(levelname)s: %(message)s",
|
|
)
|
|
|
|
# Get a list of all toml files in the mods dir
|
|
mods_tomls = list((Path(__file__).parent.parent / "mods").glob("*.toml"))
|
|
|
|
# Look for update.modrinth.mod-id and update.modrinth.version
|
|
mods = []
|
|
for mod_toml in mods_tomls:
|
|
with open(mod_toml, "rb") as f:
|
|
mod = tomllib.load(f)
|
|
if "update" in mod and "modrinth" in mod["update"]:
|
|
mods.append(
|
|
{
|
|
"name": mod["name"],
|
|
"mod_id": mod["update"]["modrinth"]["mod-id"],
|
|
"version_id": mod["update"]["modrinth"]["version"],
|
|
"dependencies": [],
|
|
}
|
|
)
|
|
|
|
# Build a map of dependencies
|
|
# mod_dependencies: Dict[str, List[str]] = {}
|
|
for mod in mods:
|
|
# Read the version metadata
|
|
version_metadata = requests.get(
|
|
f"https://api.modrinth.com/v2/version/{mod['version_id']}"
|
|
).json()
|
|
|
|
# Track the dependencies
|
|
for dependency in version_metadata.get("dependencies", {}):
|
|
if "project_id" in dependency:
|
|
mod["dependencies"].append(
|
|
{"name": None, "mod_id": dependency["project_id"]}
|
|
)
|
|
|
|
# In-fill all the dependency names (that we know about)
|
|
for mod in mods:
|
|
for dependency in mod["dependencies"]:
|
|
for mod_data in mods:
|
|
if mod_data["mod_id"] == dependency["mod_id"]:
|
|
dependency["name"] = mod_data["name"]
|
|
break
|
|
|
|
# De-dupe dependencies
|
|
for mod in mods:
|
|
mod["dependencies"] = list({v['name']:v for v in mod["dependencies"]}.values())
|
|
|
|
# If graphviz output requested, write it
|
|
if args.dot:
|
|
with open(args.dot, "w") as f:
|
|
f.write("digraph {\n")
|
|
for mod in mods:
|
|
f.write(f'"{mod["name"]}" [label="{mod["name"]}"];\n')
|
|
for dependency in mod["dependencies"]:
|
|
f.write(f'"{mod["name"]}" -> "{dependency["name"]}";\n')
|
|
f.write("}\n")
|
|
|
|
# Build a map of all mods, and which other mods depend upon them
|
|
mod_to_dependers: Dict[str, List[str]] = {name:[] for name in [mod["name"] for mod in mods]}
|
|
for mod in mods:
|
|
for dependency in mod["dependencies"]:
|
|
if dependency["name"] not in mod_to_dependers:
|
|
mod_to_dependers[dependency["name"]] = []
|
|
mod_to_dependers[dependency["name"]].append(mod["name"])
|
|
|
|
print(json.dumps(mod_to_dependers, indent=4))
|
|
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|