use axum::extract::{Path, State};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::routing::{delete, get, post};
use axum::{Json, Router};
use serde::Deserialize;
use serde_json::json;
use crate::state::AppState;
use super::helpers::{rpc_ok, rpc_no_content};
pub fn routes() -> Router<AppState> {
Router::new()
.route("/v1/qrcodelink", get(qrcodelink))
.route("/v1/qrcodelink/raw", get(qrcodelink_raw))
.route("/v1/devices/{number}", post(link_device).get(list_devices))
.route("/v1/devices/{number}/{device_id}", delete(remove_device))
.route(
"/v1/devices/{number}/local-data",
delete(delete_local_data),
)
}
#[derive(Deserialize)]
struct QrLinkQuery {
#[serde(default)]
device_name: Option<String>,
}
async fn qrcodelink(
axum::extract::Query(query): axum::extract::Query<QrLinkQuery>,
State(st): State<AppState>,
) -> Response {
let mut params = json!({});
if let Some(name) = query.device_name {
params["deviceName"] = json!(name);
}
rpc_ok(&st, "startLink", params).await
}
async fn qrcodelink_raw(
axum::extract::Query(query): axum::extract::Query<QrLinkQuery>,
State(st): State<AppState>,
) -> Response {
let mut params = json!({});
if let Some(name) = query.device_name {
params["deviceName"] = json!(name);
}
match st.rpc("startLink", params).await {
Ok(result) => {
let uri = result
.as_str()
.or_else(|| result.get("deviceLinkUri").and_then(|v| v.as_str()))
.unwrap_or("");
(StatusCode::OK, uri.to_string()).into_response()
}
Err(e) => {
let status = crate::state::rpc_error_status(&e);
(status, Json(json!({ "error": e }))).into_response()
}
}
}
#[derive(Deserialize)]
struct LinkDeviceBody {
uri: String,
#[serde(default)]
device_name: Option<String>,
}
async fn link_device(
Path(number): Path<String>,
State(st): State<AppState>,
Json(body): Json<LinkDeviceBody>,
) -> Response {
let mut params = json!({ "account": number, "uri": body.uri });
if let Some(name) = body.device_name {
params["deviceName"] = json!(name);
}
rpc_no_content(&st, "finishLink", params).await
}
async fn list_devices(Path(number): Path<String>, State(st): State<AppState>) -> Response {
rpc_ok(&st, "listDevices", json!({ "account": number })).await
}
async fn remove_device(
Path((number, device_id)): Path<(String, i64)>,
State(st): State<AppState>,
) -> Response {
rpc_no_content(&st, "removeDevice", json!({ "account": number, "deviceId": device_id })).await
}
async fn delete_local_data(Path(number): Path<String>, State(st): State<AppState>) -> Response {
rpc_no_content(&st, "deleteLocalAccountData", json!({ "account": number })).await
}