From 4b39f1ec48eac104413faaec022890f50d3b1387 Mon Sep 17 00:00:00 2001 From: TheCaptain989 Date: Tue, 3 Jun 2025 15:53:59 -0500 Subject: [PATCH] Release 2.16.0 --- .dockerignore | 1 + .github/workflows/BuildImage.yml | 3 +- .gitignore | 3 ++ README.md | 3 +- SECURITY.md | 4 +- root/usr/local/bin/striptracks.sh | 75 +++++++++++++++++++++++-------- 6 files changed, 66 insertions(+), 23 deletions(-) diff --git a/.dockerignore b/.dockerignore index 03a45ec..6005a5c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,3 +8,4 @@ READMETEMPLATE.md README.md SECURITY.md +bash_unit diff --git a/.github/workflows/BuildImage.yml b/.github/workflows/BuildImage.yml index ad3977e..021df32 100644 --- a/.github/workflows/BuildImage.yml +++ b/.github/workflows/BuildImage.yml @@ -6,6 +6,7 @@ on: workflow_dispatch: inputs: mod_version: + description: 'Version of the mod (optional)' type: string required: false @@ -31,7 +32,7 @@ jobs: echo "MULTI_ARCH=${{ env.MULTI_ARCH }}" >> $GITHUB_OUTPUT if [[ -z "${{ env.MOD_VERSION }}" ]]; then # **** If the mod needs to be versioned, set the versioning logic below. Otherwise leave as is. **** - MOD_VERSION="2.15.0" + MOD_VERSION="2.16.0" else MOD_VERSION=${{ env.MOD_VERSION }} echo "MOD_VERSION_OVERRIDE=true" >> $GITHUB_OUTPUT diff --git a/.gitignore b/.gitignore index 96374c4..6769090 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk + +# Miscellaneous +bash_unit diff --git a/README.md b/README.md index f242e1f..ae13512 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ All language conditions with positive scores *and* Negated conditions with negat The script also supports command-line arguments that will override the automatic language detection. More granular control can therefore be exerted or extended using tagging and defining multiple *Connect* scripts (this is native Radarr/Sonarr functionality outside the scope of this documentation). The syntax for the command-line is: -`striptracks.sh [{-a|--audio} [{-s|--subs} ] [{-f|--file} ]] [--reorder] [--disable-recycle] [{-l|--log} ] [{-c|--config} ] [{-d|--debug} []]` +`striptracks.sh [{-a|--audio} [{-s|--subs} ] [{-f|--file} ]] [--reorder] [--disable-recycle] [{-l|--log} ] [{-c|--config} ] [{-p|--priority} {idle|low|medium|high}] [{-d|--debug} []]`
Table of Command-Line Arguments @@ -224,6 +224,7 @@ Option|Argument|Description `--disable-recycle`| |Disable recycle bin use, even if configured in Radarr/Sonarr `-l`, `--log`|``|The log filename
Default is `/config/log/striptracks.txt` `-c`, `--config`|``|Radarr/Sonarr XML configuration file
Default is `/config/config.xml` +`-p`, `--priority`|`idle`, `low`, `medium`, `high`|CPU and I/O process priority for mkvmerge
Default is `medium`
![notes] High priority can consume all system resources. When processing a large video file your system may become unresponsive! `-d`, `--debug`|`[]`|Enables debug logging. Level is optional.
Default is `1` (low)
`2` includes JSON output
`3` contains even more JSON output `--help`| |Display help and exit. `--version`| |Display version and exit. diff --git a/SECURITY.md b/SECURITY.md index 685d524..c26219a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,8 +6,8 @@ Only the latest major and minor version are supported. | Version | Supported | | ------- | ------------------ | -| 2.15.x | :heavy_check_mark: | -| < 2.15 | :x: | +| 2.16.x | :heavy_check_mark: | +| < 2.16 | :x: | ## Reporting a Vulnerability diff --git a/root/usr/local/bin/striptracks.sh b/root/usr/local/bin/striptracks.sh index ee9e56e..53f4e0e 100755 --- a/root/usr/local/bin/striptracks.sh +++ b/root/usr/local/bin/striptracks.sh @@ -62,6 +62,7 @@ function initialize_variables { export striptracks_maxlogsize=512000 export striptracks_maxlog=4 export striptracks_debug=0 + export striptracks_nice="nice" # If this were defined directly in Radarr or Sonarr this would not be needed here # shellcheck disable=SC2089 export striptracks_isocodemap='{"languages":[{"language":{"name":"Any","iso639-2":["any"]}},{"language":{"name":"Afrikaans","iso639-2":["afr"]}},{"language":{"name":"Albanian","iso639-2":["sqi","alb"]}},{"language":{"name":"Arabic","iso639-2":["ara"]}},{"language":{"name":"Bengali","iso639-2":["ben"]}},{"language":{"name":"Bosnian","iso639-2":["bos"]}},{"language":{"name":"Bulgarian","iso639-2":["bul"]}},{"language":{"name":"Catalan","iso639-2":["cat"]}},{"language":{"name":"Chinese","iso639-2":["zho","chi"]}},{"language":{"name":"Croatian","iso639-2":["hrv"]}},{"language":{"name":"Czech","iso639-2":["ces","cze"]}},{"language":{"name":"Danish","iso639-2":["dan"]}},{"language":{"name":"Dutch","iso639-2":["nld","dut"]}},{"language":{"name":"English","iso639-2":["eng"]}},{"language":{"name":"Estonian","iso639-2":["est"]}},{"language":{"name":"Finnish","iso639-2":["fin"]}},{"language":{"name":"Flemish","iso639-2":["nld","dut"]}},{"language":{"name":"French","iso639-2":["fra","fre"]}},{"language":{"name":"German","iso639-2":["deu","ger"]}},{"language":{"name":"Greek","iso639-2":["ell","gre"]}},{"language":{"name":"Hebrew","iso639-2":["heb"]}},{"language":{"name":"Hindi","iso639-2":["hin"]}},{"language":{"name":"Hungarian","iso639-2":["hun"]}},{"language":{"name":"Icelandic","iso639-2":["isl","ice"]}},{"language":{"name":"Indonesian","iso639-2":["ind"]}},{"language":{"name":"Italian","iso639-2":["ita"]}},{"language":{"name":"Japanese","iso639-2":["jpn"]}},{"language":{"name":"Kannada","iso639-2":["kan"]}},{"language":{"name":"Korean","iso639-2":["kor"]}},{"language":{"name":"Latvian","iso639-2":["lav"]}},{"language":{"name":"Lithuanian","iso639-2":["lit"]}},{"language":{"name":"Macedonian","iso639-2":["mac","mkd"]}},{"language":{"name":"Malayalam","iso639-2":["mal"]}},{"language":{"name":"Marathi","iso639-2":["mar"]}},{"language":{"name":"Mongolian","iso639-2":["mon"]}},{"language":{"name":"Norwegian","iso639-2":["nno","nob","nor"]}},{"language":{"name":"Persian","iso639-2":["fas","per"]}},{"language":{"name":"Polish","iso639-2":["pol"]}},{"language":{"name":"Portuguese","iso639-2":["por"]}},{"language":{"name":"Portuguese (Brazil)","iso639-2":["por"]}},{"language":{"name":"Romansh","iso639-2":["roh"]}},{"language":{"name":"Romanian","iso639-2":["rum","ron"]}},{"language":{"name":"Russian","iso639-2":["rus"]}},{"language":{"name":"Serbian","iso639-2":["srp"]}},{"language":{"name":"Slovak","iso639-2":["slk","slo"]}},{"language":{"name":"Slovenian","iso639-2":["slv"]}},{"language":{"name":"Spanish","iso639-2":["spa"]}},{"language":{"name":"Spanish (Latino)","iso639-2":["spa"]}},{"language":{"name":"Swedish","iso639-2":["swe"]}},{"language":{"name":"Tagalog","iso639-2":["tgl"]}},{"language":{"name":"Tamil","iso639-2":["tam"]}},{"language":{"name":"Telugu","iso639-2":["tel"]}},{"language":{"name":"Thai","iso639-2":["tha"]}},{"language":{"name":"Turkish","iso639-2":["tur"]}},{"language":{"name":"Ukrainian","iso639-2":["ukr"]}},{"language":{"name":"Urdu","iso639-2":["urd"]}},{"language":{"name":"Vietnamese","iso639-2":["vie"]}},{"language":{"name":"Unknown","iso639-2":["und"]}}]}' @@ -116,7 +117,7 @@ mode. Source: https://github.com/TheCaptain989/radarr-striptracks Usage: - $0 [{-a|--audio} [{-s|--subs} ] [{-f|--file} ]] [--reorder] [--disable-recycle] [{-l|--log} ] [{-c|--config} ] [{-d|--debug} []] + $0 [{-a|--audio} [{-s|--subs} ] [{-f|--file} ]] [--reorder] [--disable-recycle] [{-l|--log} ] [{-c|--config} ] [{-p|--priority} {idle|low|medium|high}] [{-d|--debug} []] Options can also be set via the STRIPTRACKS_ARGS environment variable. Command-line arguments override the environment variable. @@ -146,6 +147,9 @@ Options and Arguments: [default: /config/log/striptracks.txt] -c, --config Radarr/Sonarr XML configuration file [default: ./config/config.xml] + -p, --priority idle|low|medium|high + CPU and I/O process priority for mkvmerge + [default: medium] -d, --debug [] Enable debug logging level is optional, between 1-3 1 is lowest, 3 is highest @@ -303,6 +307,25 @@ function process_command_line { exit 1 fi ;; + -p|--priority ) + # Set process priority + if [ -z "$2" ] || [ ${2:0:1} = "-" ]; then + echo "Error|Invalid option: $1 requires an argument." >&2 + usage + exit 20 + elif [[ ! "$2" =~ ^(idle|low|medium|high)$ ]]; then + echo "Error|Invalid option: $1 argument must be idle, low, medium, or high." >&2 + usage + exit 20 + fi + case "$2" in + idle) export striptracks_nice="ionice -c 3 nice -n 19" ;; # Idle priority + low) export striptracks_nice="ionice -c 2 -n 7 nice -n 19" ;; # Low priority + medium) export striptracks_nice="ionice -c 2 -n 4 nice -n 10" ;; # Normal priority + high) export striptracks_nice="ionice -c 2 -n 0 nice -n 0" ;; # High priority + esac + shift 2 + ;; --reorder ) # Reorder audio and subtitles tracks export striptracks_reorder="true" @@ -571,7 +594,7 @@ function delete_videofile { # # Adding a 'seriesId' to the Sonarr import causes the returned videos to have an 'Unknown' quality. Probably a bug. # striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ # -H "Content-Type: application/json" \ - # -H "Accept: application/json" \ + # -H "Accept: application/json" \ # --data-urlencode "${temp_id}" \ # --data-urlencode "folder=$striptracks_video_folder" \ # -d "filterExistingFiles=false" \ @@ -595,7 +618,7 @@ function set_metadata { local i=0 for ((i=1; i <= 5; i++)); do - call_api 1 "Updating from quality '$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)' to '$(echo $striptracks_original_metadata | jq -crM .quality.quality.name)' and release group '$(echo $striptracks_videofile_info | jq -crM '.releaseGroup | select(. != null)')' to '$(echo $striptracks_original_metadata | jq -crM '.releaseGroup | select(. != null)')'." "PUT" "$striptracks_videofile_api/bulk" "$(echo $striptracks_original_metadata | jq -crM "[{id:${striptracks_videofile_id}, quality, releaseGroup}]")" + call_api 0 "Updating from quality '$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)' to '$(echo $striptracks_original_metadata | jq -crM .quality.quality.name)' and release group '$(echo $striptracks_videofile_info | jq -crM '.releaseGroup | select(. != null)')' to '$(echo $striptracks_original_metadata | jq -crM '.releaseGroup | select(. != null)')'." "PUT" "$striptracks_videofile_api/bulk" "$(echo $striptracks_original_metadata | jq -crM "[{id:${striptracks_videofile_id}, quality, releaseGroup}]")" # Exit loop if database is not locked, else wait if wait_if_locked; then @@ -610,10 +633,12 @@ function get_mediainfo { local videofile="$1" - local mkvcommand="nice /usr/bin/mkvmerge -J \"$videofile\"" + local mkvcommand="/usr/bin/mkvmerge -J \"$videofile\"" [ $striptracks_debug -ge 1 ] && echo "Debug|Executing: $mkvcommand" | log unset striptracks_json - export striptracks_json=$(eval $mkvcommand) + # This must be a declare statement to avoid the 'Argument list too long' error with some large returned JSON + declare -g striptracks_json + striptracks_json=$(eval $mkvcommand) local return=$? [ $striptracks_debug -ge 1 ] && echo "Debug|mkvmerge returned ${#striptracks_json} bytes" | log [ $striptracks_debug -ge 2 ] && [ ${#striptracks_json} -ne 0 ] && echo "mkvmerge returned: $striptracks_json" | awk '{print "Debug|"$0}' | log @@ -651,7 +676,7 @@ function get_mediainfo { function get_rename { # Get a list of video files from Radarr/Sonarr that need to be renamed - call_api 1 "Getting list of videos that could be renamed." "GET" "rename" "${striptracks_video_type}Id=$striptracks_rescan_id" + call_api 0 "Getting list of videos that could be renamed." "GET" "rename" "${striptracks_video_type}Id=$striptracks_rescan_id" [ "$striptracks_result" != "null" ] && [ "$striptracks_result" != "" ] return } @@ -809,8 +834,8 @@ function check_log { # Log file checks # Check that log path exists - if [ ! -d "$(dirname $striptracks_log)" ]; then - [ $striptracks_debug -ge 1 ] && echo "Debug|Log file path does not exist: '$(dirname $striptracks_log)'. Using log file in current directory." + if [ ! -d "$(dirname "$striptracks_log")" ]; then + [ $striptracks_debug -ge 1 ] && echo "Debug|Log file path does not exist: '$(dirname "$striptracks_log")'. Using log file in current directory." export striptracks_log=./striptracks.txt fi @@ -981,13 +1006,19 @@ function call_api { local url="$striptracks_api_url/$endpoint" [ $striptracks_debug -ge 1 ] && echo "Debug|$message Calling ${striptracks_type^} API using $method and URL '$url'${data:+ with data $data}" | log + if [ "$method" = "GET" ]; then + method="-G" + else + method="-X $method" + fi unset striptracks_result - export striptracks_result=$(curl -s --fail-with-body \ + declare -g striptracks_result + striptracks_result=$(curl -s --fail-with-body \ -H "X-Api-Key: $striptracks_apikey" \ -H "Content-Type: application/json" \ - -H "Accept: application/json" \ + -H "Accept: application/json" \ ${data:+ -d "$data"} \ - -X $method \ + $method \ "$url") local curl_return=$?; [ $curl_return -ne 0 ] && { local message=$(echo -e "[$curl_return] curl error when calling: \"$url\"${data:+ with data $data}\nWeb server returned: $(echo $striptracks_result | jq -jcM '.message?')" | awk '{print "Error|"$0}') @@ -1483,7 +1514,8 @@ function set_title_and_exit_if_nothing_removed { echo "$message" | log local mkvcommand="/usr/bin/mkvpropedit -q --edit info --set \"title=$striptracks_title\" \"$striptracks_video\"" [ $striptracks_debug -ge 1 ] && echo "Debug|Executing: $mkvcommand" | log - local result=$(eval $mkvcommand) + local result + result=$(eval $mkvcommand) local return=$? [ $striptracks_debug -ge 1 ] && echo "Debug|mkvpropedit returned ${#result} bytes" | log [ $striptracks_debug -ge 2 ] && [ ${#result} -ne 0 ] && echo "mkvpropedit returned: $result" | awk '{print "Debug|"$0}' | log @@ -1534,9 +1566,10 @@ function remux_video { fi # Execute MKVmerge (remux then rename, see issue #46) - local mkvcommand="nice /usr/bin/mkvmerge --title \"$striptracks_title\" -q -o \"$striptracks_tempvideo\" $audioarg $subsarg $striptracks_neworder \"$striptracks_video\"" + local mkvcommand="$striptracks_nice /usr/bin/mkvmerge --title \"$striptracks_title\" -q -o \"$striptracks_tempvideo\" $audioarg $subsarg $striptracks_neworder \"$striptracks_video\"" [ $striptracks_debug -ge 1 ] && echo "Debug|Executing: $mkvcommand" | log - local result=$(eval $mkvcommand) + local result + result=$(eval $mkvcommand) local return=$? [ $striptracks_debug -ge 1 ] && echo "Debug|mkvmerge returned ${#result} bytes" | log [ $striptracks_debug -ge 2 ] && [ ${#result} -ne 0 ] && echo "mkvmerge returned: $result" | awk '{print "Debug|"$0}' | log @@ -1566,7 +1599,8 @@ function set_perms_and_owner { if [ "$(id -u)" -eq 0 ]; then # Set owner [ $striptracks_debug -ge 1 ] && echo "Debug|Changing owner of file \"$striptracks_tempvideo\"" | log - local result=$(chown --reference="$striptracks_video" "$striptracks_tempvideo") + local result + result=$(chown --reference="$striptracks_video" "$striptracks_tempvideo") local return=$?; [ $return -ne 0 ] && { local message=$(echo -e "[$return] Error when changing owner of file: \"$striptracks_tempvideo\"\nchown returned: $result" | awk '{print "Error|"$0}') echo "$message" | log @@ -1578,7 +1612,8 @@ function set_perms_and_owner { [ $striptracks_debug -ge 1 ] && echo "Debug|Unable to change owner of file when running as user '$(id -un)'" | log fi # Set permissions - local result=$(chmod --reference="$striptracks_video" "$striptracks_tempvideo") + local result + result=$(chmod --reference="$striptracks_video" "$striptracks_tempvideo") local return=$?; [ $return -ne 0 ] && { local message=$(echo -e "[$return] Error when changing permissions of file: \"$striptracks_tempvideo\"\nchmod returned: $result" | awk '{print "Error|"$0}') echo "$message" | log @@ -1592,7 +1627,8 @@ function replace_original_video { # Just delete the original video if running in batch mode or if configured to do so (see issue #99) if [ "$striptracks_type" = "batch" -o "$striptracks_recycle" = "false" ]; then [ $striptracks_debug -ge 1 ] && echo "Debug|Deleting: \"$striptracks_video\"" | log - local result=$(rm "$striptracks_video") + local result + result=$(rm "$striptracks_video") local return=$?; [ $return -ne 0 ] && { local message=$(echo -e "[$return] Error when deleting video: \"$striptracks_video\"\nrm returned: $result" | awk '{print "Error|"$0}') echo "$message" | log @@ -1620,7 +1656,8 @@ function replace_original_video { # Rename the temporary video file to MKV [ $striptracks_debug -ge 1 ] && echo "Debug|Renaming \"$striptracks_tempvideo\" to \"$striptracks_newvideo\"" | log - local result=$(mv -f "$striptracks_tempvideo" "$striptracks_newvideo") + local result + result=$(mv -f "$striptracks_tempvideo" "$striptracks_newvideo") local return=$?; [ $return -ne 0 ] && { local message=$(echo -e "[$return] Unable to rename temp video: \"$striptracks_tempvideo\" to: \"$striptracks_newvideo\". Halting.\nmv returned: $result" | awk '{print "Error|"$0}') echo "$message" | log @@ -1810,7 +1847,7 @@ function rescan_and_cleanup { } # Check if new video is in list of files that can be renamed if [ -n "$striptracks_result" -a "$striptracks_result" != "[]" ]; then - local renamedvideo="$(echo $striptracks_result | jq -crM ".[] | select(.${striptracks_json_quality_root}Id == $striptracks_videofile_id) | .newPath")" + local renamedvideo="$(echo "$striptracks_result" | jq -crM ".[] | select(.${striptracks_json_quality_root}Id == $striptracks_videofile_id) | .newPath")" # Rename video if needed if [ -n "$renamedvideo" ]; then rename_videofile "$striptracks_videofile_id" "$renamedvideo"