Fixed ytdl retries
Build and Publish / Build and Publish Docker Image (push) Successful in 3m40s

This commit is contained in:
Ultradesu
2026-08-14 12:56:03 +01:00
parent 0b32d7e813
commit 1ab53e3898
8 changed files with 805 additions and 129 deletions
+28 -13
View File
@@ -1069,19 +1069,34 @@ impl App for AdminApp {
),
"admin_releases_edit",
),
Route::with_handler_and_name(
"/releases/{id}/delete",
cot::router::method::post(
|session: Session, db: Database, path: Path<PathId>| async move {
let admin = match auth::require_admin_or_redirect(&session, &db).await {
Ok(u) => u,
Err(resp) => return Ok(resp),
};
views::releases_delete(admin, &db, path.0.id).await
},
),
"admin_releases_delete",
),
{
let pool = Arc::clone(&pool);
let pool_config = Arc::clone(&pool_config);
Route::with_handler_and_name(
"/releases/{id}/delete",
cot::router::method::post(move |session: Session, db: Database, path: Path<PathId>| {
let pool = Arc::clone(&pool);
let pool_config = Arc::clone(&pool_config);
async move {
let admin = match auth::require_admin_or_redirect(&session, &db).await {
Ok(u) => u,
Err(resp) => return Ok(resp),
};
let pg_pool = pool
.get_or_init(|| async {
sqlx::postgres::PgPoolOptions::new()
.max_connections(5)
.connect(&pool_config.database_url)
.await
.expect("admin pool")
})
.await;
views::releases_delete(admin, &db, pg_pool, path.0.id).await
}
}),
"admin_releases_delete",
)
},
// -- Media Files --------------------------------------------------
Route::with_handler_and_name(
"/media-files",
+22 -90
View File
@@ -2066,7 +2066,12 @@ pub async fn bulk_library(
.into_response();
}
let affected = apply_library_action(pool, &kind, action, &ids).await?;
let storage_dir = if action == "delete" && matches!(kind.as_str(), "releases" | "tracks") {
AppConfig::load_with_db(&db).await.0.agent_storage_dir
} else {
String::new()
};
let affected = apply_library_action(pool, &kind, action, &ids, &storage_dir).await?;
Json(MutationResponse { ok: true, affected }).into_response()
}
@@ -3620,10 +3625,11 @@ async fn apply_library_action(
kind: &str,
action: &str,
ids: &[i64],
storage_dir: &str,
) -> cot::Result<u64> {
match action {
"hide" | "show" => set_library_visibility(pool, kind, ids, action == "hide").await,
"delete" => delete_library_items(pool, kind, ids).await,
"delete" => delete_library_items(pool, kind, ids, storage_dir).await,
_ => Ok(0),
}
}
@@ -3674,10 +3680,15 @@ async fn set_library_visibility(
Ok(result.rows_affected())
}
async fn delete_library_items(pool: &PgPool, kind: &str, ids: &[i64]) -> cot::Result<u64> {
async fn delete_library_items(
pool: &PgPool,
kind: &str,
ids: &[i64],
storage_dir: &str,
) -> cot::Result<u64> {
match kind {
"releases" => delete_releases(pool, ids).await,
"tracks" => delete_tracks(pool, ids).await,
"releases" => delete_releases(pool, ids, storage_dir).await,
"tracks" => delete_tracks(pool, ids, storage_dir).await,
"playlists" => delete_playlists(pool, ids).await,
_ => delete_artists(pool, ids).await,
}
@@ -3707,95 +3718,16 @@ async fn delete_artists(pool: &PgPool, ids: &[i64]) -> cot::Result<u64> {
Ok(result.rows_affected())
}
async fn delete_releases(pool: &PgPool, ids: &[i64]) -> cot::Result<u64> {
let track_ids =
sqlx::query_as::<_, IdRow>("SELECT id FROM furumusic__track WHERE release_id = ANY($1)")
.bind(ids)
.fetch_all(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?
.into_iter()
.map(|row| row.id)
.collect::<Vec<_>>();
if !track_ids.is_empty() {
sqlx::query("DELETE FROM furumusic__playlist_track WHERE track_id = ANY($1)")
.bind(&track_ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__user_liked_track WHERE track_id = ANY($1)")
.bind(&track_ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__play_history WHERE track_id = ANY($1)")
.bind(&track_ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__track_genre WHERE track_id = ANY($1)")
.bind(&track_ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__track_artist WHERE track_id = ANY($1)")
.bind(&track_ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
}
sqlx::query("DELETE FROM furumusic__track WHERE release_id = ANY($1)")
.bind(ids)
.execute(pool)
async fn delete_releases(pool: &PgPool, ids: &[i64], storage_dir: &str) -> cot::Result<u64> {
crate::library_cleanup::delete_releases(pool, ids, storage_dir)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__release_artist WHERE release_id = ANY($1)")
.bind(ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
let result = sqlx::query("DELETE FROM furumusic__release WHERE id = ANY($1)")
.bind(ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
Ok(result.rows_affected())
.map_err(|error| cot::Error::internal(error.to_string()))
}
async fn delete_tracks(pool: &PgPool, ids: &[i64]) -> cot::Result<u64> {
sqlx::query("DELETE FROM furumusic__playlist_track WHERE track_id = ANY($1)")
.bind(ids)
.execute(pool)
async fn delete_tracks(pool: &PgPool, ids: &[i64], storage_dir: &str) -> cot::Result<u64> {
crate::library_cleanup::delete_tracks(pool, ids, storage_dir)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__user_liked_track WHERE track_id = ANY($1)")
.bind(ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__play_history WHERE track_id = ANY($1)")
.bind(ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__track_genre WHERE track_id = ANY($1)")
.bind(ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
sqlx::query("DELETE FROM furumusic__track_artist WHERE track_id = ANY($1)")
.bind(ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
let result = sqlx::query("DELETE FROM furumusic__track WHERE id = ANY($1)")
.bind(ids)
.execute(pool)
.await
.map_err(|e| cot::Error::internal(e.to_string()))?;
Ok(result.rows_affected())
.map_err(|error| cot::Error::internal(error.to_string()))
}
async fn delete_playlists(pool: &PgPool, ids: &[i64]) -> cot::Result<u64> {
+3 -1
View File
@@ -1262,9 +1262,11 @@ pub async fn releases_update(
pub async fn releases_delete(
_admin: AuthenticatedUser,
db: &Database,
pool: &sqlx::PgPool,
release_id: i64,
) -> cot::Result<cot::http::Response<Body>> {
Release::delete_by_id(db, release_id)
let (config, _) = AppConfig::load_with_db(db).await;
crate::library_cleanup::delete_releases(pool, &[release_id], &config.agent_storage_dir)
.await
.map_err(|e| cot::Error::internal(format!("failed to delete release: {e}")))?;
Ok(auth::redirect("/admin/releases"))