feat: Rust commands - PersonInfo starred, faces data key, video temp file, +5 new commands
This commit is contained in:
@@ -27,6 +27,7 @@ struct FileInfo {
|
||||
struct PersonInfo {
|
||||
identity_uuid: String,
|
||||
name: String,
|
||||
starred: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -34,6 +35,8 @@ struct FaceInfo {
|
||||
id: i64,
|
||||
file_uuid: String,
|
||||
frame_number: i64,
|
||||
timestamp_secs: f64,
|
||||
face_id: Option<String>,
|
||||
confidence: f64,
|
||||
}
|
||||
|
||||
@@ -47,6 +50,27 @@ struct TraceInfo {
|
||||
frame_count: i64,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct FaceCandidate {
|
||||
id: i64,
|
||||
face_id: Option<String>,
|
||||
file_uuid: String,
|
||||
frame_number: i64,
|
||||
confidence: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SearchIdentityResult {
|
||||
identity_id: i64,
|
||||
name: String,
|
||||
source: String,
|
||||
tmdb_id: Option<i64>,
|
||||
file_uuid: Option<String>,
|
||||
start_time: f64,
|
||||
end_time: f64,
|
||||
text_content: Option<String>,
|
||||
}
|
||||
|
||||
const CORE_API: &str = "http://localhost:3002";
|
||||
const API_KEY: &str = "muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69";
|
||||
|
||||
@@ -133,9 +157,6 @@ async fn get_people(page: usize, per_page: usize) -> Result<Vec<PersonInfo>, Str
|
||||
let json: serde_json::Value = response.json().await.map_err(|e| format!("Parse failed: {}", e))?;
|
||||
eprintln!("[get_people] identities count: {}", json["identities"].as_array().map(|a| a.len()).unwrap_or(0));
|
||||
|
||||
let response = client.get(&url).send().await.map_err(|e| format!("Request failed: {}", e))?;
|
||||
let json: serde_json::Value = response.json().await.map_err(|e| format!("Parse failed: {}", e))?;
|
||||
|
||||
let people: Vec<PersonInfo> = json["identities"]
|
||||
.as_array()
|
||||
.unwrap_or(&vec![])
|
||||
@@ -144,6 +165,7 @@ async fn get_people(page: usize, per_page: usize) -> Result<Vec<PersonInfo>, Str
|
||||
Some(PersonInfo {
|
||||
identity_uuid: i["identity_uuid"].as_str()?.to_string(),
|
||||
name: i["name"].as_str()?.to_string(),
|
||||
starred: i["metadata"]["starred"].as_bool().unwrap_or(false),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
@@ -160,7 +182,7 @@ async fn get_faces(uuid: String, per_page: usize) -> Result<Vec<FaceInfo>, Strin
|
||||
let response = client.get(&url).send().await.map_err(|e| format!("Request failed: {}", e))?;
|
||||
let json: serde_json::Value = response.json().await.map_err(|e| format!("Parse failed: {}", e))?;
|
||||
|
||||
let faces: Vec<FaceInfo> = json["faces"]
|
||||
let faces: Vec<FaceInfo> = json["data"]
|
||||
.as_array()
|
||||
.unwrap_or(&vec![])
|
||||
.iter()
|
||||
@@ -169,6 +191,8 @@ async fn get_faces(uuid: String, per_page: usize) -> Result<Vec<FaceInfo>, Strin
|
||||
id: f["id"].as_i64().unwrap_or(0),
|
||||
file_uuid: f["file_uuid"].as_str()?.to_string(),
|
||||
frame_number: f["frame_number"].as_i64().unwrap_or(0),
|
||||
timestamp_secs: f["timestamp_secs"].as_f64().unwrap_or(0.0),
|
||||
face_id: f["face_id"].as_str().map(|s| s.to_string()),
|
||||
confidence: f["confidence"].as_f64().unwrap_or(0.0),
|
||||
})
|
||||
})
|
||||
@@ -221,7 +245,13 @@ async fn get_video_stream(uuid: String, start_time: f64, end_time: f64) -> Resul
|
||||
.map_err(|e| format!("Video request failed: {}", e))?
|
||||
.bytes().await
|
||||
.map_err(|e| format!("Video read failed: {}", e))?;
|
||||
Ok(format!("data:video/mp4;base64,{}", STANDARD.encode(&bytes)))
|
||||
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let file_path = tmp_dir.join(format!("momentry_{}.mp4", uuid));
|
||||
std::fs::write(&file_path, &bytes)
|
||||
.map_err(|e| format!("Write temp file failed: {}", e))?;
|
||||
|
||||
Ok(format!("file://{}", file_path.display()))
|
||||
}
|
||||
|
||||
const PROFILE_DIRS: &[&str] = &[
|
||||
@@ -274,6 +304,98 @@ async fn delete_identity(uuid: String) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn search_identities(query: String, limit: usize) -> Result<Vec<SearchIdentityResult>, String> {
|
||||
let client = reqwest::Client::new();
|
||||
let url = format!("{}/api/v1/identities/search?api_key={}&q={}", CORE_API, API_KEY, query);
|
||||
let resp = client.get(&url).send().await.map_err(|e| format!("Request failed: {}", e))?;
|
||||
let json: serde_json::Value = resp.json().await.map_err(|e| format!("Parse failed: {}", e))?;
|
||||
let results: Vec<SearchIdentityResult> = json["results"]
|
||||
.as_array()
|
||||
.unwrap_or(&vec![])
|
||||
.iter()
|
||||
.take(limit)
|
||||
.filter_map(|r| {
|
||||
Some(SearchIdentityResult {
|
||||
identity_id: r["identity_id"].as_i64().unwrap_or(0),
|
||||
name: r["name"].as_str()?.to_string(),
|
||||
source: r["source"].as_str().unwrap_or("").to_string(),
|
||||
tmdb_id: r["tmdb_id"].as_i64(),
|
||||
file_uuid: r["file_uuid"].as_str().map(|s| s.to_string()),
|
||||
start_time: r["start_time"].as_f64().unwrap_or(0.0),
|
||||
end_time: r["end_time"].as_f64().unwrap_or(0.0),
|
||||
text_content: r["text_content"].as_str().map(|s| s.to_string()),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_face_candidates(page: usize, per_page: usize) -> Result<Vec<FaceCandidate>, String> {
|
||||
let client = reqwest::Client::new();
|
||||
let url = format!("{}/api/v1/faces/candidates?api_key={}&page={}&page_size={}", CORE_API, API_KEY, page, per_page);
|
||||
let resp = client.get(&url).send().await.map_err(|e| format!("Request failed: {}", e))?;
|
||||
let json: serde_json::Value = resp.json().await.map_err(|e| format!("Parse failed: {}", e))?;
|
||||
let candidates: Vec<FaceCandidate> = json["candidates"]
|
||||
.as_array()
|
||||
.unwrap_or(&vec![])
|
||||
.iter()
|
||||
.filter_map(|c| {
|
||||
Some(FaceCandidate {
|
||||
id: c["id"].as_i64().unwrap_or(0),
|
||||
face_id: c["face_id"].as_str().map(|s| s.to_string()),
|
||||
file_uuid: c["file_uuid"].as_str()?.to_string(),
|
||||
frame_number: c["frame_number"].as_i64().unwrap_or(0),
|
||||
confidence: c["confidence"].as_f64().unwrap_or(0.0),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok(candidates)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn merge_identities(uuid: String, into_uuid: String) -> Result<(), String> {
|
||||
let client = reqwest::Client::new();
|
||||
let url = format!("{}/api/v1/identity/{}/mergeinto?api_key={}", CORE_API, uuid, API_KEY);
|
||||
let resp = client.post(&url)
|
||||
.json(&serde_json::json!({"into_uuid": into_uuid}))
|
||||
.send().await
|
||||
.map_err(|e| format!("Request failed: {}", e))?;
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("Merge failed: {}", resp.status()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn bind_face(uuid: String, face_id: String, file_uuid: String) -> Result<(), String> {
|
||||
let client = reqwest::Client::new();
|
||||
let url = format!("{}/api/v1/identity/{}/bind?api_key={}", CORE_API, uuid, API_KEY);
|
||||
let resp = client.post(&url)
|
||||
.json(&serde_json::json!({"face_id": face_id, "file_uuid": file_uuid}))
|
||||
.send().await
|
||||
.map_err(|e| format!("Request failed: {}", e))?;
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("Bind failed: {}", resp.status()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn unbind_face(uuid: String, face_id: String, file_uuid: String) -> Result<(), String> {
|
||||
let client = reqwest::Client::new();
|
||||
let url = format!("{}/api/v1/identity/{}/unbind?api_key={}", CORE_API, uuid, API_KEY);
|
||||
let resp = client.post(&url)
|
||||
.json(&serde_json::json!({"face_id": face_id, "file_uuid": file_uuid}))
|
||||
.send().await
|
||||
.map_err(|e| format!("Request failed: {}", e))?;
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("Unbind failed: {}", resp.status()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
@@ -287,7 +409,12 @@ fn main() {
|
||||
get_video_stream,
|
||||
get_identity_profile,
|
||||
update_identity_name,
|
||||
delete_identity
|
||||
delete_identity,
|
||||
search_identities,
|
||||
get_face_candidates,
|
||||
merge_identities,
|
||||
bind_face,
|
||||
unbind_face
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
Reference in New Issue
Block a user