gbserver/src/services/keywords/create_site.rs

90 lines
3.3 KiB
Rust
Raw Normal View History

2025-07-20 00:03:37 -03:00
use rhai::Dynamic;
use rhai::Engine;
2025-07-31 00:36:10 -03:00
use std::error::Error;
use std::fs;
2025-08-02 00:07:54 -03:00
use std::path::{ PathBuf};
use std::io::Read;
2025-07-20 00:03:37 -03:00
use crate::services::state::AppState;
2025-07-31 00:36:10 -03:00
use crate::services::utils;
2025-07-20 00:03:37 -03:00
2025-07-31 00:36:10 -03:00
pub fn create_site_keyword(state: &AppState, engine: &mut Engine) {
let state_clone = state.clone();
2025-07-20 00:03:37 -03:00
engine
.register_custom_syntax(
&[
2025-08-02 00:07:54 -03:00
"CREATE_SITE", "$expr$", ",", "$expr$", ",", "$expr$",
2025-07-20 00:03:37 -03:00
],
2025-08-02 00:07:54 -03:00
true,
move |context, inputs| {
2025-08-02 00:07:54 -03:00
if inputs.len() < 3 {
2025-07-20 00:03:37 -03:00
return Err("Not enough arguments for CREATE SITE".into());
}
2025-08-02 00:07:54 -03:00
let alias = context.eval_expression_tree(&inputs[0])?;
let template_dir = context.eval_expression_tree(&inputs[1])?;
let prompt = context.eval_expression_tree(&inputs[2])?;
let config = state_clone.config.as_ref().expect("Config must be initialized").clone();
let fut = create_site(&config, alias, template_dir, prompt);
2025-07-31 00:36:10 -03:00
let result =
tokio::task::block_in_place(|| tokio::runtime::Handle::current().block_on(fut))
2025-08-02 00:07:54 -03:00
.map_err(|e| format!("Site creation failed: {}", e))?;
2025-07-20 00:03:37 -03:00
2025-07-31 00:36:10 -03:00
Ok(Dynamic::from(result))
2025-07-20 00:03:37 -03:00
},
)
.unwrap();
2025-07-31 00:36:10 -03:00
}
async fn create_site(
2025-08-02 00:07:54 -03:00
config: &crate::services::config::AppConfig,
alias: Dynamic,
template_dir: Dynamic,
2025-07-31 00:36:10 -03:00
prompt: Dynamic,
2025-08-02 00:07:54 -03:00
) -> Result<String, Box<dyn Error + Send + Sync>> {
// Convert paths to platform-specific format
let base_path = PathBuf::from(&config.site_path);
let template_path = base_path.join(template_dir.to_string());
let alias_path = base_path.join(alias.to_string());
// Create destination directory
fs::create_dir_all(&alias_path).map_err(|e| e.to_string())?;
2025-07-31 00:36:10 -03:00
2025-08-02 00:07:54 -03:00
// Process all HTML files in template directory
let mut combined_content = String::new();
for entry in fs::read_dir(&template_path).map_err(|e| e.to_string())? {
let entry = entry.map_err(|e| e.to_string())?;
let path = entry.path();
if path.extension().map_or(false, |ext| ext == "html") {
let mut file = fs::File::open(&path).map_err(|e| e.to_string())?;
let mut contents = String::new();
file.read_to_string(&mut contents).map_err(|e| e.to_string())?;
combined_content.push_str(&contents);
combined_content.push_str("\n\n--- TEMPLATE SEPARATOR ---\n\n");
}
}
2025-07-31 00:36:10 -03:00
2025-08-02 00:07:54 -03:00
// Combine template content with prompt
let full_prompt = format!(
"TEMPLATE FILES:\n{}\n\nPROMPT: {}\n\nGenerate a new HTML file cloning all previous TEMPLATE (keeping only the local _assets libraries use, no external resources), but turning this into this prompt:",
combined_content,
prompt.to_string()
);
2025-07-31 00:36:10 -03:00
2025-08-02 00:07:54 -03:00
// Call LLM with the combined prompt
println!("Asking LLM to create site.");
let llm_result = utils::call_llm(&full_prompt, &config.ai).await?;
2025-07-31 00:36:10 -03:00
2025-08-02 00:07:54 -03:00
// Write the generated HTML file
let index_path = alias_path.join("index.html");
2025-07-31 00:36:10 -03:00
fs::write(index_path, llm_result).map_err(|e| e.to_string())?;
2025-08-02 00:07:54 -03:00
println!("Site created at: {}", alias_path.display());
Ok(alias_path.to_string_lossy().into_owned())
}