diff --git a/src/api/pack.py b/src/api/pack.py index c6a684d..54ecab2 100644 --- a/src/api/pack.py +++ b/src/api/pack.py @@ -7,7 +7,7 @@ from PIL import Image from io import BytesIO import base64 import json -from .source import Modrinth +from .source import Modrinth, CurseForge @apiPack.route("/", methods=["GET"]) @@ -89,6 +89,8 @@ def addMod(id): if source == "Modrinth": mod = Modrinth.getModrinthMod(slug, version, mod_loader, game_version) + elif source == "CurseForge": + mod = CurseForge.getCurseForgeMod(slug, version, mod_loader, game_version) if mod.get("status") != "ok": return jsonify({"status": "error", "message": mod.get("message")}) diff --git a/src/api/source/CurseForge.py b/src/api/source/CurseForge.py new file mode 100644 index 0000000..4442370 --- /dev/null +++ b/src/api/source/CurseForge.py @@ -0,0 +1,88 @@ +MODLOADER_ENUM = {"forge": 1, "fabric": 4, "quilt": 5, "neoforge": 6} +HASHALGO_ENUM = {1: "sha1", 2: "md5"} + +import requests +from config import CURSEFORGE_API_KEY + + +def getCurseForgeMod(slug, version, mod_loader, game_version): + headers = {"x-api-key": CURSEFORGE_API_KEY} + + metaR = requests.get( + f"https://api.curseforge.com/v1/mods/search?gameid=432&slug={slug}", + headers=headers, + ) + if metaR.status_code != 200: + return { + "status": "error", + "message": f"failed to fetch curseforge mod: {metaR.status_code}", + } + + meta: dict = metaR.json() + if len(meta.get("data")) == 0: + return { + "status": "error", + "message": f"mod not found", + } + meta = meta.get("data")[0] + + selected_version = None + if version: + versR = requests.get( + f'https://api.curseforge.com/v1/mods/{meta.get("id")}/files/{version}', + headers=headers, + ) + else: + versR = requests.get( + f'https://api.curseforge.com/v1/mods/{meta.get("id")}/files?gameVersion={game_version}&modLoaderType={MODLOADER_ENUM[mod_loader]}&pageSize=1', + headers=headers, + ) + + if versR.status_code != 200: + return { + "status": "error", + "message": f"failed to fetch curseforge mod versions: {versR.status_code}", + } + + vers: dict = versR.json() + if len(vers.get("data")) == 0: + return { + "status": "error", + "message": f"mod is not compatible with this game version or mod loader", + } + + if version: + selected_version = vers.get("data") + else: + selected_version = vers.get("data")[0] + + developers = [] + for dev in meta["authors"]: + developers.append(dev["name"]) + + hashes = {} + for hash in selected_version.get("hashes"): + hashes[HASHALGO_ENUM[hash.get("algo")]] = hash.get("value") + + return { + "status": "ok", + "mod": { + "slug": slug, + "icon": meta.get("logo").get("url"), + "title": meta.get("name"), + "developers": developers, + "source": "CurseForge", + "url": f"https://www.curseforge.com/minecraft/mc-mods/{slug}", + "environment": { + "client": True, + "server": True, + }, + "file": { + "version": selected_version.get("id"), + "hashes": hashes, + "url": selected_version.get("downloadUrl"), + "filename": selected_version.get("fileName"), + "size": selected_version.get("fileSizeOnDisk"), + }, + }, + }