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 {
|
struct PersonInfo {
|
||||||
identity_uuid: String,
|
identity_uuid: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
starred: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@@ -34,6 +35,8 @@ struct FaceInfo {
|
|||||||
id: i64,
|
id: i64,
|
||||||
file_uuid: String,
|
file_uuid: String,
|
||||||
frame_number: i64,
|
frame_number: i64,
|
||||||
|
timestamp_secs: f64,
|
||||||
|
face_id: Option<String>,
|
||||||
confidence: f64,
|
confidence: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +50,27 @@ struct TraceInfo {
|
|||||||
frame_count: i64,
|
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 CORE_API: &str = "http://localhost:3002";
|
||||||
const API_KEY: &str = "muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69";
|
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))?;
|
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));
|
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"]
|
let people: Vec<PersonInfo> = json["identities"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.unwrap_or(&vec![])
|
.unwrap_or(&vec![])
|
||||||
@@ -144,6 +165,7 @@ async fn get_people(page: usize, per_page: usize) -> Result<Vec<PersonInfo>, Str
|
|||||||
Some(PersonInfo {
|
Some(PersonInfo {
|
||||||
identity_uuid: i["identity_uuid"].as_str()?.to_string(),
|
identity_uuid: i["identity_uuid"].as_str()?.to_string(),
|
||||||
name: i["name"].as_str()?.to_string(),
|
name: i["name"].as_str()?.to_string(),
|
||||||
|
starred: i["metadata"]["starred"].as_bool().unwrap_or(false),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.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 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 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()
|
.as_array()
|
||||||
.unwrap_or(&vec![])
|
.unwrap_or(&vec![])
|
||||||
.iter()
|
.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),
|
id: f["id"].as_i64().unwrap_or(0),
|
||||||
file_uuid: f["file_uuid"].as_str()?.to_string(),
|
file_uuid: f["file_uuid"].as_str()?.to_string(),
|
||||||
frame_number: f["frame_number"].as_i64().unwrap_or(0),
|
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),
|
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))?
|
.map_err(|e| format!("Video request failed: {}", e))?
|
||||||
.bytes().await
|
.bytes().await
|
||||||
.map_err(|e| format!("Video read failed: {}", e))?;
|
.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] = &[
|
const PROFILE_DIRS: &[&str] = &[
|
||||||
@@ -274,6 +304,98 @@ async fn delete_identity(uuid: String) -> Result<(), String> {
|
|||||||
Ok(())
|
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() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
@@ -287,7 +409,12 @@ fn main() {
|
|||||||
get_video_stream,
|
get_video_stream,
|
||||||
get_identity_profile,
|
get_identity_profile,
|
||||||
update_identity_name,
|
update_identity_name,
|
||||||
delete_identity
|
delete_identity,
|
||||||
|
search_identities,
|
||||||
|
get_face_candidates,
|
||||||
|
merge_identities,
|
||||||
|
bind_face,
|
||||||
|
unbind_face
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|||||||
Reference in New Issue
Block a user