wsb-daemon 0.248.6265

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
use wsb::prelude::*;
use axum::{
    extract::{Path, State},
    http::StatusCode,
    Json,
};

use super::sessions::ErrorResponse;
use crate::web::machine_web::MachineWeb;

pub async fn list_all_pins(
    State(state): State<MachineWeb>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
    let db = state.db.clone();

    let pins = tokio::task::spawn_blocking(move || db.list_all_pins())
        .await
        .unwrap_or_else(|e| Err(anyhow::anyhow!("join error: {}", e)))
        .map_err(|e| {
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ErrorResponse {
                    error: e.to_string(),
                }),
            )
        })?;
    Ok(Json(serde_json::json!({ "pins": pins })))
}

pub async fn list_session_pins(
    State(state): State<MachineWeb>,
    Path(id): Path<String>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
    let db = state.db.clone();
    let id_clone = id.clone();

    let pins = tokio::task::spawn_blocking(move || db.list_session_pins(&id_clone))
        .await
        .unwrap_or_else(|e| Err(anyhow::anyhow!("join error: {}", e)))
        .map_err(|e| {
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ErrorResponse {
                    error: e.to_string(),
                }),
            )
        })?;
    Ok(Json(serde_json::json!({ "pins": pins })))
}

#[derive(Deserialize)]
pub struct PinRequest {
    pub note: Option<String>,
}

pub async fn pin_message(
    State(state): State<MachineWeb>,
    Path((session_id, message_id)): Path<(String, i64)>,
    Json(body): Json<PinRequest>,
) -> Result<(StatusCode, Json<serde_json::Value>), (StatusCode, Json<ErrorResponse>)> {
    let db = state.db.clone();

    let pin_id = tokio::task::spawn_blocking({
        let session_id = session_id.clone();
        move || {
            db.pin_message(&session_id, message_id, body.note.as_deref())
        }
    })
    .await
    .unwrap_or_else(|e| Err(anyhow::anyhow!("join error: {}", e)))
    .map_err(|e| {
        (
            StatusCode::BAD_REQUEST,
            Json(ErrorResponse {
                error: e.to_string(),
            }),
        )
    })?;

    Ok((
        StatusCode::CREATED,
        Json(serde_json::json!({ "id": pin_id })),
    ))
}

pub async fn unpin_message(
    State(state): State<MachineWeb>,
    Path((session_id, message_id)): Path<(String, i64)>,
) -> Result<StatusCode, (StatusCode, Json<ErrorResponse>)> {
    let db = state.db.clone();

    tokio::task::spawn_blocking({
        let session_id = session_id.clone();
        move || db.unpin_message(&session_id, message_id)
    })
    .await
    .unwrap_or_else(|e| Err(anyhow::anyhow!("join error: {}", e)))
    .map_err(|e| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: e.to_string(),
            }),
        )
    })?;
    Ok(StatusCode::NO_CONTENT)
}