Repair playlists

This commit is contained in:
Antoine Gersant 2024-08-09 17:40:59 -07:00
parent 6b5c291cb7
commit 3f645d1011
4 changed files with 57 additions and 46 deletions

View file

@ -170,7 +170,7 @@ impl App {
vfs_manager.clone(),
ddns_manager.clone(),
);
let playlist_manager = playlist::Manager::new(db.clone(), vfs_manager.clone());
let playlist_manager = playlist::Manager::new(db.clone());
let thumbnail_manager = thumbnail::Manager::new(thumbnails_dir_path);
let lastfm_manager = lastfm::Manager::new(index_manager.clone(), user_manager.clone());

View file

@ -2,18 +2,17 @@ use core::clone::Clone;
use sqlx::{Acquire, QueryBuilder, Sqlite};
use std::path::PathBuf;
use crate::app::{vfs, Error};
use crate::app::Error;
use crate::db::DB;
#[derive(Clone)]
pub struct Manager {
db: DB,
vfs_manager: vfs::Manager,
}
impl Manager {
pub fn new(db: DB, vfs_manager: vfs::Manager) -> Self {
Self { db, vfs_manager }
pub fn new(db: DB) -> Self {
Self { db }
}
pub async fn list_playlists(&self, owner: &str) -> Result<Vec<String>, Error> {
@ -37,26 +36,18 @@ impl Manager {
owner: &str,
content: &[PathBuf],
) -> Result<(), Error> {
let vfs = self.vfs_manager.get_vfs().await?;
struct PlaylistSong {
path: String,
virtual_path: String,
ordering: i64,
}
let mut new_songs: Vec<PlaylistSong> = Vec::with_capacity(content.len());
for (i, path) in content.iter().enumerate() {
if let Some(real_path) = vfs
.virtual_to_real(path)
.ok()
.and_then(|p| p.to_str().map(|s| s.to_owned()))
{
for (i, virtual_path) in content.iter().enumerate() {
new_songs.push(PlaylistSong {
path: real_path,
virtual_path: virtual_path.to_string_lossy().to_string(),
ordering: i as i64,
});
}
}
let mut connection = self.db.connect().await?;
@ -93,10 +84,12 @@ impl Manager {
.await?;
for chunk in new_songs.chunks(10_000) {
QueryBuilder::<Sqlite>::new("INSERT INTO playlist_songs (playlist, path, ordering) ")
QueryBuilder::<Sqlite>::new(
"INSERT INTO playlist_songs (playlist, virtual_path, ordering) ",
)
.push_values(chunk, |mut b, song| {
b.push_bind(playlist_id)
.push_bind(&song.path)
.push_bind(&song.virtual_path)
.push_bind(song.ordering);
})
.build()
@ -132,20 +125,20 @@ impl Manager {
.ok_or(Error::PlaylistNotFound)?;
// List songs
todo!();
// sqlx::query_as!(
// Song,
// r#"
// SELECT s.*
// FROM playlist_songs ps
// INNER JOIN songs s ON ps.virtual_path = s.virtual_path
// WHERE ps.playlist = $1
// ORDER BY ps.ordering
// "#,
// playlist_id
// )
// .fetch_all(connection.as_mut())
// .await?
sqlx::query_scalar!(
r#"
SELECT virtual_path
FROM playlist_songs ps
WHERE ps.playlist = $1
ORDER BY ps.ordering
"#,
playlist_id
)
.fetch_all(connection.as_mut())
.await?
.into_iter()
.map(PathBuf::from)
.collect()
};
Ok(songs)

View file

@ -73,7 +73,7 @@ impl ContextBuilder {
)
.await
.unwrap();
let playlist_manager = playlist::Manager::new(db.clone(), vfs_manager.clone());
let playlist_manager = playlist::Manager::new(db.clone());
config_manager.apply(&self.config).await.unwrap();

View file

@ -2,8 +2,8 @@ use std::path::Path;
use http::StatusCode;
use crate::server::dto;
use crate::server::test::protocol::V8;
use crate::server::dto::{self, SongList};
use crate::server::test::protocol::{V7, V8};
use crate::server::test::{constants::*, protocol, ServiceType, TestService};
use crate::test_name;
@ -85,7 +85,25 @@ async fn get_playlist_golden_path() {
}
let request = protocol::read_playlist::<V8>(TEST_PLAYLIST_NAME);
let response = service.fetch_json::<_, Vec<dto::Song>>(&request).await;
let response = service.fetch_json::<_, SongList>(&request).await;
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn get_playlist_golden_path_api_v7() {
let mut service = ServiceType::new(&test_name!()).await;
service.complete_initial_setup().await;
service.login().await;
{
let my_playlist = dto::SavePlaylistInput { tracks: Vec::new() };
let request = protocol::save_playlist(TEST_PLAYLIST_NAME, my_playlist);
let response = service.fetch(&request).await;
assert_eq!(response.status(), StatusCode::OK);
}
let request = protocol::read_playlist::<V7>(TEST_PLAYLIST_NAME);
let response = service.fetch_json::<_, Vec<dto::v7::Song>>(&request).await;
assert_eq!(response.status(), StatusCode::OK);
}