use actix_session::Session; use actix_web::{HttpResponse, web}; use serde::Deserialize; use shanty_db::queries; use crate::auth; use crate::error::ApiError; use crate::state::AppState; fn default_limit() -> u64 { 50 } #[derive(Deserialize)] pub struct SearchParams { q: Option, #[serde(default = "default_limit")] limit: u64, #[serde(default)] offset: u64, } #[derive(Deserialize)] pub struct WatchTrackRequest { artist: Option, title: Option, mbid: Option, } pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service( web::resource("/tracks/watch") .route(web::post().to(watch_track)) .route(web::delete().to(unwatch_track)), ) .service(web::resource("/tracks").route(web::get().to(list_tracks))) .service(web::resource("/tracks/{id}").route(web::get().to(get_track))); } async fn list_tracks( state: web::Data, session: Session, query: web::Query, ) -> Result { auth::require_auth(&session)?; let tracks = if let Some(ref q) = query.q { queries::tracks::search(state.db.conn(), q).await? } else { queries::tracks::list(state.db.conn(), query.limit, query.offset).await? }; Ok(HttpResponse::Ok().json(tracks)) } async fn get_track( state: web::Data, session: Session, path: web::Path, ) -> Result { auth::require_auth(&session)?; let id = path.into_inner(); let track = queries::tracks::get_by_id(state.db.conn(), id).await?; Ok(HttpResponse::Ok().json(track)) } async fn watch_track( state: web::Data, session: Session, body: web::Json, ) -> Result { let (user_id, _, _) = auth::require_auth(&session)?; if body.title.is_none() && body.mbid.is_none() { return Err(ApiError::BadRequest( "provide title or recording mbid".into(), )); } let entry = shanty_watch::add_track( state.db.conn(), body.artist.as_deref(), body.title.as_deref(), body.mbid.as_deref(), &state.mb_client, Some(user_id), ) .await?; Ok(HttpResponse::Ok().json(serde_json::json!({ "id": entry.id, "status": entry.status, "name": entry.name, "artist_name": entry.artist_name, }))) } async fn unwatch_track( state: web::Data, session: Session, body: web::Json, ) -> Result { auth::require_auth(&session)?; let mbid = body .mbid .as_deref() .ok_or_else(|| ApiError::BadRequest("provide recording mbid".into()))?; let removed = queries::wanted::remove_by_mbid(state.db.conn(), mbid).await?; Ok(HttpResponse::Ok().json(serde_json::json!({"removed": removed}))) }