mods.sh (3575B)
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 | #! /usr/bin/env nix #! nix shell nixpkgs#bash nixpkgs#cacert nixpkgs#coreutils nixpkgs#curl nixpkgs#jq nixpkgs#nix -c bash set -euo pipefail # Script to automatically update Minecraft Server Mods from Modrinth # API="https://api.modrinth.com/v2" COMMIT_PREFIX="chore(mc-server): Update" # Locate mod metadata file SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DATA="${MODS_FILE:-${SCRIPT_DIR}/../modules/games/mc-server/_mods.nix}" if [[ ! -f "${DATA}" ]] then echo "Mod metadata file not found: '${DATA}'" exit 1 fi export CURL_CA_BUNDLE="${CURL_CA_BUNDLE:-$(nix eval --raw nixpkgs#cacert)/etc/ssl/certs/ca-bundle.crt}" # Tracking declare -a UNAVAILABLE=() updated=0 uptodate=0 # Fetch latest version metadata for a project, target loader and game version latest() { local id="${1}" loader="${2}" version="${3}" curl -s -G "${API}/project/${id}/version" \ --data-urlencode "loaders=[\"${loader}\"]" \ --data-urlencode "game_versions=[\"${version}\"]" \ | jq -r ' (sort_by(.date_published) | reverse | .[0]) as $v | if $v == null then empty else (($v.files | map(select(.primary)) + .)[0]) as $f | if $f == null then empty else "\($f.url)\t\($f.hashes.sha512)" end end ' 2>/dev/null || true } # Update every mod of a loader process_loader() { local loader="${1}" json version count json="$(nix eval --json -f "${DATA}" "${loader}" 2>/dev/null || true)" if [[ -z "${json}" || "${json}" == "null" ]] then return 0 fi version="$(echo "${json}" | jq -r '.version')" count="$(echo "${json}" | jq -r '.mods | length')" echo "==> Loader '${loader}' (Minecraft ${version}): ${count} mods" local i name id oldurl oldhash result newurl sha512 newhash for ((i = 0; i < count; i++)) do name="$(echo "${json}" | jq -r ".mods[${i}].name")" id="$(echo "${json}" | jq -r ".mods[${i}].id")" oldurl="$(echo "${json}" | jq -r ".mods[${i}].url")" oldhash="$(echo "${json}" | jq -r ".mods[${i}].hash")" result="$(latest "${id}" "${loader}" "${version}")" newurl="$(echo "${result}" | cut -f1)" sha512="$(echo "${result}" | cut -f2)" if [[ -z "${result}" || "${newurl}" == "null" || -z "${newurl}" || "${sha512}" == "null" ]] then echo " ✗ ${name}: no build for Minecraft ${version}" UNAVAILABLE+=("${name} (${loader} ${version})") continue fi if [[ "${newurl}" == "${oldurl}" ]] then echo " = ${name}: up to date" ((uptodate += 1)) || true continue fi newhash="$(nix hash convert --hash-algo sha512 --to sri "${sha512}")" sed -i "s|${oldurl}|${newurl}|" "${DATA}" sed -i "s|${oldhash}|${newhash}|" "${DATA}" echo " ↑ ${name}: updated" ((updated += 1)) || true done # Commit per loader if [[ "${COMMIT:-true}" == "true" ]] then git -C "$(dirname "${DATA}")" diff-index --quiet HEAD "${DATA}" 2>/dev/null || \ git -C "$(dirname "${DATA}")" commit -q -n "${DATA}" \ -m "${COMMIT_PREFIX} \`${loader}\` mods" || true fi } # Execution echo "Checking for Mod Updates..." # Iterate over every defined loader mapfile -t LOADERS < <(nix eval --json -f "${DATA}" 2>/dev/null | jq -r 'keys[]') for loader in "${LOADERS[@]}" do process_loader "${loader}" done # Summary echo echo "Summary: ${updated} updated, ${uptodate} up to date, ${#UNAVAILABLE[@]} unavailable" if (( ${#UNAVAILABLE[@]} > 0 )) then echo "Could not update to the target Minecraft version:" for m in "${UNAVAILABLE[@]}" do echo " - ${m}" done fi |