use std::fs::create_dir_all;
use std::path::PathBuf;
use tauri::{AppHandle, Manager, Runtime};
use crate::error::Error;
const MODELS_SUBDIR: &str = "whisper-models";
#[allow(dead_code)]
pub fn get_models_dir<R: Runtime>(app: &AppHandle<R>) -> Result<PathBuf, Error> {
let base_path = app
.path()
.app_data_dir()
.map_err(|e| Error::ConfigError(format!("Could not determine app data directory: {e}")))?;
let full_path = base_path.join(MODELS_SUBDIR);
create_dir_all(&full_path).map_err(|e| {
Error::ConfigError(format!(
"Could not create models directory {}: {}",
full_path.display(),
e
))
})?;
Ok(full_path)
}
#[allow(dead_code)]
pub fn get_model_path<R: Runtime>(app: &AppHandle<R>, model_name: &str) -> Result<PathBuf, Error> {
validate_path(model_name)?;
let models_dir = get_models_dir(app)?;
Ok(models_dir.join(model_name))
}
#[allow(dead_code)]
pub fn model_exists<R: Runtime>(app: &AppHandle<R>, model_name: &str) -> Result<bool, Error> {
let model_path = get_model_path(app, model_name)?;
Ok(model_path.exists() && model_path.is_file())
}
#[allow(dead_code)]
pub fn list_available_models<R: Runtime>(app: &AppHandle<R>) -> Result<Vec<String>, Error> {
let models_dir = get_models_dir(app)?;
let mut models = Vec::new();
if let Ok(entries) = std::fs::read_dir(&models_dir) {
for entry in entries.flatten() {
if let Ok(metadata) = entry.metadata() {
if metadata.is_file() {
if let Some(name) = entry.file_name().to_str() {
if name.ends_with(".bin") {
models.push(name.to_string());
}
}
}
}
}
}
Ok(models)
}
#[allow(dead_code)]
pub fn validate_path(path: &str) -> Result<(), Error> {
let path_buf = PathBuf::from(path);
for component in path_buf.components() {
if let std::path::Component::ParentDir = component {
return Err(Error::ConfigError(
"Path traversal not allowed (contains '..')".to_string(),
));
}
}
Ok(())
}