3 f
=/usr
/local
/lib
/err
;test -r $f ||
{ echo "error: $0 no $f" >&2;exit 1;}; .
$f
21 printf "%s\n" "$*" >&2
22 if $dry_run && [[ $1 == beet
&& $2 == modify
]]; then
32 if ! $plist_only; then
33 echo begin star rating import from navidrome to beets
38 if [[ $HOSTNAME != kd
]]; then
39 ssh_prefix
="ssh b8.nz"
41 install -m 700 -d /tmp/nav2beet
42 for r in 1 2 3 4 5; do
43 sqlite3 /i/navidrome/navidrome.db ".output /tmp/nav2beet/$r" "select path from annotation inner join media_file on item_id = id where rating = $r;"
45 tar cz -C /tmp nav2beet
49 for r
in 1 2 3 4 5; do
50 sqlite3
/i
/navidrome
/navidrome.db
".output $r" "select path from annotation inner join media_file on item_id = id where rating = $r;"
55 # todo: consider if this is a problem: file removed/renamed in main
56 # collection, but not yet updated navidrome, we want to skip it not
61 done < <($ssh_prefix find /i
/m
-type f
-name '*.flac')
62 for r
in 1 2 3 4 5; do
63 while read -r path
; do
64 beetpath
="/i/m${path#/i/converted}"
65 flac
="${beetpath%.mp3}.flac"
66 if [[ ${flacs[$flac]} ]]; then
69 navirating
[$beetpath]=$r
75 for r
in 1 2 3 4 5; do
76 m beet
ls -f '$path' rating
:$r >$tmpf
77 while read -r path
; do
82 for path
in "${!navirating[@]}"; do
83 r
="${navirating[$path]}"
84 if [[ $r != "${beetrating[$path]}" ]]; then
85 # note: this assumes there are no cases like filea.mp3 filea.mp3.mp3, which would affect both files.
86 echo "$r != ${beetrating[$path]}, beet modify -y path:$path rating=$r"
87 beet modify
-y "path:$path" "rating=$r"
90 # end star rating import from navidrome to beets:
93 echo begin import navidrome playlists as flexible attribute with value t.
94 # These are only the playlists listed in the beets config.yaml
95 # "subsonicplaylist:" and then duplicated here:
99 # these are useful tags
103 # these are normal playlists
110 # this puts the navidrome playlists into a smart attribute
112 m beet subsonicplaylist
114 beet
ls -f '$id $subsonic_playlist' subsonic_playlist
::. |
sed 's/;/ /g' >$tmpf
120 while read -r id id_plists
; do
121 navlists
[id
]="$id_plists"
124 for plist
in ${plists[@]}; do
125 echo "processing $plist"
126 for id
in $
(beet
ls -f '$id' $plist:t ^genre
:spoken-w ^genre
:skit ^rating
:1); do
129 for navlist
in ${navlists[id]}; do
130 if [[ $navlist == "$plist" ]]; then
133 newnavlist
+=($navlist)
137 navlists
[id
]="${newnavlist[*]}"
139 # exists in beets, but not navidrome so we must have removed
140 # it from the playlist in navidrome.
141 m beet modify
-y "id:$id" "$plist!"
145 # The ones we didnt find and remove are ones we added
147 for id
in ${!navlists[@]}; do
148 [[ ${navlists[id]} ]] ||
continue
149 m beet modify
-y "id:$id" ${navlists[id]// /=t }=t
152 # old way of doing it which sets everything. this doesnt
153 # account for removed tracks in navidrome, and it will
154 # be slower for handling many playlists.
155 # while read -r id plists; do
156 # plists="${plists#;}"
157 # m beet modify -y "id:$id" ${plists//;/=t }
158 # done < <(beet ls -f '$id $subsonic_playlist' subsonic_playlist::.)
160 # if we remove a track from a playlist in navidrome,
161 # beet subsonicplaylist won't remove corresponding beet
162 # smart attribute, so clear them all here.
164 m beet modify
-y subsonic_playlist
::.
'subsonic_playlist!'