Repair playlists
This commit is contained in:
parent
6b5c291cb7
commit
3f645d1011
4 changed files with 57 additions and 46 deletions
|
@ -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());
|
||||
|
||||
|
|
|
@ -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,25 +36,17 @@ 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()))
|
||||
{
|
||||
new_songs.push(PlaylistSong {
|
||||
path: real_path,
|
||||
ordering: i as i64,
|
||||
});
|
||||
}
|
||||
for (i, virtual_path) in content.iter().enumerate() {
|
||||
new_songs.push(PlaylistSong {
|
||||
virtual_path: virtual_path.to_string_lossy().to_string(),
|
||||
ordering: i as i64,
|
||||
});
|
||||
}
|
||||
|
||||
let mut connection = self.db.connect().await?;
|
||||
|
@ -93,15 +84,17 @@ impl Manager {
|
|||
.await?;
|
||||
|
||||
for chunk in new_songs.chunks(10_000) {
|
||||
QueryBuilder::<Sqlite>::new("INSERT INTO playlist_songs (playlist, path, ordering) ")
|
||||
.push_values(chunk, |mut b, song| {
|
||||
b.push_bind(playlist_id)
|
||||
.push_bind(&song.path)
|
||||
.push_bind(song.ordering);
|
||||
})
|
||||
.build()
|
||||
.execute(connection.as_mut())
|
||||
.await?;
|
||||
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.virtual_path)
|
||||
.push_bind(song.ordering);
|
||||
})
|
||||
.build()
|
||||
.execute(connection.as_mut())
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue