2019-07-04 00:34:09 +02:00
|
|
|
#!/bin/bash
|
2019-07-06 16:17:03 +02:00
|
|
|
set -eou pipefail
|
2019-07-04 00:34:09 +02:00
|
|
|
|
|
|
|
FACTORIO_VERSION=$1
|
|
|
|
MOD_DIR=$2
|
|
|
|
USERNAME=$3
|
|
|
|
TOKEN=$4
|
|
|
|
|
|
|
|
MOD_BASE_URL="https://mods.factorio.com"
|
|
|
|
|
|
|
|
print_step()
|
|
|
|
{
|
|
|
|
echo "$1"
|
|
|
|
}
|
|
|
|
|
2019-07-05 09:15:18 +02:00
|
|
|
print_success()
|
2019-07-04 00:34:09 +02:00
|
|
|
{
|
|
|
|
echo "$1"
|
|
|
|
}
|
|
|
|
|
|
|
|
print_failure()
|
|
|
|
{
|
|
|
|
echo "$1"
|
|
|
|
}
|
|
|
|
|
2024-11-28 15:42:22 +02:00
|
|
|
# Checks game version vs version in mod.
|
|
|
|
# Returns 0 if major version differs or mod minor version is less than game version, 1 if ok
|
|
|
|
check_game_version() {
|
|
|
|
local game_version="$1"
|
|
|
|
local mod_version="$2"
|
|
|
|
|
|
|
|
local game_major mod_major game_minor mod_minor
|
|
|
|
game_major=$(echo "$game_version" | cut -d '.' -f1)
|
|
|
|
game_minor=$(echo "$game_version" | cut -d '.' -f2)
|
|
|
|
mod_major=$(echo "$mod_version" | cut -d '.' -f1)
|
|
|
|
mod_minor=$(echo "$mod_version" | cut -d '.' -f2)
|
|
|
|
|
|
|
|
if [[ "$game_major" -ne "$mod_major" ]]; then
|
|
|
|
echo 0
|
|
|
|
return
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ "$mod_minor" -ge "$game_minor" ]]; then
|
|
|
|
echo 1
|
|
|
|
else
|
|
|
|
echo 0
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# Checks dependency string with provided version.
|
|
|
|
# Only checks for operator based string, ignoring everything else
|
|
|
|
# Returns 1 if check is ok, 0 if not
|
|
|
|
check_dependency_version()
|
|
|
|
{
|
|
|
|
local dependency="$1"
|
|
|
|
local mod_version="$2"
|
|
|
|
|
|
|
|
if [[ "$dependency" =~ ^(\?|!|~|\(~\)) ]]; then
|
|
|
|
echo 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
local condition
|
|
|
|
condition=$(echo "$dependency" | grep -oE '(>=|<=|>|<|=) [0-9]+(\.[0-9]+)*')
|
|
|
|
|
|
|
|
if [[ -z "$condition" ]]; then
|
|
|
|
echo 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
local operator required_version
|
|
|
|
operator=$(echo "$condition" | awk '{print $1}')
|
|
|
|
required_version=$(echo "$condition" | awk '{print $2}')
|
|
|
|
|
|
|
|
case "$operator" in
|
|
|
|
">=")
|
|
|
|
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | head -n1)" == "$required_version" ]]; then
|
|
|
|
echo 1
|
|
|
|
else
|
|
|
|
echo 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
">")
|
|
|
|
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | head -n1)" == "$required_version" && "$required_version" != "$FACTORIO_VERSION" ]]; then
|
|
|
|
echo 1
|
|
|
|
else
|
|
|
|
echo 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
"<=")
|
|
|
|
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | tail -n1)" == "$required_version" ]]; then
|
|
|
|
echo 1
|
|
|
|
else
|
|
|
|
echo 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
"<")
|
|
|
|
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | tail -n1)" == "$required_version" && "$required_version" != "$FACTORIO_VERSION" ]]; then
|
|
|
|
echo 1
|
|
|
|
else
|
|
|
|
echo 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
"=")
|
|
|
|
if [[ "$mod_version" == "$required_version" ]]; then
|
|
|
|
echo 1
|
|
|
|
else
|
|
|
|
echo 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
echo 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
get_mod_info()
|
|
|
|
{
|
|
|
|
local mod_info_json="$1"
|
|
|
|
|
|
|
|
while IFS= read -r mod_release_info; do
|
|
|
|
local mod_version mod_factorio_version
|
|
|
|
mod_version=$(echo "$mod_release_info" | jq -r ".version")
|
|
|
|
mod_factorio_version=$(echo "$mod_release_info" | jq -r ".info_json.factorio_version")
|
|
|
|
|
|
|
|
if [[ $(check_game_version "$mod_factorio_version" "$FACTORIO_VERSION") == 0 ]]; then
|
|
|
|
echo " Skipping mod version $mod_version because of factorio version mismatch" >&2
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
# If we found 'dependencies' element, we also check versions there
|
|
|
|
if [[ $(echo "$mod_release_info" | jq -e '.info_json | has("dependencies") and (.dependencies | length > 0)') == true ]]; then
|
|
|
|
while IFS= read -r dependency; do
|
|
|
|
|
|
|
|
# We only check for 'base' dependency
|
|
|
|
if [[ "$dependency" == base* ]] && [[ $(check_dependency_version "$dependency" "$FACTORIO_VERSION") == 0 ]]; then
|
|
|
|
echo " Skipping mod version $mod_version, unsatisfied base dependency: $dependency" >&2
|
|
|
|
continue 2
|
|
|
|
fi
|
|
|
|
|
|
|
|
done < <(echo "$mod_release_info" | jq -r '.info_json.dependencies[]')
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "$mod_release_info" | jq -j ".file_name, \";\", .download_url, \";\", .sha1"
|
|
|
|
break
|
|
|
|
|
|
|
|
done < <(echo "$mod_info_json" | jq -c ".releases|sort_by(.released_at)|reverse|.[]")
|
|
|
|
}
|
|
|
|
|
2019-07-04 00:34:09 +02:00
|
|
|
update_mod()
|
|
|
|
{
|
2020-08-11 19:10:59 +02:00
|
|
|
MOD_NAME="$1"
|
|
|
|
MOD_NAME_ENCODED="${1// /%20}"
|
2019-07-04 00:34:09 +02:00
|
|
|
|
2024-10-22 19:28:25 +02:00
|
|
|
print_step "Checking for update of mod $MOD_NAME for factorio $FACTORIO_VERSION ..."
|
2019-07-04 00:34:09 +02:00
|
|
|
|
2024-11-28 15:42:22 +02:00
|
|
|
MOD_INFO_URL="$MOD_BASE_URL/api/mods/$MOD_NAME_ENCODED/full"
|
2019-07-04 00:34:09 +02:00
|
|
|
MOD_INFO_JSON=$(curl --silent "$MOD_INFO_URL")
|
|
|
|
|
2020-04-05 11:07:18 +02:00
|
|
|
if ! echo "$MOD_INFO_JSON" | jq -e .name >/dev/null; then
|
|
|
|
print_success " Custom mod not on $MOD_BASE_URL, skipped."
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
2024-11-28 15:42:22 +02:00
|
|
|
MOD_INFO=$(get_mod_info "$MOD_INFO_JSON")
|
|
|
|
|
|
|
|
if [[ "$MOD_INFO" == "" ]]; then
|
|
|
|
print_failure " Not compatible with version"
|
|
|
|
return 0
|
|
|
|
fi
|
2019-07-04 00:34:09 +02:00
|
|
|
|
|
|
|
MOD_FILENAME=$(echo "$MOD_INFO" | cut -f1 -d";")
|
|
|
|
MOD_URL=$(echo "$MOD_INFO" | cut -f2 -d";")
|
|
|
|
MOD_SHA1=$(echo "$MOD_INFO" | cut -f3 -d";")
|
|
|
|
|
|
|
|
if [[ $MOD_FILENAME == null ]]; then
|
|
|
|
print_failure " Not compatible with version"
|
2020-04-05 11:09:01 +02:00
|
|
|
return 0
|
2019-07-04 00:34:09 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ -f $MOD_DIR/$MOD_FILENAME ]]; then
|
|
|
|
print_success " Already up-to-date."
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
2024-10-22 19:28:25 +02:00
|
|
|
print_step " Downloading $MOD_FILENAME"
|
2019-07-04 00:34:09 +02:00
|
|
|
FULL_URL="$MOD_BASE_URL$MOD_URL?username=$USERNAME&token=$TOKEN"
|
|
|
|
HTTP_STATUS=$(curl --silent -L -w "%{http_code}" -o "$MOD_DIR/$MOD_FILENAME" "$FULL_URL")
|
|
|
|
|
|
|
|
if [[ $HTTP_STATUS != 200 ]]; then
|
|
|
|
print_failure " Download failed: Code $HTTP_STATUS."
|
2019-11-04 16:12:24 +01:00
|
|
|
rm -f "$MOD_DIR/$MOD_FILENAME"
|
2019-07-04 00:34:09 +02:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ ! -f $MOD_DIR/$MOD_FILENAME ]]; then
|
|
|
|
print_failure " Downloaded file missing!"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2019-07-06 16:41:40 +02:00
|
|
|
if ! [[ $(sha1sum "$MOD_DIR/$MOD_FILENAME") =~ $MOD_SHA1 ]]; then
|
2019-07-04 00:34:09 +02:00
|
|
|
print_failure " SHA1 mismatch!"
|
2019-11-04 16:12:24 +01:00
|
|
|
rm -f "$MOD_DIR/$MOD_FILENAME"
|
2019-07-04 00:34:09 +02:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
print_success " Download complete."
|
|
|
|
|
|
|
|
for file in "$MOD_DIR/${MOD_NAME}_"*".zip"; do # wildcard does usually not work in quotes: https://unix.stackexchange.com/a/67761
|
|
|
|
if [[ $file != $MOD_DIR/$MOD_FILENAME ]]; then
|
|
|
|
print_success " Deleting old version: $file"
|
2019-11-04 16:12:24 +01:00
|
|
|
rm -f "$file"
|
2019-07-04 00:34:09 +02:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
if [[ -f $MOD_DIR/mod-list.json ]]; then
|
|
|
|
jq -r ".mods|map(select(.enabled))|.[].name" "$MOD_DIR/mod-list.json" | while read -r mod; do
|
|
|
|
if [[ $mod != base ]]; then
|
2024-11-28 15:42:22 +02:00
|
|
|
update_mod "$mod" || true
|
2019-07-04 00:34:09 +02:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
fi
|