diff --git a/Dockerfile b/Dockerfile index 6b488a8..6e1b01c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,14 @@ # syntax=docker/dockerfile:1 +## Buildstage ## FROM ghcr.io/linuxserver/baseimage-alpine:3.17 as buildstage ARG MOD_VERSION +# copy local files COPY root/ /root-layer/ +# Add version to script RUN \ MOD_VERSION="${MOD_VERSION:-unknown}" && \ sed -i -e "s/{{VERSION}}/$MOD_VERSION/" \ @@ -17,5 +20,5 @@ FROM scratch LABEL maintainer="TheCaptain989" -# Copy local files +# Add files from buildstage COPY --from=buildstage /root-layer/ / diff --git a/README.md b/README.md index b84c3b9..10f138a 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Container info: Production Container info: ![Docker Image Size](https://img.shields.io/docker/image-size/linuxserver/mods/radarr-striptracks "Container Size") # Installation -1. Pull your selected container ([linuxserver/radarr](https://hub.docker.com/r/linuxserver/radarr "LinuxServer.io's Radarr container") or [linuxserver/sonarr](https://hub.docker.com/r/linuxserver/sonarr "LinuxServer.io's Sonarr container")) from Docker Hub: - `docker pull linuxserver/radarr:latest` OR - `docker pull linuxserver/sonarr:latest` +1. Pull your selected container ([linuxserver/radarr](https://hub.docker.com/r/linuxserver/radarr "LinuxServer.io's Radarr container") or [linuxserver/sonarr](https://hub.docker.com/r/linuxserver/sonarr "LinuxServer.io's Sonarr container")) from GitHub Container Registry or Docker Hub: + `docker pull lscr.io/linuxserver/radarr:latest` OR + `docker pull lscr.io/linuxserver/sonarr:latest` 2. Configure the Docker container with all the port, volume, and environment settings from the *original container documentation* here: **[linuxserver/radarr](https://hub.docker.com/r/linuxserver/radarr "Radarr Docker container")** @@ -36,7 +36,7 @@ Production Container info: ![Docker Image Size](https://img.shields.io/docker/im -v /path/to/movies:/movies \ -v /path/to/downloadclient-downloads:/downloads \ --restart unless-stopped \ - ghcr.io/linuxserver/radarr + lscr.io/linuxserver/radarr ``` *Example Synology Configuration* @@ -57,11 +57,13 @@ Production Container info: ![Docker Image Size](https://img.shields.io/docker/im The source video can be any mkvtoolnix supported video format. The output is an MKV file with the same name. Chapters, if they exist, are preserved. The Title attribute in the MKV is set to the movie title plus year (ex: `The Sting (1973)`) or the series title plus episode information (ex: `Happy! 01x01 - What Smiles Are For`). -The language of the video file will be updated in the Radarr or Sonarr database to reflect the actual languages preserved in the remuxed video. +The language of the video file will be updated in the Radarr or Sonarr database to reflect the actual languages preserved in the remuxed video. If you've configured the Radarr/Sonarr **Recycle Bin** path correctly, the original video will be moved there. ![danger] **NOTE:** If you have *not* configured the Recycle Bin, the original video file will be deleted/overwritten and permanently lost. +If the resulting video file would contain the same tracks as the original, the remux step is skipped *unless* the source file is not an MKV. + ### Syntax Beginning with version 2.0 of this mod, the script may be called with no arguments. In this configuration it will detect the language(s) defined in the profile (*Quality Profile* for Radarr, *Language Profile* for Sonarr) configured on the particular movie or TV show. diff --git a/SECURITY.md b/SECURITY.md index eca05c7..858057f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,8 +6,8 @@ Only the latest major and minor version are supported. | Version | Supported | | ------- | ------------------ | -| 2.3.x | :heavy_check_mark: | -| < 2.3 | :x: | +| 2.4.x | :heavy_check_mark: | +| < 2.4 | :x: | ## Reporting a Vulnerability diff --git a/root/usr/local/bin/striptracks.sh b/root/usr/local/bin/striptracks.sh index 4326c74..d3f7110 100755 --- a/root/usr/local/bin/striptracks.sh +++ b/root/usr/local/bin/striptracks.sh @@ -18,6 +18,7 @@ # Dependencies: # mkvmerge +# mkvpropedit # awk # curl # jq @@ -31,13 +32,19 @@ # 1 - no video file specified on command line # 2 - no audio language specified on command line # 3 - no subtitles language specified on command line -# 4 - mkvmerge not found +# 4 - mkvmerge or mkvpropedit not found # 5 - input video file not found # 6 - unable to rename temp video to MKV # 7 - unknown eventtype environment variable # 8 - unsupported Radarr/Sonarr version (v2) # 9 - mkvmerge get media info failed # 10 - remuxing completed, but no output file found +# 11 - source video had no audio or subtitle tracks +# 12 - no tracks would be removed; remuxing not performed +# 13 - awk script exited abnormally +# 16 - could not delete the original file +# 17 - Radarr/Sonarr API error +# 18 - Radarr/Sonarr job timeout # 20 - general error ### Variables @@ -127,15 +134,15 @@ while (( "$#" )); do export striptracks_debug=1 shift fi - ;; + ;; --help ) # Display usage usage exit 0 - ;; + ;; --version ) # Display version echo "$striptracks_script $striptracks_ver" exit 0 - ;; + ;; -f|--file ) # Batch Mode if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then # Overrides detected *_eventtype @@ -147,7 +154,7 @@ while (( "$#" )); do usage exit 1 fi - ;; + ;; -a|--audio ) # Audio languages to keep if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then export striptracks_audiokeep="$2" @@ -157,7 +164,7 @@ while (( "$#" )); do usage exit 2 fi - ;; + ;; -s|--subs ) # Subtitles languages to keep if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then export striptracks_subskeep="$2" @@ -167,22 +174,22 @@ while (( "$#" )); do usage exit 3 fi - ;; + ;; -*|--*=) # Unknown option echo "Error|Unknown option: $1" >&2 usage exit 20 - ;; + ;; *) # preserve positional arguments striptracks_pos_params="$striptracks_pos_params $1" shift - ;; + ;; esac done # Set positional arguments in their proper place eval set -- "$striptracks_pos_params" -# Check for and assign positional arguments. Named arguments override positional arguments. +# Check for and assign positional arguments. Named override positional. if [ -n "$1" ]; then if [ -n "$striptracks_audiokeep" ]; then echo "Warning|Both positional and named arguments set for audio. Using $striptracks_audiokeep" >&2 @@ -206,41 +213,50 @@ if [[ "${striptracks_type,,}" = "batch" ]]; then elif [[ "${striptracks_type,,}" = "radarr" ]]; then # Radarr mode export striptracks_video="$radarr_moviefile_path" + export striptracks_video_folder="$radarr_movie_path" export striptracks_video_api="movie" export striptracks_video_id="${radarr_movie_id}" export striptracks_videofile_api="moviefile" export striptracks_videofile_id="${radarr_moviefile_id}" export striptracks_rescan_id="${radarr_movie_id}" - export striptracks_json_quality_root=".movieFile" + export striptracks_json_quality_root="movieFile" export striptracks_video_type="movie" export striptracks_profile_type="quality" + export striptracks_profile_jq=".qualityProfileId" export striptracks_title="${radarr_movie_title:-UNKNOWN} (${radarr_movie_year:-UNKNOWN})" export striptracks_language_api="language" + export striptracks_language_jq=".language" + # export striptracks_language_node="languages" elif [[ "${striptracks_type,,}" = "sonarr" ]]; then # Sonarr mode export striptracks_video="$sonarr_episodefile_path" + export striptracks_video_folder="$sonarr_series_path" export striptracks_video_api="episode" export striptracks_video_id="${sonarr_episodefile_episodeids}" export striptracks_videofile_api="episodefile" export striptracks_videofile_id="${sonarr_episodefile_id}" export striptracks_rescan_id="${sonarr_series_id}" - export striptracks_json_quality_root=".episodeFile" + export striptracks_json_quality_root="episodeFile" export striptracks_video_type="series" export striptracks_profile_type="language" + export striptracks_profile_jq=".series.languageProfileId" export striptracks_title="${sonarr_series_title:-UNKNOWN} $(numfmt --format "%02f" ${sonarr_episodefile_seasonnumber:-0})x$(numfmt --format "%02f" ${sonarr_episodefile_episodenumbers:-0}) - ${sonarr_episodefile_episodetitles:-UNKNOWN}" export striptracks_language_api="languageprofile" + export striptracks_language_jq=".languages[] | select(.allowed).language" + # export striptracks_language_node="language" + # # Sonarr requires the episodeIds array + # export striptracks_sonarr_json=" \"episodeIds\":[.episodes[].id]," else # Called in an unexpected way echo -e "Error|Unknown or missing '*_eventtype' environment variable: ${striptracks_type}\nNot called from Radarr/Sonarr.\nTry using Batch Mode option: -f " exit 7 fi export striptracks_rescan_api="Rescan${striptracks_video_type^}" -export striptracks_json_key="${striptracks_video_type}Id" export striptracks_eventtype="${striptracks_type,,}_eventtype" export striptracks_tempvideo="${striptracks_video%.*}.tmp" export striptracks_newvideo="${striptracks_video%.*}.mkv" # If this were defined directly in Radarr or Sonarr this would not be needed here -striptracks_isocodemap='{"languages":[{"language":{"name":"Any","iso639-2":["ara","ben","bos","bul","cat","zho","chi","hrv","ces","cze","dan","nld","dut","eng","est","fin","fra","fre","deu","ger","ell","gre","heb","hin","hun","isl","ice","ind","ita","jpn","kor","lav","lit","mal","nor","fas","per","pol","por","ron","rum","rus","srp","slk","slo","spa","swe","tam","tel","tha","tur","ukr","vie","und"]}},{"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":"Korean","iso639-2":["kor"]}},{"language":{"name":"Latvian","iso639-2":["lav"]}},{"language":{"name":"Lithuanian","iso639-2":["lit"]}},{"language":{"name":"Malayalam","iso639-2":["mal"]}},{"language":{"name":"Norwegian","iso639-2":["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":"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":"Spanish","iso639-2":["spa"]}},{"language":{"name":"Spanish (Latino)","iso639-2":["spa"]}},{"language":{"name":"Swedish","iso639-2":["swe"]}},{"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":"Vietnamese","iso639-2":["vie"]}},{"language":{"name":"Unknown","iso639-2":["und"]}}]}' +striptracks_isocodemap='{"languages":[{"language":{"name":"Any","iso639-2":["ara","ben","bos","bul","cat","zho","chi","hrv","ces","cze","dan","nld","dut","eng","est","fin","fra","fre","deu","ger","ell","gre","heb","hin","hun","isl","ice","ind","ita","jpn","kor","lav","lit","mal","nor","fas","per","pol","por","ron","rum","rus","srp","slk","slo","spa","swe","tam","tel","tha","tur","ukr","vie","und"]}},{"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":"Korean","iso639-2":["kor"]}},{"language":{"name":"Latvian","iso639-2":["lav"]}},{"language":{"name":"Lithuanian","iso639-2":["lit"]}},{"language":{"name":"Malayalam","iso639-2":["mal"]}},{"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":"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":"Spanish","iso639-2":["spa"]}},{"language":{"name":"Spanish (Latino)","iso639-2":["spa"]}},{"language":{"name":"Swedish","iso639-2":["swe"]}},{"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":"Vietnamese","iso639-2":["vie"]}},{"language":{"name":"Unknown","iso639-2":["und"]}}]}' ### Functions @@ -266,18 +282,44 @@ function read_xml { local IFS=\> read -d \< striptracks_xml_entity striptracks_xml_content } -# Get video information -function get_video_info { - [ $striptracks_debug -ge 1 ] && echo "Debug|Getting video information for $striptracks_video_api '$striptracks_video_id'. Calling ${striptracks_type^} API using GET and URL '$striptracks_api_url/v3/$striptracks_video_api/$striptracks_video_id'" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ - -X GET "$striptracks_api_url/v3/$striptracks_video_api/$striptracks_video_id") - local striptracks_return2=$?; [ "$striptracks_return2" != 0 ] && { - local striptracks_message="Error|[$striptracks_return2] curl error when calling: \"$striptracks_api_url/v3/$striptracks_video_api/$striptracks_video_id\"" +# Get Radarr/Sonarr version +function get_version { + local url="$striptracks_api_url/system/status" + [ $striptracks_debug -ge 1 ] && echo "Debug|Getting ${striptracks_type^} version. Calling ${striptracks_type^} API using GET and URL '$url'" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --get "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') echo "$striptracks_message" | log echo "$striptracks_message" >&2 } [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - if [ "$(echo $striptracks_result | jq -crM .hasFile)" = "true" ]; then + if [ "$(echo $striptracks_result | jq -crM '.version?')" != "null" ]; then + local striptracks_return=0 + else + local striptracks_return=1 + fi + return $striptracks_return +} +# Get video information +function get_video_info { + local url="$striptracks_api_url/$striptracks_video_api/$striptracks_video_id" + [ $striptracks_debug -ge 1 ] && echo "Debug|Getting video information for $striptracks_video_api '$striptracks_video_id'. Calling ${striptracks_type^} API using GET and URL '$url'" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --get "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + } + [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM .hasFile)" = "true" ]; then local striptracks_return=0 else local striptracks_return=1 @@ -286,16 +328,20 @@ function get_video_info { } # Get video file information function get_videofile_info { - [ $striptracks_debug -ge 1 ] && echo "Debug|Getting video file information for $striptracks_videofile_api id '$striptracks_videofile_id'. Calling ${striptracks_type^} API using GET and URL '$striptracks_api_url/v3/$striptracks_videofile_api/$striptracks_videofile_id'" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ - -X GET "$striptracks_api_url/v3/$striptracks_videofile_api/$striptracks_videofile_id") - local striptracks_return2=$?; [ "$striptracks_return2" != 0 ] && { - local striptracks_message="Error|[$striptracks_return2] curl error when calling: \"$striptracks_api_url/v3/$striptracks_videofile_api/$striptracks_videofile_id\"" + local url="$striptracks_api_url/$striptracks_videofile_api/$striptracks_videofile_id" + [ $striptracks_debug -ge 1 ] && echo "Debug|Getting video file information for $striptracks_videofile_api '$striptracks_videofile_id'. Calling ${striptracks_type^} API using GET and URL '$url'" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --get "$url" ) + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') echo "$striptracks_message" | log echo "$striptracks_message" >&2 } [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - if [ "$(echo $striptracks_result | jq -crM .path)" != "null" ]; then + if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM .path)" != "null" ]; then local striptracks_return=0 else local striptracks_return=1 @@ -304,69 +350,94 @@ function get_videofile_info { } # Initiate Rescan request function rescan { - striptracks_message="Info|Calling ${striptracks_type^} API to rescan ${striptracks_video_type}, try #$loop" - echo "$striptracks_message" | log - [ $striptracks_debug -ge 1 ] && echo "Debug|Forcing rescan of $striptracks_video_api '$striptracks_rescan_id', try #$loop. Calling ${striptracks_type^} API '$striptracks_rescan_api' using POST and URL '$striptracks_api_url/v3/command' with data {\"name\": \"$striptracks_rescan_api\", \"$striptracks_json_key\": $striptracks_rescan_id}" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" -H "Content-Type: application/json" \ - -d "{\"name\": \"$striptracks_rescan_api\", \"$striptracks_json_key\": $striptracks_rescan_id}" \ - -X POST "$striptracks_api_url/v3/command") - local striptracks_return2=$?; [ "$striptracks_return2" != 0 ] && { - local striptracks_message="Error|[$striptracks_return2] curl error when calling: \"$striptracks_api_url/v3/command\" with data {\"name\": \"$striptracks_rescan_api\", \"$striptracks_json_key\": $striptracks_rescan_id}" + local url="$striptracks_api_url/command" + local data="{\"name\":\"$striptracks_rescan_api\",\"${striptracks_video_type}Id\":$striptracks_rescan_id}" + echo "Info|Calling ${striptracks_type^} API to rescan ${striptracks_video_type}" | log + [ $striptracks_debug -ge 1 ] && echo "Debug|Forcing rescan of $striptracks_video_type '$striptracks_rescan_id'. Calling ${striptracks_type^} API using POST and URL '$url' with data $data" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d $data \ + "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') echo "$striptracks_message" | log echo "$striptracks_message" >&2 } [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log striptracks_jobid="$(echo $striptracks_result | jq -crM .id)" - if [ "$striptracks_jobid" != "null" ]; then + if [ $striptracks_curlret -eq 0 -a "$striptracks_jobid" != "null" ]; then local striptracks_return=0 else local striptracks_return=1 fi return $striptracks_return } -# Check result of rescan job -function check_rescan { +# Check result of command job +function check_job { + # Exit codes: + # 0 - success + # 1 - queued + # 2 - failed + # 3 - loop timed out + # 10 - curl error local i=0 + local url="$striptracks_api_url/command/$striptracks_jobid" + [ $striptracks_debug -ge 1 ] && echo "Debug|Checking job $striptracks_jobid completion. Calling ${striptracks_type^} API using GET and URL '$url'" | log for ((i=1; i <= 15; i++)); do - [ $striptracks_debug -ge 1 ] && echo "Debug|Checking job $striptracks_jobid completion, try #$i. Calling ${striptracks_type^} API using GET and URL '$striptracks_api_url/v3/command/$striptracks_jobid'" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ - -X GET "$striptracks_api_url/v3/command/$striptracks_jobid") - local striptracks_return2=$?; [ "$striptracks_return2" != 0 ] && { - local striptracks_message="Error|[$striptracks_return2] curl error when calling: \"$striptracks_api_url/v3/command/$striptracks_jobid\"" + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --get "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') echo "$striptracks_message" | log echo "$striptracks_message" >&2 + local striptracks_return=10 + break } [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + + # Guard clauses + if [ "$(echo $striptracks_result | jq -crM .status)" = "failed" ]; then + local striptracks_return=2 + break + fi + if [ "$(echo $flac2mp3_result | jq -crM .status)" = "queued" ]; then + local flac2mp3_return=1 + break + fi if [ "$(echo $striptracks_result | jq -crM .status)" = "completed" ]; then local striptracks_return=0 break - else - if [ "$(echo $striptracks_result | jq -crM .status)" = "failed" ]; then - local striptracks_return=2 - break - else - # It may have timed out, so let's wait a second - local striptracks_return=1 - [ $striptracks_debug -ge 1 ] && echo "Debug|Job not done. Waiting 1 second." | log - sleep 1 - fi fi + + # It may have timed out, so let's wait a second + [ $striptracks_debug -ge 1 ] && echo "Debug|Job not done. Waiting 1 second." | log + local striptracks_return=3 + sleep 1 done return $striptracks_return } # Get language/quality profiles function get_profiles { - [ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of $striptracks_profile_type profiles. Calling ${striptracks_type^} API using GET and URL '$striptracks_api_url/v3/${striptracks_profile_type}Profile'" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ - -X GET "$striptracks_api_url/v3/${striptracks_profile_type}Profile") - local striptracks_return2=$?; [ "$striptracks_return2" != 0 ] && { - local striptracks_message="Error|[$striptracks_return2] curl error when calling: \"$striptracks_api_url/v3/${striptracks_profile_type}Profile\"" + local url="$striptracks_api_url/${striptracks_profile_type}Profile" + [ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of $striptracks_profile_type profiles. Calling ${striptracks_type^} API using GET and URL '$url'" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --get "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') echo "$striptracks_message" | log echo "$striptracks_message" >&2 } # This returns A LOT of data, and it is normally not needed [ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - if [ "$(echo $striptracks_result | jq -crM '.message?')" != "NotFound" ]; then + if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM '.message?')" != "NotFound" ]; then local striptracks_return=0 else local striptracks_return=1 @@ -375,16 +446,95 @@ function get_profiles { } # Get language codes function get_language_codes { - [ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of language codes. Calling ${striptracks_type^} API using GET and URL '$striptracks_api_url/v3/${striptracks_language_api}'" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ - -X GET "$striptracks_api_url/v3/${striptracks_language_api}") - local striptracks_return2=$?; [ "$striptracks_return2" != 0 ] && { - local striptracks_message="Error|[$striptracks_return2] curl error when calling: \"$striptracks_api_url/v3/${striptracks_language_api}\"" + local url="$striptracks_api_url/${striptracks_language_api}" + [ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of language codes. Calling ${striptracks_type^} API using GET and URL '$url'" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --get "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') echo "$striptracks_message" | log echo "$striptracks_message" >&2 } [ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - if [ "$(echo $striptracks_result | jq -crM '.[] | .name')" != "null" ]; then + if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq -crM '.[] | .name')" != "null" ]; then + local striptracks_return=0 + else + local striptracks_return=1 + fi + return $striptracks_return +} +# Delete track +function delete_video { + local url="$striptracks_api_url/$striptracks_videofile_api/$1" + [ $striptracks_debug -ge 1 ] && echo "Debug|Deleting or recycling \"$striptracks_video\". Calling ${striptracks_type^} API using DELETE and URL '$url'" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -X DELETE "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + } + [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + if [ $striptracks_curlret -eq 0 ]; then + local striptracks_return=0 + else + local striptracks_return=1 + fi + return $striptracks_return +} +# # Get file details on possible files to import into Radarr/Sonarr +# function get_import_info { + # local url="$striptracks_api_url/manualimport" + # if [[ "${striptracks_type,,}" = "radarr" ]]; then + # local temp_id="${striptracks_video_type}Id=$striptracks_rescan_id" + # fi + # [ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of files that can be imported. Calling ${striptracks_type^} API using GET and URL '$url?${temp_id:+$temp_id&}folder=$striptracks_video_folder&filterExistingFiles=false'" | log + # unset striptracks_result + # # 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" \ + # --data-urlencode "${temp_id}" \ + # --data-urlencode "folder=$striptracks_video_folder" \ + # -d "filterExistingFiles=false" \ + # --get "$url") + # local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + # local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url?${temp_id:+$temp_id&}folder=$striptracks_video_folder&filterExistingFiles=false\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + # echo "$striptracks_message" | log + # echo "$striptracks_message" >&2 + # } + # [ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + # if [ $striptracks_curlret -eq 0 -a "${#striptracks_result}" != 0 ]; then + # local striptracks_return=0 + # else + # local striptracks_return=1 + # fi + # return $striptracks_return +# } +# Update file quality in Radarr/Sonarr +function set_quality { + local url="$striptracks_api_url/$striptracks_videofile_api/editor" + local data="{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"quality\":$striptracks_original_quality}" + [ $striptracks_debug -ge 1 ] && echo "Debug|Updating from quality '$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)' to '$(echo $striptracks_original_quality | jq -crM .quality.name)'. Calling ${striptracks_type^} API using PUT and URL '$url' with data $data" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d "$data" \ + -X PUT "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + } + [ $striptracks_debug -ge 3 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + if [ $striptracks_curlret -eq 0 -a "${#striptracks_result}" != 0 ]; then local striptracks_return=0 else local striptracks_return=1 @@ -394,20 +544,152 @@ function get_language_codes { # Read in the output of mkvmerge info extraction function get_mediainfo { [ $striptracks_debug -ge 1 ] && echo "Debug|Executing: /usr/bin/mkvmerge -J \"$1\"" | log + unset striptracks_json striptracks_json=$(/usr/bin/mkvmerge -J "$1") - local striptracks_return2=$?; [ "$striptracks_return2" != 0 ] && { - local striptracks_message="Error|[$striptracks_return2] Error executing mkvmerge." + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message="Error|[$striptracks_curlret] Error executing mkvmerge." echo "$striptracks_message" | log echo "$striptracks_message" >&2 } [ $striptracks_debug -ge 2 ] && echo "mkvmerge returned: $striptracks_json" | awk '{print "Debug|"$0}' | log - if [ "$(echo $striptracks_json | jq -crM '.container.supported')" == "true" ]; then + if [ "$(echo $striptracks_json | jq -crM '.container.supported')" = "true" ]; then local striptracks_return=0 else local striptracks_return=1 fi return $striptracks_return } +# # Import new video into Radarr/Sonarr +# function import_video { + # local url="$striptracks_api_url/command" + # local data="{\"name\":\"ManualImport\",\"files\":$striptracks_json,\"importMode\":\"auto\"}" + # echo "Info|Importing new video \"$striptracks_newvideo\" into ${striptracks_type^}" | log + # [ $striptracks_debug -ge 1 ] && echo "Debug|Importing new file into ${striptracks_type^}. Calling ${striptracks_type^} API using POST and URL '$url' with data $data" | log + # unset striptracks_result + # striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + # -H "Content-Type: application/json" \ + # -H "Accept: application/json" \ + # -d "$data" \ + # "$url") + # local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + # local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + # echo "$striptracks_message" | log + # echo "$striptracks_message" >&2 + # } + # [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + # if [ $striptracks_curlret -eq 0 -a "$(echo $striptracks_result | jq .id?)" != "null" ]; then + # local striptracks_return=0 + # else + # local striptracks_return=1 + # fi + # return $striptracks_return +# } +# Get video files from Radarr/Sonarr that need to be renamed +function get_rename { + local url="$striptracks_api_url/rename" + local data="${striptracks_video_type}Id=$striptracks_rescan_id" + [ $striptracks_debug -ge 1 ] && echo "Debug|Getting list of videos that could be renamed. Calling ${striptracks_type^} API using GET and URL '$url&$data'" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d "$data" \ + --get "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url&$data\"\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + } + [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then + local striptracks_return=0 + else + local striptracks_return=1 + fi + return $striptracks_return +} +# Rename video file according to Radarr/Sonarr naming rules +function rename_video { + local url="$striptracks_api_url/command" + local data="{\"name\":\"RenameFiles\",\"${striptracks_video_type}Id\":$striptracks_rescan_id,\"files\":[$striptracks_videofile_id]}" + echo "Info|Renaming new video file per ${striptracks_type^}'s rules to \"$(basename "$striptracks_renamedvideo")\"" | log + [ $striptracks_debug -ge 1 ] && echo "Debug|Renaming \"$striptracks_newvideo\". Calling ${striptracks_type^} API using POST and URL '$url' with data $data" | log + unset striptracks_result + striptracks_result=$(curl -s --fail-with-body -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d "$data" \ + "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + } + [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then + local striptracks_return=0 + else + local striptracks_return=1 + fi + return $striptracks_return +} +# Set video language in Radarr +function set_radarr_language { + local url="$striptracks_api_url/$striptracks_videofile_api/editor" + local data="{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"languages\":${striptracks_json_languages}}" + [ $striptracks_debug -ge 1 ] && echo "Debug|Updating from language(s) '$(echo $striptracks_videofile_info | jq -crM "[.languages[].name] | join(\",\")")' to '$(echo $striptracks_json_languages | jq -crM "[.[].name] | join(\",\")")'. Calling ${striptracks_type^} API using PUT and URL '$url' with data $data" | log + unset striptracks_result + striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d "$data" \ + -X PUT "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + } + [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then + local striptracks_return=0 + else + local striptracks_return=1 + fi + return $striptracks_return +} +# Set video language in Sonarr +function set_sonarr_language { + local url="$striptracks_api_url/$striptracks_videofile_api/editor" + local data="{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"language\":$(echo $striptracks_json_languages | jq -crM ".[0]")}" + [ $striptracks_debug -ge 1 ] && echo "Debug|Updating from language '$(echo $striptracks_videofile_info | jq -crM ".language.name")' to '$(echo $striptracks_json_languages | jq -crM ".[0].name")'. Calling ${striptracks_type^} API using PUT and URL '$striptracks_api_url/v3/$striptracks_videofile_api/editor' with data $data" | log + unset striptracks_result + striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d "$data" \ + -X PUT "$url") + local striptracks_curlret=$?; [ $striptracks_curlret -ne 0 ] && { + local striptracks_message=$(echo -e "[$striptracks_curlret] curl error when calling: \"$url\" with data $data\nWeb server returned: $(echo $striptracks_result | jq -crM .message?)" | awk '{print "Error|"$0}') + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + } + [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log + if [ $striptracks_curlret -eq 0 -a "$striptracks_result" != "null" ]; then + local striptracks_return=0 + else + local striptracks_return=1 + fi + return $striptracks_return +} +# Exit program +function end_script { + # Cool bash feature + striptracks_message="Info|Completed in $(($SECONDS/60))m $(($SECONDS%60))s" + echo "$striptracks_message" | log + [ "$1" != "" ] && striptracks_exitstatus=$1 + [ $striptracks_debug -ge 1 ] && echo "Debug|Exit code ${striptracks_exitstatus:-0}" | log + exit ${striptracks_exitstatus:-0} +} ### End Functions # Check for required binaries @@ -415,7 +697,13 @@ if [ ! -f "/usr/bin/mkvmerge" ]; then striptracks_message="Error|/usr/bin/mkvmerge is required by this script" echo "$striptracks_message" | log echo "$striptracks_message" >&2 - exit 4 + end_script 4 +fi +if [ ! -f "/usr/bin/mkvpropedit" ]; then + striptracks_message="Error|/usr/bin/mkvpropedit is required by this script" + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + end_script 4 fi # Log Debug state @@ -428,6 +716,15 @@ fi # Log environment [ $striptracks_debug -ge 2 ] && printenv | sort | sed 's/^/Debug|/' | log +# Handle Test event +if [[ "${!striptracks_eventtype}" = "Test" ]]; then + echo "Info|${striptracks_type^} event: ${!striptracks_eventtype}" | log + striptracks_message="Info|Script was test executed successfully." + echo "$striptracks_message" | log + echo "$striptracks_message" + end_script 0 +fi + # Log Batch mode if [ "$striptracks_type" = "batch" ]; then [ $striptracks_debug -ge 1 ] && echo "Debug|Switching to batch mode. Input filename: ${striptracks_video}" | log @@ -446,23 +743,17 @@ elif [ -f "$striptracks_arr_config" ]; then [[ $striptracks_xml_entity = "ApiKey" ]] && striptracks_apikey=$striptracks_xml_content done < $striptracks_arr_config + # Check for localhost [[ $striptracks_bindaddress = "*" ]] && striptracks_bindaddress=localhost # Build URL to Radarr/Sonarr API - striptracks_api_url="http://$striptracks_bindaddress:$striptracks_port$striptracks_urlbase/api" + striptracks_api_url="http://$striptracks_bindaddress:$striptracks_port$striptracks_urlbase/api/v3" # Check Radarr/Sonarr version - [ $striptracks_debug -ge 1 ] && echo "Debug|Getting ${striptracks_type^} version. Calling ${striptracks_type^} API using GET and URL '$striptracks_api_url/v3/system/status'" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ - -X GET "$striptracks_api_url/v3/system/status") - striptracks_return=$?; [ "$striptracks_return" != 0 ] && { - striptracks_message="Error|[$striptracks_return] curl or jq error when parsing: \"$striptracks_api_url/v3/system/status\" | jq -crM .version" - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - } - [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - striptracks_arr_version="$(echo $striptracks_result | jq -crM .version)" - [ $striptracks_debug -ge 1 ] && echo "Debug|Detected ${striptracks_type^} version $striptracks_arr_version" | log + if get_version; then + striptracks_arr_version="$(echo $striptracks_result | jq -crM .version)" + [ $striptracks_debug -ge 1 ] && echo "Debug|Detected ${striptracks_type^} version $striptracks_arr_version" | log + fi # Requires API v3 if [ "${striptracks_arr_version/.*/}" = "2" ]; then @@ -470,21 +761,8 @@ elif [ -f "$striptracks_arr_config" ]; then striptracks_message="Error|This script does not support ${striptracks_type^} version ${striptracks_arr_version}. Please upgrade." echo "$striptracks_message" | log echo "$striptracks_message" >&2 - exit 8 + end_script 8 fi - - # Get RecycleBin - [ $striptracks_debug -ge 1 ] && echo "Debug|Getting ${striptracks_type^} RecycleBin. Calling ${striptracks_type^} API using GET and URL '$striptracks_api_url/v3/config/mediamanagement'" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" \ - -X GET "$striptracks_api_url/v3/config/mediamanagement") - striptracks_return=$?; [ "$striptracks_return" != 0 ] && { - striptracks_message="Error|[$striptracks_return] curl or jq error when parsing: \"$striptracks_api_url/v3/config/mediamanagement\" | jq -crM .recycleBin" - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - } - [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - striptracks_recyclebin="$(echo $striptracks_result | jq -crM .recycleBin)" - [ $striptracks_debug -ge 1 ] && echo "Debug|Detected ${striptracks_type^} RecycleBin '$striptracks_recyclebin'" | log else # No config file means we can't call the API. Best effort at this point. striptracks_message="Warn|Unable to locate ${striptracks_type^} config file: '$striptracks_arr_config'" @@ -492,22 +770,13 @@ else echo "$striptracks_message" >&2 fi -# Handle Test event -if [[ "${!striptracks_eventtype}" = "Test" ]]; then - echo "Info|${striptracks_type^} event: ${!striptracks_eventtype}" | log - striptracks_message="Info|Script was test executed successfully." - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - exit 0 -fi - # Check if video file variable is blank if [ -z "$striptracks_video" ]; then - striptracks_message="Error|No video file detected! radarr_moviefile_path or sonarr_episodefile_path environment variable missing or -f option not specified on command line." + striptracks_message="Error|No video file detected! radarr_moviefile_path or sonarr_episodefile_path environment variable missing and -f option not specified on command line." echo "$striptracks_message" | log echo "$striptracks_message" >&2 usage - exit 1 + end_script 1 fi # Check if source video exists @@ -515,11 +784,11 @@ if [ ! -f "$striptracks_video" ]; then striptracks_message="Error|Input file not found: \"$striptracks_video\"" echo "$striptracks_message" | log echo "$striptracks_message" >&2 - exit 5 + end_script 5 fi -#### Detect languages configured in Radarr/Sonarr -# Bypass language detection if using batch mode +#### Prep work. Includes detect languages configured in Radarr/Sonarr, quality of video, etc. +# Bypass if using batch mode if [ "$striptracks_type" = "batch" ]; then [ $striptracks_debug -ge 1 ] && echo "Debug|Cannot detect languages in batch mode." | log # Check for URL @@ -527,40 +796,45 @@ elif [ -n "$striptracks_api_url" ]; then # Get language codes if get_language_codes; then striptracks_lang_codes="$striptracks_result" + # Fix for Sonarr code formatting + if [ "${striptracks_type,,}" = "sonarr" ]; then + striptracks_lang_codes="$(echo $striptracks_lang_codes | jq -crM '[.[0].languages[].language]')" + fi # Get quality/language profile info if get_profiles; then striptracks_profiles="$striptracks_result" # Get video profile if get_video_info; then - # Per environment logic - if [[ "${striptracks_type,,}" = "radarr" ]]; then - striptracks_lang_codes="$striptracks_lang_codes" - striptracks_profileId="$(echo $striptracks_result | jq -crM .qualityProfileId)" - striptracks_languages="$(echo $striptracks_profiles | jq -cM "[.[] | select(.id == $striptracks_profileId) | .language]")" - elif [[ "${striptracks_type,,}" = "sonarr" ]]; then - striptracks_lang_codes="$(echo $striptracks_lang_codes | jq -crM "[.[0].languages[].language]")" - striptracks_profileId="$(echo $striptracks_result | jq -crM .series.languageProfileId)" - striptracks_languages="$(echo $striptracks_profiles | jq -crM "[.[] | select(.id == $striptracks_profileId) | .languages[] | select(.allowed).language]")" - else - # Should never fire due to previous checks, but just in case - striptracks_message "Error|Unknown environment detected late: ${striptracks_type}" + # This is not necessary, as this is normally set in the environment. However, this is needed for testing. + striptracks_videofile_id="$(echo $striptracks_result | jq -crM .${striptracks_json_quality_root}.id)" + # Get language name(s) from video profile ID + striptracks_profileId="$(echo $striptracks_result | jq -crM $striptracks_profile_jq)" + striptracks_languages="$(echo $striptracks_profiles | jq -cM "[.[] | select(.id == $striptracks_profileId) | $striptracks_language_jq]")" + striptracks_profileName="$(echo $striptracks_profiles | jq -crM ".[] | select(.id == $striptracks_profileId).name")" + striptracks_proflangNames="$(echo $striptracks_languages | jq -crM '[.[].name]')" + # Get originalLanguage of video from Radarr (returns null for Sonarr) + striptracks_orglangName="$(echo $striptracks_result | jq -crM .originalLanguage.name)" + # Get video file info. Needed to save the original quality. + get_videofile_info + striptracks_return=$?; [ $striptracks_return -ne 0 ] && { + # No '.path' in returned JSON + striptracks_message="Warn|The '$striptracks_videofile_api' API with id $striptracks_videofile_id returned no path." echo "$striptracks_message" | log echo "$striptracks_message" >&2 - exit 7 - fi - striptracks_profileName="$(echo $striptracks_profiles | jq -crM ".[] | select(.id == $striptracks_profileId).name")" + striptracks_exitstatus=20 + } + # Save original quality + striptracks_original_quality="$(echo $striptracks_result | jq -crM .quality)" + [ $striptracks_debug -ge 1 ] && echo "Debug|Detected quality '$(echo $striptracks_original_quality | jq -crM .quality.name)'" | log [ $striptracks_debug -ge 1 ] && echo "Debug|Detected $striptracks_profile_type profile '(${striptracks_profileId}) ${striptracks_profileName}'" | log - striptracks_proflangNames="$(echo $striptracks_languages | jq -crM "[.[].name]")" [ $striptracks_debug -ge 1 ] && echo "Debug|Detected $striptracks_profile_type profile language(s) '$(echo $striptracks_languages | jq -crM '[.[] | "(\(.id | tostring)) \(.name)"] | join(",")')'" | log - # Get originalLanguage of video from Radarr - striptracks_orglangName="$(echo $striptracks_result | jq -crM .originalLanguage.name)" - if [ -n "$striptracks_orglangName" ]; then + if [ -n "$striptracks_orglangName" -a "$striptracks_orglangName" != "null" ]; then striptracks_orglangCode="$(echo $striptracks_isocodemap | jq -jcrM ".languages[] | select(.language.name == \"$striptracks_orglangName\") | .language | \":\(.\"iso639-2\"[])\"")" - [ $striptracks_debug -ge 1 ] && echo "Debug|Detected original video language of '$striptracks_orglangName ($striptracks_orglangCode)' from $striptracks_video_type '$striptracks_video_id'" | log + [ $striptracks_debug -ge 1 ] && echo "Debug|Detected original video language of '$striptracks_orglangName ($striptracks_orglangCode)' from $striptracks_video_type '$striptracks_rescan_id'" | log fi # Map language names to ISO code(s) used by mkvmerge unset striptracks_proflangCodes - for striptracks_templang in $(echo $striptracks_proflangNames | jq -crM ".[]"); do + for striptracks_templang in $(echo $striptracks_proflangNames | jq -crM '.[]'); do # Convert 'Original' profile selection to specific video language (Radarr only) if [[ "$striptracks_templang" = "Original" ]]; then striptracks_templang="$striptracks_orglangName" @@ -573,29 +847,33 @@ elif [ -n "$striptracks_api_url" ]; then striptracks_message="Warn|The '$striptracks_video_api' API with id $striptracks_video_id returned a false hasFile." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=17 fi else # Get Profiles API failed striptracks_message="Warn|Unable to retrieve $striptracks_profile_type profiles from ${striptracks_type^} API" echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=17 fi else # Get language codes API failed - striptracks_message="Warn|Unable to retrieve language codes from '$striptracks_language_api' API (returned a null name)." + striptracks_message="Warn|Unable to retrieve language codes from '$striptracks_language_api' API (curl error or returned a null name)." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=17 fi else # No URL means we can't call the API striptracks_message="Warn|Unable to determine ${striptracks_type^} API URL." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=20 fi -# Special handling for ':org' code. This is only valid in Radarr! +# Special handling for ':org' code from command line. This is only valid in Radarr! if [[ "$striptracks_audiokeep" =~ :org ]]; then - [ $striptracks_debug -ge 1 ] && echo "Debug|:org specified for audio. Changing '${striptracks_audiokeep}' to '${striptracks_audiokeep//:org/${striptracks_orglangCode}}'" | log + [ $striptracks_debug -ge 1 ] && echo "Debug|Command line ':org' code specified for audio. Changing '${striptracks_audiokeep}' to '${striptracks_audiokeep//:org/${striptracks_orglangCode}}'" | log striptracks_audiokeep="${striptracks_audiokeep//:org/${striptracks_orglangCode}}" if [ "${striptracks_type,,}" = "sonarr" -o "${striptracks_type,,}" = "batch" ]; then striptracks_message="Warn|:org code specified for audio, but this is undefined for Sonarr and Batch mode! Unexpected behavior may result." @@ -604,7 +882,7 @@ if [[ "$striptracks_audiokeep" =~ :org ]]; then fi fi if [[ "$striptracks_subskeep" =~ :org ]]; then - [ $striptracks_debug -ge 1 ] && echo "Debug|:org specified for subtitles. Changing '${striptracks_subskeep}' to '${striptracks_subskeep//:org/${striptracks_orglangCode}}'" | log + [ $striptracks_debug -ge 1 ] && echo "Debug|Command line ':org' specified for subtitles. Changing '${striptracks_subskeep}' to '${striptracks_subskeep//:org/${striptracks_orglangCode}}'" | log striptracks_subskeep="${striptracks_subskeep//:org/${striptracks_orglangCode}}" if [ "${striptracks_type,,}" = "sonarr" -o "${striptracks_type,,}" = "batch" ]; then striptracks_message="Warn|:org code specified for subtitles, but this is undefined for Sonarr and Batch mode! Unexpected behavior may result." @@ -620,7 +898,7 @@ if [ -z "$striptracks_audiokeep" -a -z "$striptracks_proflangCodes" ]; then echo "$striptracks_message" | log echo "$striptracks_message" >&2 usage - exit 2 + end_script 2 fi ## Allows command line argument to override detected languages if [ -z "$striptracks_audiokeep" -a -n "$striptracks_proflangCodes" ]; then @@ -651,7 +929,7 @@ if get_mediainfo "$striptracks_video"; then ( if (.chapters[] | .num_entries) then "Chapters: \(.chapters[] | .num_entries) entries\n" else - "" + empty end ), ( .tracks[] | @@ -667,7 +945,7 @@ else striptracks_message="Error|Container format '$(echo $striptracks_json | jq -crM .container.type)' is unsupported by mkvmerge. Unable to continue." echo "$striptracks_message" | log echo "$striptracks_message" >&2 - exit 9 + end_script 9 fi # Process video file @@ -677,6 +955,7 @@ echo "$striptracks_json_processed" | awk -v Debug=$striptracks_debug \ -v Title="$striptracks_title" \ -v AudioKeep="$striptracks_audiokeep" \ -v SubsKeep="$striptracks_subskeep" ' +# Exit codes: 0 success; 1 No tracks in source file; 2 No tracks removed; 3 How did we get here? # Array join function, based on GNU docs function join(array, sep, i, ret) { for (i in array) @@ -722,9 +1001,9 @@ BEGIN { Chapters = $3 } END { + # Source video had no tracks if (!NoTr) { - print "Error|No tracks found in \""Video"\"" > "/dev/stderr" - exit + exit 1 } if (!AudCnt) AudCnt=0; if (!SubsCnt) SubsCnt=0 print "Info|Original tracks: "NoTr" (audio: "AudCnt", subtitles: "SubsCnt")" @@ -758,12 +1037,21 @@ END { if (length(AudRmvLog) != 0) print "Info|Removed audio tracks: " join(AudRmvLog, ",") if (length(SubsRmvLog) != 0) print "Info|Removed subtitles tracks: " join(SubsRmvLog, ",") print "Info|Kept tracks: "length(AudioCommand)+length(SubsCommand)+VidCnt" (audio: "length(AudioCommand)", subtitles: "length(SubsCommand)")" + # All tracks matched/no tracks removed. + if (length(AudioCommand)+length(SubsCommand)+VidCnt == NoTr) { + if (Debug >= 1) print "Debug|No tracks will be removed from video \""Video"\"" + # Only skip remux if already MKV. + if (match(Video, /\.mkv$/)) { + exit 2 + } + if (Debug >= 1) print "Debug|Source video is not MKV. Remuxing anyway." + } + # This should never happen, but belt and suspenders if (length(AudioCommand) == 0) { - # This should never happen, but belt and suspenders - # Prevents errors during mkvmerge execution - CommandLine = "-A" - } else - CommandLine = "-a " join(AudioCommand, ",") + print "Warn|Script encountered an error when determining audio tracks to keep and must close." + exit 3 + } + CommandLine = "-a " join(AudioCommand, ",") if (length(SubsCommand) == 0) CommandLine = CommandLine" -S" else @@ -774,41 +1062,69 @@ END { }' | log #### END MAIN -# Check for script completion and non-empty file +# Check awk exit code +striptracks_return="${PIPESTATUS[1]}" +[ $striptracks_debug -ge 2 ] && echo "Debug|awk exited with code: $striptracks_return" | log +[ $striptracks_return -ne 0 ] && { + case "$striptracks_return" in + 1) # Source video had no tracks + striptracks_message="Error|The original video \"$striptracks_video\" had no audio or subtitle tracks!" + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + end_script 11 + ;; + 2) # All tracks matched/no tracks removed and already MKV. Remuxing not performed. + striptracks_message="Info|No tracks would be removed from video. Setting Title only and exiting." + echo "$striptracks_message" | log + [ $striptracks_debug -ge 1 ] && echo "Debug|Executing: /usr/bin/mkvpropedit -q --edit info --set \"title=$striptracks_title\" \"$striptracks_video\"" | log + /usr/bin/mkvpropedit -q --edit info --set "title=$striptracks_title" "$striptracks_video" 2>&1 | log + end_script 12 + ;; + *) striptracks_message="Error|[$striptracks_return] Script exited abnormally." + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + end_script 13 + ;; + esac +} + +# Check for non-empty file if [ ! -s "$striptracks_tempvideo" ]; then striptracks_message="Error|Unable to locate or invalid remuxed file: \"$striptracks_tempvideo\". Halting." echo "$striptracks_message" | log echo "$striptracks_message" >&2 - exit 10 + end_script 10 fi -# Remove the original video. Use Recycle Bin if configured -if [ "$striptracks_recyclebin" ]; then - [ $striptracks_debug -ge 1 ] && echo "Debug|Recycling: \"$striptracks_video\" to \"${striptracks_recyclebin%/}/$(basename "$striptracks_video")"\" | log - mv "$striptracks_video" "${striptracks_recyclebin%/}/$(basename "$striptracks_video")" 2>&1 | log - striptracks_return=$?; [ "$striptracks_return" != 0 ] && { - striptracks_message="Error|[$striptracks_return] Unable to move video: \"$striptracks_video\" to Recycle Bin: \"${striptracks_recyclebin%/}/$(basename "$striptracks_video")\"" - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - } -else +# Just delete the original video if running in batch mode +if [ "$striptracks_type" = "batch" ]; then [ $striptracks_debug -ge 1 ] && echo "Debug|Deleting: \"$striptracks_video\"" | log rm "$striptracks_video" 2>&1 | log - striptracks_return=$?; [ "$striptracks_return" != 0 ] && { - striptracks_message="Error|[$striptracks_return] Unable to delete original video: \"$striptracks_video\"" + striptracks_return=$?; [ $striptracks_return -ne 0 ] && { + striptracks_message="Error|[$striptracks_return] Error when deleting track: \"$striptracks_track\"" echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=16 + } +else + # Call Radarr/Sonarr to delete the original video, or recycle if configured. + delete_video $striptracks_videofile_id + striptracks_return=$?; [ $striptracks_return -ne 0 ] && { + striptracks_message="Error|[$striptracks_return] ${striptracks_type^} error when deleting the original video: \"$striptracks_video\"" + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=17 } fi # Rename the temporary video file to MKV [ $striptracks_debug -ge 1 ] && echo "Debug|Renaming: \"$striptracks_tempvideo\" to \"$striptracks_newvideo\"" | log mv -f "$striptracks_tempvideo" "$striptracks_newvideo" 2>&1 | log -striptracks_return=$?; [ "$striptracks_return" != 0 ] && { +striptracks_return=$?; [ $striptracks_return -ne 0 ] && { striptracks_message="Error|[$striptracks_return] Unable to rename temp video: \"$striptracks_tempvideo\" to: \"$striptracks_newvideo\". Halting." echo "$striptracks_message" | log echo "$striptracks_message" >&2 - exit 6 + end_script 6 } striptracks_filesize=$(numfmt --to iec --format "%.3f" $(stat -c %s "$striptracks_newvideo")) @@ -822,166 +1138,209 @@ if [ "$striptracks_type" = "batch" ]; then elif [ -n "$striptracks_api_url" ]; then # Check for video IDs if [ "$striptracks_video_id" -a "$striptracks_videofile_id" ]; then - # Get video file info - if get_videofile_info; then - # Save original quality - striptracks_original_quality="$(echo $striptracks_result | jq -crM .quality)" - [ $striptracks_debug -ge 1 ] && echo "Debug|Detected quality '$(echo $striptracks_original_quality | jq -crM .quality.name)'." | log - # Loop a maximum of twice - # Radarr needs to Rescan twice when the file extension changes (.avi -> .mkv for example) - for ((loop=1; $loop <= 2; loop++)); do - # Scan the disk for the new movie file - if rescan; then - # Give it a beat - sleep 1 - # Check that the Rescan completed - if check_rescan; then - # Get new video file id - if get_video_info; then - # Get new video file ID - striptracks_videofile_id="$(echo $striptracks_result | jq -crM ${striptracks_json_quality_root}.id)" - [ $striptracks_debug -ge 1 ] && echo "Debug|Set new video file id '$striptracks_videofile_id'." | log - # Get new video file info - if get_videofile_info; then - striptracks_videofile_info="$striptracks_result" - # Check that the file didn't get lost in the Rescan. - # If we lost the quality information, put it back - if [ "$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)" != "$(echo $striptracks_original_quality | jq -crM .quality.name)" ]; then - [ $striptracks_debug -ge 1 ] && echo "Debug|Updating from quality '$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)' to '$(echo $striptracks_original_quality | jq -crM .quality.name)'. Calling ${striptracks_type^} API using PUT and URL '$striptracks_api_url/v3/$striptracks_videofile_api/editor' with data {\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"quality\":$striptracks_original_quality}" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" -H "Content-Type: application/json" \ - -d "{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"quality\":$striptracks_original_quality}" \ - -X PUT "$striptracks_api_url/v3/$striptracks_videofile_api/editor") - striptracks_return=$?; [ "$striptracks_return" != 0 ] && { - striptracks_message="Error|[$striptracks_return] curl error when calling: \"$striptracks_api_url/v3/$striptracks_videofile_api/editor\" with data {\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"quality\":$striptracks_original_quality}" - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - } - [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - # Check that the returned result shows the update - if [ "$(echo $striptracks_result | jq -crM .[].quality.quality.name)" = "$(echo $striptracks_original_quality | jq -crM .quality.name)" ]; then - # Updated successfully - [ $striptracks_debug -ge 1 ] && echo "Debug|Successfully updated quality to '$(echo $striptracks_result | jq -crM .[].quality.quality.name)'." | log - loop=2 - else - striptracks_message="Warn|Unable to update ${striptracks_type^} $striptracks_video_api '$striptracks_title' to quality '$(echo $striptracks_original_quality | jq -crM .quality.name)'" - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - fi - else - # The quality is already correct - [ $striptracks_debug -ge 1 ] && echo "Debug|Quality of '$(echo $striptracks_original_quality | jq -crM .quality.name)' remained unchanged." | log - loop=2 - fi - # Check the languages returned - # If we stripped out other languages, remove them from Radarr - # Only works in Radarr (no per-episode edit function in Sonarr) - unset striptracks_json - if get_mediainfo "$striptracks_newvideo"; then - # Build array of full name languages - striptracks_final_langcodes="$(echo $striptracks_json | jq -crM ".tracks[] | select(.type == \"audio\") | .properties.language")" - unset striptracks_newvideo_languages - for i in $striptracks_final_langcodes; do - striptracks_newvideo_languages+="$(echo $striptracks_isocodemap | jq -crM ".languages[] | .language | select((.\"iso639-2\"[]) == \"$i\") | select(.name != \"Any\" and .name != \"Original\").name")" - done - if [ -n "$striptracks_newvideo_languages" ]; then - # Covert to standard JSON - striptracks_json_languages="$(echo $striptracks_lang_codes | jq -crM "map(select(.name | inside(\"$striptracks_newvideo_languages\")) | {id, name})")" - # Check languages for Radarr - if [ "$(echo $striptracks_videofile_info | jq -crM .languages)" != "null" ]; then - if [ "$(echo $striptracks_videofile_info | jq -crM ".languages")" != "$striptracks_json_languages" ]; then - [ $striptracks_debug -ge 1 ] && echo "Debug|Updating from language(s) '$(echo $striptracks_videofile_info | jq -crM "[.languages[].name] | join(\",\")")' to '$(echo $striptracks_json_languages | jq -crM "[.[].name] | join(\",\")")'. Calling ${striptracks_type^} API using PUT and URL '$striptracks_api_url/v3/$striptracks_videofile_api/editor' with data {\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"languages\":${striptracks_json_languages}}" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" -H "Content-Type: application/json" \ - -d "{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"languages\":${striptracks_json_languages}}" \ - -X PUT "$striptracks_api_url/v3/$striptracks_videofile_api/editor") - striptracks_return=$?; [ "$striptracks_return" != 0 ] && { - striptracks_message="Error|[$striptracks_return] curl error when calling: \"$striptracks_api_url/v3/$striptracks_videofile_api/editor\" with data {\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"languages\":${striptracks_json_languages}}" - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - } - [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - else - # The languages are already correct - [ $striptracks_debug -ge 1 ] && echo "Debug|Language(s) '$(echo $striptracks_json_languages | jq -crM "[.[].name] | join(\",\")")' remained unchanged." | log - fi - # Check languages for Sonarr - elif [ "$(echo $striptracks_videofile_info | jq -crM .language)" != "null" ]; then - if [ "$(echo $striptracks_videofile_info | jq -crM ".language")" != "$(echo $striptracks_json_languages | jq -crM ".[0]")" ]; then - [ $striptracks_debug -ge 1 ] && echo "Debug|Updating from language '$(echo $striptracks_videofile_info | jq -crM ".language.name")' to '$(echo $striptracks_json_languages | jq -crM ".[0].name")'. Calling ${striptracks_type^} API using PUT and URL '$striptracks_api_url/v3/$striptracks_videofile_api/editor' with data {\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"language\":$(echo $striptracks_json_languages | jq -crM ".[0]")}" | log - striptracks_result=$(curl -s -H "X-Api-Key: $striptracks_apikey" -H "Content-Type: application/json" \ - -d "{\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"language\":$(echo $striptracks_json_languages | jq -crM ".[0]")}" \ - -X PUT "$striptracks_api_url/v3/$striptracks_videofile_api/editor") - striptracks_return=$?; [ "$striptracks_return" != 0 ] && { - striptracks_message="Error|[$striptracks_return] curl error when calling: \"$striptracks_api_url/v3/$striptracks_videofile_api/editor\" with data {\"${striptracks_videofile_api}Ids\":[${striptracks_videofile_id}],\"languages\":$(echo $striptracks_json_languages | jq -crM ".[0]")}" - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - } - [ $striptracks_debug -ge 2 ] && echo "API returned: $striptracks_result" | awk '{print "Debug|"$0}' | log - else - # The languages are already correct - [ $striptracks_debug -ge 1 ] && echo "Debug|Language '$(echo $striptracks_json_languages | jq -crM ".[0].name")' remained unchanged." | log - fi - else - # Some unknown JSON formatting - striptracks_message="Warn|The '$striptracks_videofile_api' API returned unknown JSON language location." - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - fi - else - # Video language not in striptracks_isocodemap - striptracks_message="Warn|Video language code(s) '${striptracks_newvideo_languages//$'\n'/,}' not found in the ISO Codemap. Cannot evaluate." - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - fi - else - # Get media info failed - striptracks_message="Error|Could not get media info from new video file. Can't check resulting languages." - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - fi - else - # No '.path' in returned JSON - striptracks_message="Warn|The '$striptracks_videofile_api' API with ${striptracks_video_api}File id $striptracks_videofile_id returned no path." - echo "$striptracks_message" | log - echo "$striptracks_message" >&2 - fi + ##### Leaving this here (and all supporting functions and variables) in case the single file import job problem can be resolved. + ##### See GitHub Issue #50. Importing directly is a much better way than rescanning. + # Scan for files to import into Radarr/Sonarr + # if get_import_info; then + # # Build JSON data + # [ $striptracks_debug -ge 1 ] && echo "Debug|Building JSON data to import" | log + # striptracks_json=$(echo $striptracks_result | jq -jcrM " + # map( + # select(.path == \"$striptracks_newvideo\") | + # {path, folderName, \"${striptracks_video_type}Id\":.${striptracks_video_type}.id,${striptracks_sonarr_json} quality, $striptracks_language_node} + # ) + # ") + + # # Import new video into Radarr/Sonarr + # import_video + # striptracks_return=$?; [ $striptracks_return -ne 0 ] && { + # striptracks_message="Error|[$striptracks_return] ${striptracks_type^} error when importing new video!" + # echo "$striptracks_message" | log + # echo "$striptracks_message" >&2 + # striptracks_exitstatus=17 + # } + # striptracks_jobid="$(echo $striptracks_result | jq -crM .id)" + # Check status of job + # Scan the disk for the new movie file + if rescan; then + # Give it a beat + sleep 1 + # Check that the Rescan completed + check_job + striptracks_return=$?; [ $striptracks_return -ne 0 ] && { + case $striptracks_return in + 1) striptracks_message="Info|${striptracks_type^} job ID $striptracks_jobid is queued. Trusting this will complete and exiting." + striptracks_exitstatus=0 + ;; + 2) striptracks_message="Warn|${striptracks_type^} job ID $striptracks_jobid failed." + striptracks_exitstatus=17 + ;; + 3) striptracks_message="Warn|Script timed out waiting on ${striptracks_type^} job ID $striptracks_jobid. Last status was: $(echo $striptracks_result | jq -crM .status)" + striptracks_exitstatus=18 + ;; + 10) striptracks_message="Error|${striptracks_type^} job ID $striptracks_jobid returned a curl error." + striptracks_exitstatus=17 + ;; + esac + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + end_script + } + + # Get new video file id + if get_video_info; then + striptracks_videofile_id="$(echo $striptracks_result | jq -crM .${striptracks_json_quality_root}.id)" + [ $striptracks_debug -ge 1 ] && echo "Debug|Set new video file id '$striptracks_videofile_id'." | log + # Get new video file info + if get_videofile_info; then + striptracks_videofile_info="$striptracks_result" + # Check that the file didn't get lost in the Rescan. + # TODO: Also losing releaseGroup + # TODO: In Radarr, losing customFormats and customFormatScore + # If we lost the quality information, put it back + if [ "$(echo $striptracks_videofile_info | jq -crM .quality.quality.name)" != "$(echo $striptracks_original_quality | jq -crM .quality.name)" ]; then + set_quality + # Check that the returned result shows the update + if [ "$(echo $striptracks_result | jq -crM .[].quality.quality.name)" = "$(echo $striptracks_original_quality | jq -crM .quality.name)" ]; then + # Updated successfully + [ $striptracks_debug -ge 1 ] && echo "Debug|Successfully updated quality to '$(echo $striptracks_result | jq -crM .[].quality.quality.name)'." | log else - # 'hasFile' is False in returned JSON. - striptracks_message="Warn|The '$striptracks_video_api' API with id $striptracks_video_id returned a false 'hasFile' (Normal with Radarr on try #1)." + striptracks_message="Warn|Unable to update ${striptracks_type^} $striptracks_video_api '$striptracks_title' to quality '$(echo $striptracks_original_quality | jq -crM .quality.name)'" echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=17 fi else - # Timeout or failure - striptracks_message="Warn|${striptracks_type^} job ID $striptracks_jobid timed out or failed." + # The quality is already correct + [ $striptracks_debug -ge 1 ] && echo "Debug|Quality of '$(echo $striptracks_original_quality | jq -crM .quality.name)' remained unchanged." | log + fi + + # Check the languages returned + # If we stripped out other languages, remove them from Radarr + # Only works in Radarr (no per-episode edit function in Sonarr) + if get_mediainfo "$striptracks_newvideo"; then + # Build array of full name languages + striptracks_newvideo_langcodes="$(echo $striptracks_json | jq -crM '.tracks[] | select(.type == "audio") | .properties.language')" + unset striptracks_newvideo_languages + for i in $striptracks_newvideo_langcodes; do + striptracks_newvideo_languages+="$(echo $striptracks_isocodemap | jq -crM ".languages[] | .language | select((.\"iso639-2\"[]) == \"$i\") | select(.name != \"Any\" and .name != \"Original\").name")" + done + if [ -n "$striptracks_newvideo_languages" ]; then + # Covert to standard JSON + striptracks_json_languages="$(echo $striptracks_lang_codes | jq -crM "map(select(.name | inside(\"$striptracks_newvideo_languages\")) | {id, name})")" + # Check languages for Radarr + if [ "$(echo $striptracks_videofile_info | jq -crM .languages)" != "null" ]; then + if [ "$(echo $striptracks_videofile_info | jq -crM ".languages")" != "$striptracks_json_languages" ]; then + if set_radarr_language; then + striptracks_exitstatus=0 + else + striptracks_message="Error|${striptracks_type^} error when updating video language(s)." + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=17 + fi + else + # The languages are already correct + [ $striptracks_debug -ge 1 ] && echo "Debug|Language(s) '$(echo $striptracks_json_languages | jq -crM "[.[].name] | join(\",\")")' remained unchanged." | log + fi + # Check languages for Sonarr + elif [ "$(echo $striptracks_videofile_info | jq -crM .language)" != "null" ]; then + if [ "$(echo $striptracks_videofile_info | jq -crM ".language")" != "$(echo $striptracks_json_languages | jq -crM ".[0]")" ]; then + if set_sonarr_language; then + striptracks_exitstatus=0 + else + striptracks_message="Error|${striptracks_type^} error when updating video language(s)." + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=17 + fi + else + # The languages are already correct + [ $striptracks_debug -ge 1 ] && echo "Debug|Language '$(echo $striptracks_json_languages | jq -crM ".[0].name")' remained unchanged." | log + fi + else + # Some unknown JSON formatting + striptracks_message="Warn|The '$striptracks_videofile_api' API returned unknown JSON language node." + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=20 + fi + else + # Video language not in striptracks_isocodemap + striptracks_message="Warn|Video language code(s) '${striptracks_newvideo_langcodes//$'\n'/,}' not found in the ISO Codemap. Cannot evaluate." + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=20 + fi + else + # Get media info failed + striptracks_message="Error|Could not get media info from new video file. Can't check resulting languages." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=9 + fi + # Get list of videos that could be renamed + get_rename + striptracks_return=$?; [ $striptracks_return -ne 0 ] && { + striptracks_message="Warn|[$striptracks_return] ${striptracks_type^} error when getting list of videos to rename." + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=17 + } + # Check if new video is in list of files that can be renamed + if [ -n "$striptracks_result" -a "$striptracks_result" != "[]" ]; then + striptracks_renamedvideo="$(echo $striptracks_result | jq -crM ".[] | select(.${striptracks_json_quality_root}Id == $striptracks_videofile_id) | .newPath")" + # Rename video if needed + if [ -n "$striptracks_renamedvideo" ]; then + rename_video + striptracks_return=$?; [ $striptracks_return -ne 0 ] && { + striptracks_message="Error|[$striptracks_return] ${striptracks_type^} error when renaming \"$(basename "$striptracks_newvideo")\" to \"$(basename "$striptracks_renamedvideo")\"" + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=17 + } + fi fi else - # Error from API - striptracks_message="Error|The '$striptracks_rescan_api' API with $striptracks_json_key $striptracks_video_id failed." + # No '.path' in returned JSON + striptracks_message="Warn|The '$striptracks_videofile_api' API with ${striptracks_video_api}File id $striptracks_videofile_id returned no path." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=17 fi - done + else + # 'hasFile' is False in returned JSON + striptracks_message="Warn|The '$striptracks_video_api' API with id $striptracks_video_id returned a false 'hasFile'." + echo "$striptracks_message" | log + echo "$striptracks_message" >&2 + striptracks_exitstatus=17 + fi + # else + # striptracks_message="Error|${striptracks_type^} error getting import file list in \"$striptracks_video_folder\" for $striptracks_video_type ID $striptracks_rescan_id. Cannot import remuxed video." + # echo "$striptracks_message" | log + # echo "$striptracks_message" >&2 + # striptracks_exitstatus=17 + # fi else - # No '.path' in returned JSON - striptracks_message="Warn|The '$striptracks_videofile_api' API with ${striptracks_video_api}File id $striptracks_videofile_id returned no path." + # Error from rescan API + striptracks_message="Error|The '$striptracks_rescan_api' API with ${striptracks_video_type}Id $striptracks_rescan_id failed." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=17 fi else # No video ID means we can't call the API - striptracks_message="Warn|Missing or empty environment variable: striptracks_video_id='$striptracks_video_id' or striptracks_videofile_id='$striptracks_videofile_id'" + striptracks_message="Warn|Missing or empty environment variable: striptracks_video_id='$striptracks_video_id' or striptracks_videofile_id='$striptracks_videofile_id'. Cannot rescan for remuxed video." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=20 fi else # No URL means we can't call the API striptracks_message="Warn|Unable to determine ${striptracks_type^} API URL." echo "$striptracks_message" | log echo "$striptracks_message" >&2 + striptracks_exitstatus=20 fi -# Cool bash feature -striptracks_message="Info|Completed in $(($SECONDS/60))m $(($SECONDS%60))s" -echo "$striptracks_message" | log +end_script \ No newline at end of file