playlistfile(path) = joinpath(path, "playlists.jsonl") function saveplaylists(; file = playlistfile(Beets.confdir())) global user_playlists open(file, "w") do f write(f, join(JSON2.write.(user_playlists), "\n")) end end function loadplaylists(; file = playlistfile(Beets.confdir())) global user_playlists isfile(file) || touch(file) ps = JSON2.readlines(file) empty!(user_playlists) for p in ps try pl = JSON2.read(p, Playlist) # TODO: Control verbosity @info "Importing playlist ($(pl.owner)) $(convert(String, pl.uuid)), with $(length(pl.songs)) songs in it" # Check if song uuid exits, else skip it (and emit a warning) filteredsongs = filter(x -> Beets.songbyid(x) !== nothing, pl.songs) if length(filteredsongs) != length(pl.songs) pl.songs = filteredsongs @warn "Failed to import some playlist's song" end push!(user_playlists, pl) catch e @warn "Failed to read with error $e" isa(e, ArgumentError) && continue end end end beetfile(f) = expanduser("~/.config/beets/$f") function saveusers(file = beetfile("users.jsonl")) global users open(file, "w") do f write(f, join(JSON2.write.(users), "\n")) end end function loadusers(; file = beetfile("users.jsonl")) global users isfile(file) || touch(file) ps = JSON2.readlines(file) p = JSON2.read.(ps, JlSonic.User) empty!(users) for pl in p push!(users, pl) end end function saveratings(; file = beetfile("ratings.json")) global user_ratings open(file, "w") do f write(f, JSON2.write(user_ratings)) end end function savestarred(; file = beetfile("starred.json")) global user_stars open(file, "w") do f write(f, JSON2.write(user_stars)) end end function loadratings(; file = beetfile("ratings.json")) global user_ratings isfile(file) || begin touch(file); return end content = read(file, String) isempty(content) && return file user_ratings = JSON2.read(content, typeof(user_ratings)) end function loadstarred(; file = beetfile("starred.json")) global user_stars isfile(file) || begin touch(file); return end content = read(file, String) isempty(content) && return user_stars user_stars = JSON2.read(content, typeof(user_stars)) end function config_create(; cover_px_size = 250, disk_cache_size = 5 * 1024 * 1024, memory_cache_size = 1 * 1024 * 1024, ) return Dict(:cover => Dict(:size => cover_px_size), :cache => Dict( :disk => Dict( :size => disk_cache_size, ), :memory => Dict( :size => memory_cache_size, ) )) end # TODO: those functions are perfect for a macro function saveshared(; file = beetfile("shared.json")) global shared open(file, "w") do f write(f, JSON2.write(shared)) end end function loadshared(; file = beetfile("shared.json")) global shared isfile(file) || return content = read(file, String) empty!(shared) push!.(shared, JSON2.read(content, typeof(shared))) end