feat: add modrinth mod

This commit is contained in:
Kentai Radiquum 2025-05-06 03:14:16 +05:00
parent 237ce9879d
commit e453f336a8
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
8 changed files with 398 additions and 21 deletions

View file

@ -7,12 +7,13 @@ from PIL import Image
from io import BytesIO
import base64
import json
from .source import Modrinth
@apiPack.route("/<id>", methods=["GET"])
def getPack(id):
if not os.path.exists(f"{PACKS_FOLDER}/{id}/packfile.json"):
return jsonify({"status": "error", "message": "not found"}), 404
return jsonify({"status": "error", "message": "pack not found"}), 404
pack = {}
with open(f"{PACKS_FOLDER}/{id}/packfile.json") as fp:
@ -59,3 +60,49 @@ def editPackImage(id):
"message": "image updated",
}
)
@apiPack.route("/<id>/mod/add", methods=["POST"])
def addMod(id):
source = request.json.get("source", None)
slug = request.json.get("slug", None)
version = request.json.get("version", None)
pack = {}
mod = {}
if not os.path.exists(f"{PACKS_FOLDER}/{id}/packfile.json"):
return jsonify({"status": "error", "message": "pack not found"})
with open(f"{PACKS_FOLDER}/{id}/packfile.json") as fp:
pack = json.load(fp)
fp.close()
mod_loader = pack.get("modloader").lower()
game_version = pack.get("version")
if not source:
return jsonify({"status": "error", "message": "mod source is required"})
if not slug:
return jsonify({"status": "error", "message": "mod slug is required"})
for mod in pack["mods"]:
if mod.get("slug") == slug:
return jsonify({"status": "error", "message": "mod already exists"})
if source == "Modrinth":
mod = Modrinth.getModrinthMod(slug, version, mod_loader, game_version)
if mod.get("status") != "ok":
return jsonify({"status": "error", "message": mod.get("message")})
pack["modpackVersion"] += 1
pack["mods"].append(mod.get("mod"))
with open(f"{PACKS_FOLDER}/{id}/packfile.json", mode="w", encoding="utf-8") as fp:
json.dump(pack, fp)
fp.close()
return jsonify(
{
"status": "ok",
"message": f"mod {mod.get("mod").get('title')} ({slug}) has been added",
"mod": mod.get("mod"),
}
)

View file

@ -0,0 +1,98 @@
import requests
from config import MODRINTH_UA
def getModrinthMod(slug, version, mod_loader, game_version):
headers = {"User-Agent": MODRINTH_UA}
descR = requests.get(f"https://api.modrinth.com/v2/project/{slug}", headers=headers)
if descR.status_code != 200:
return {
"status": "error",
"message": f"failed to fetch modrinth description: {descR.status_code}",
}
versR = requests.get(
f'https://api.modrinth.com/v2/project/{slug}/version?loaders=["{mod_loader}"]&game_versions=["{game_version}"]',
headers=headers,
)
if versR.status_code != 200:
return {
"status": "error",
"message": f"failed to fetch modrinth mod versions: {versR.status_code}",
}
devsR = requests.get(
f"https://api.modrinth.com/v2/project/{slug}/members",
headers=headers,
)
if devsR.status_code != 200:
return {
"status": "error",
"message": f"failed to fetch modrinth mod developers: {devsR.status_code}",
}
desc: dict = descR.json()
vers: dict = versR.json()
devs: dict = devsR.json()
if len(vers) == 0:
return {
"status": "error",
"message": f"mod is not compatible with this game version or mod loader",
}
selected_version = vers[0]
if version:
for _sf in vers:
if _sf.get("version_number") == version:
selected_version = _sf
break
primary_file = None
for _pf in selected_version.get("files"):
if _pf.get("primary") == True:
primary_file = _pf
break
if primary_file is None:
return {
"status": "error",
"message": f"failed to get primary mod file",
}
developers = []
for dev in devs:
developers.append(dev["user"]["username"])
isClient = False
if desc.get("client_side") in ["optional", "required"]:
isClient = True
isServer = False
if desc.get("server_side") in ["optional", "required"]:
isServer = True
return {
"status": "ok",
"mod": {
"slug": slug,
"icon": desc.get("icon_url"),
"title": desc.get("title"),
"developers": developers,
"source": "Modrinth",
"url": f"https://modrinth.com/mod/{slug}",
"environment": {
"client": isClient,
"server": isServer,
},
"file": {
"version": selected_version.get("version_number"),
"hashes": primary_file.get("hashes"),
"url": primary_file.get("url"),
"filename": primary_file.get("filename"),
"size": primary_file.get("size"),
},
},
}

View file

View file

@ -5,3 +5,11 @@ if os.getenv("is_dev") == "True":
PACKS_FOLDER = "../packs"
IMG_ALLOWED_MIME = {"image/png", "image/jpg", "image/jpeg", "image/webp", "image/jfif"}
MODRINTH_UA = None
if os.getenv("MODRINTH_UA"):
MODRINTH_UA = os.getenv("MODRINTH_UA")
CURSEFORGE_API_KEY = None
if os.getenv("CURSEFORGE_API_KEY"):
CURSEFORGE_API_KEY = os.getenv("CURSEFORGE_API_KEY")