host info updates
[distro-setup] / nav2beet
1 #!/bin/bash
2 # I, Ian Kelling, follow the GNU license recommendations at
3 # https://www.gnu.org/licenses/license-recommendations.en.html. They
4 # recommend that small programs, < 300 lines, be licensed under the
5 # Apache License 2.0. This file contains or is part of one or more small
6 # programs. If a small program grows beyond 300 lines, I plan to switch
7 # its license to GPL.
8
9 # Copyright 2024 Ian Kelling
10
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
14
15 # http://www.apache.org/licenses/LICENSE-2.0
16
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
22
23
24 set -e; . /usr/local/lib/bash-bear; set +e
25
26 source /a/bin/ds/beet-data
27 source /b/bash_unpublished/source-semi-priv
28
29 declare -A genre_a
30 for g in ${all_genres[@]}; do
31 genre_a[$g]=t
32 done
33
34 # these options are mainly for debugging / developing quickly.
35 plist_only=false
36 dry_run=false
37 while (( $# )); do
38 case $1 in
39 plist)
40 plist_only=true
41 shift
42 ;;
43 dry)
44 dry_run=true
45 shift
46 ;;
47 *)
48 echo "error. unexpected arg read script"
49 exit 1
50 ;;
51 esac
52 done
53
54 m ()
55 {
56 printf "%s\n" "$*" >&2
57 if $dry_run; then
58 echo "dry run: $*"
59 else
60 "$@"
61 fi
62 }
63
64 tmpf=$(mktemp)
65
66 declare -A flacs
67
68 declare -A navirating
69 tmpdir=$(mktemp -d)
70 cd $tmpdir
71 # the code here is duplicated later for non ssh context.
72 if [[ $HOSTNAME != kd ]]; then
73
74 ssh b8.nz bash -s "$(md5sum </a/bin/ds/beet-data)" <<'EOF' | tar xz
75 if [[ $1 != "$(md5sum </a/bin/ds/beet-data)" ]]; then
76 echo error: old beet-data on kd
77 exit 1
78 fi
79 install -m 700 -d /tmp/nav2beet
80 cd /tmp/nav2beet
81 /a/bin/ds/nav2beet-local
82 tar cz -C /tmp nav2beet
83 EOF
84 cd nav2beet
85 else
86 /a/bin/ds/nav2beet-local
87 fi
88 while read -r l; do
89 flacs[$l]=t
90 done <flacs
91
92 if ! $plist_only; then
93 echo begin star rating import from navidrome to beets
94 for r in 1 2 3 4 5; do
95 while read -r path; do
96 beetpath="/i/m${path#/i/converted}"
97 flac="${beetpath%.mp3}.flac"
98 if [[ ${flacs[$flac]} ]]; then
99 beetpath="$flac"
100 fi
101 navirating[$beetpath]=$r
102 done <$r
103 done
104 declare -A beetrating
105 for r in 1 2 3 4 5; do
106 # shellcheck disable=SC2016 # expected beets arg
107 m beet ls -f '$path' rating:$r >$tmpf
108 while read -r path; do
109 beetrating[$path]=$r
110 done <$tmpf
111 done
112
113 for path in "${!navirating[@]}"; do
114 r="${navirating[$path]}"
115 if [[ ! "${beetrating[$path]}" ]]; then
116 if [[ -e $path ]]; then
117 echo "$0: ERROR: $path exists but we have no rating for it"
118 exit 1
119 else
120 echo "$0: WARNING: $path exists in navidrome but not beets"
121 continue
122 fi
123 fi
124 if [[ $r != "${beetrating[$path]}" ]]; then
125 echo "$r != ${beetrating[$path]}, beet modify -y path:$path rating=$r"
126 beet modify -y "path:$path" "rating=$r"
127 fi
128 done
129 # end star rating import from navidrome to beets:
130 fi
131
132 echo begin import navidrome playlists as flexible attribute with value t.
133
134 shopt -s nullglob
135 for path in 2genre/*/*; do
136 id="${path#*/}"
137 id="${id%/*}"
138 filename="${path##*/}"
139 tmp="${filename%%[^0-9-]*}"
140 genre="${filename#"$tmp"}"
141 if [[ ${genre_a[$genre]} ]]; then
142 is_genre=true
143 else
144 # Some playlists we create with random names to remind us to do something
145 # with these tracks later once we are at a computer.
146 is_genre=false
147 fi
148 while read -r path; do
149 flac="${path%.mp3}.flac"
150 if [[ ${flacs[$flac]} ]]; then
151 path="$flac"
152 fi
153 if $is_genre; then
154 m beet modify -y "path:$path" "genre=$genre"
155 else
156 m beet modify -y "path:$path" "$genre=t"
157 fi
158 done <"$path"
159 # how i figured this out:
160 # s tcpdump -i any -w /tmp/tcpdump port 4533
161 # then delete a test playlist in client.
162 # made some sense out of it with: http://www.subsonic.org/pages/api.jsp
163 # open file in wireshard, right click "Hypertext Transfer Protocol", copy, as printable text, put into file /tmp/headers
164 # /a/opt/h2c/h2c </tmp/headers
165 # change from https to http.
166 # then tested out removing stuff i suspected was not important,
167 # and added https and host so it would work remotely.
168 m curl --http1.1 --user "iank:$navidrome_pw" "https://b8.nz/rest/deletePlaylist.view?u=iank&s=sb219dvv7egnoe4i47k75cli0m&t=1c8f5575cd0fdf03deb971187c9c88b1&v=1.2.0&c=DSub&id=$id"
169 done
170
171
172 for plist in ${nav_tags[@]}; do
173 echo "processing $plist"
174 # shellcheck disable=SC2016 # expected beets arg
175 beet ls -f '$path' $plist:t $nav_convert_query | sort | sed 's,\.flac$,.mp3,'> p
176 while read -r path; do
177 flac="${path%.mp3}.flac"
178 if [[ ${flacs[$flac]} ]]; then
179 path="$flac"
180 fi
181 m beet modify -y "path:$path" "$plist!"
182 # files unique to tmpf are in beets not navidrome
183 done < <(comm -23 p $plist)
184 while read -r path; do
185 flac="${path%.mp3}.flac"
186 if [[ ${flacs[$flac]} ]]; then
187 path="$flac"
188 fi
189 m beet modify -y "path:$path" $plist=t
190 # files unique to plist are in navidrome not beets
191 done < <(comm -13 p $plist)
192
193 done
194
195 cd
196 rm -rf $tmpdir