tank-sort.nix (3439B)
1 { pkgs, vars, ... }: 2 3 let 4 media-sort = pkgs.callPackage ../common/media-sort.nix {}; 5 6 tank-sort = pkgs.writeShellScriptBin "tank-sort" '' 7 set -euo pipefail # Exit on any error 8 9 # variables 10 export PATH=/run/wrappers/bin:/run/current-system/sw/bin:$PATH 11 temp_mount="$(mktemp -d)" 12 rclone_remote="seedbox:" 13 extensions="mp4,m4v,mkv" 14 state_file="$HOME/.cache/tank-sort.cache" 15 destination_tvshows="/tank/media/videos/television" 16 template_tvshows="{{ .Name }}/{{ .Name }} S{{ printf \"%02d\" .Season }}E{{ printf \"%02d\" .Episode }}{{ if ne .ExtraEpisode -1 }}-{{ printf \"%02d\" .ExtraEpisode }}{{end}}.{{ .Ext }}" 17 destination_movies="/tank/media/videos/movies" 18 template_movies="{{ .Name }} ({{ .Year }})/{{ .Name }}.{{ .Ext }}" 19 20 # Cleanup function 21 cleanup() { 22 echo "Cleaning up..." 23 if [ -n "''${RCLONE_PID:-}" ]; then 24 kill "$RCLONE_PID" 2>/dev/null || tru 25 wait "$RCLONE_PID" 2>/dev/null || true 26 fi 27 if mountpoint -q "$temp_mount" 2>/dev/null; then 28 fusermount -uz "$temp_mount" 2>/dev/null || true 29 fi 30 if [ -d "$temp_mount" ]; then 31 rmdir "$temp_mount" 2>/dev/null || true 32 fi 33 } 34 trap cleanup EXIT 35 36 # check for changes on remote 37 current_hash="$(${pkgs.rclone}/bin/rclone --config /home/${vars.user.username}/.config/rclone/rclone.conf lsjson "$rclone_remote" \ 38 --include "*.{''${extensions}}" \ 39 | ${pkgs.jq}/bin/jq -S '.[] | {Path, Size, ModTime}' \ 40 | sort \ 41 | sha256sum | cut -d' ' -f1)" 42 if [ -f "$state_file" ]; then 43 previous_hash="$(cat "$state_file")" 44 else 45 previous_hash="" 46 fi 47 48 if [ "$current_hash" = "$previous_hash" ]; then 49 echo "No changes detected in remote. Exiting." 50 exit 0 51 fi 52 53 echo "Changes detected. Proceeding..." 54 55 # mount remote 56 echo "Mounting rclone remote..." 57 ${pkgs.rclone}/bin/rclone mount "$rclone_remote" "$temp_mount" --vfs-cache-mode writes & 58 ${pkgs.rclone}/bin/rclone mount \ 59 "$rclone_remote" \ 60 "$temp_mount" \ 61 --vfs-cache-mode writes & 62 RCLONE_PID=$! 63 64 # Wait for mount to be ready 65 echo "Waiting for mount to be ready..." 66 mounted=0 67 for i in {1..30}; do 68 if mountpoint -q "$temp_mount"; then 69 mounted=1 70 break 71 fi 72 sleep 1 73 done 74 if [ "$mounted" -eq 0 ]; then 75 echo "ERROR: rclone mount never became available" 76 exit 1 77 fi 78 79 # sorting process 80 echo "Starting media sort..." 81 ${media-sort}/bin/media-sort \ 82 --action copy \ 83 --concurrency 1 \ 84 --accuracy-threshold 90 \ 85 --tv-dir "$destination_tvshows" \ 86 --movie-dir "$destination_movies" \ 87 --tv-template "$template_tvshows" \ 88 --movie-template "$template_movies" \ 89 --recursive \ 90 --overwrite-if-larger \ 91 --extensions "$extensions" \ 92 "$temp_mount" 93 94 # update state file 95 echo "$current_hash" > "$state_file" 96 97 # git tank logger 98 tank-log 99 100 echo "Media sort completed successfully" 101 ''; 102 in { 103 environment.systemPackages = [ tank-sort media-sort ]; 104 105 systemd.services.tank-sort = { 106 description = "Sort media from rclone remote"; 107 serviceConfig = { 108 Type = "oneshot"; 109 User = vars.user.username; 110 ExecStart = "${tank-sort}/bin/tank-sort"; 111 Environment = [ 112 "PATH=/run/wrappers/bin:/run/current-system/sw/bin" 113 "HOME=/home/${vars.user.username}" 114 ]; 115 }; 116 }; 117 118 systemd.timers.tank-sort = { 119 description = "Run tank-sort every 4 hours"; 120 wantedBy = [ "timers.target" ]; 121 timerConfig = { 122 OnCalendar = "*-*-* 00/4:00:00"; 123 Persistent = true; 124 }; 125 }; 126 }