From c15bd364c1f109593e5c0f4eb16a9f7dff97252d Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Sat, 2 Aug 2025 00:49:33 -0300 Subject: [PATCH] - First run to generate e-mail. --- src/prompts/business/data-enrichment.bas | 9 ++++---- src/services/keywords/first.rs | 21 +++++++++++++++++++ src/services/keywords/get_website.rs | 4 ++-- src/services/keywords/mod.rs | 1 + src/services/keywords/set.rs | 26 ++++++++++++++---------- src/services/script.rs | 4 +++- src/services/utils.rs | 18 ++++++++++++++++ 7 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 src/services/keywords/first.rs diff --git a/src/prompts/business/data-enrichment.bas b/src/prompts/business/data-enrichment.bas index 558ee85..a6af886 100644 --- a/src/prompts/business/data-enrichment.bas +++ b/src/prompts/business/data-enrichment.bas @@ -5,21 +5,20 @@ FOR EACH item IN items let website = WEBSITE OF item.company PRINT website - let page = GET website let prompt = "Build the same simulator , but for " + item.company + " using just *content about the company* from its website, so it is possible to create a good and useful emulator in the same langue as the content: " + page let alias = LLM "Return a single word for " + item.company + " like a token, no spaces, no special characters, no numbers, no uppercase letters." - + CREATE_SITE alias, "OpenSourceCars", prompt let to = item.emailcto - let subject = "General Bots" - let body = "Oi, tudo bem? Criamos o simulador " + alias + " especificamente para vocês!" + "\n\n Acesse o site: https://sites.pragmatismo.com.br/" + alias + "\n\n" + "Para acessar o simulador, clique no link acima ou copie e cole no seu navegador." + "\n\n" + "Para iniciar, clique no ícone de Play." + "\n\n" + "Atenciosamente,\nDário Vieira" + let subject = "Simulador " + alias + let body = "Oi, " + FIRST(item.Contact) + "! Tudo bem? Estou empolgado, pois criamos o simulador " + alias + " especificamente para vocês!" + "\n\n Acesse o site: https://sites.pragmatismo.com.br/" + alias + "\n\n" + "Para acessar o simulador, clique no link acima ou copie e cole no seu navegador." + "\n\n" + "Para iniciar, clique no ícone de Play." + "\n\n" + "Atenciosamente,\nDário Vieira\n\n" CREATE_DRAFT to, subject, body - + NEXT item \ No newline at end of file diff --git a/src/services/keywords/first.rs b/src/services/keywords/first.rs new file mode 100644 index 0000000..5d4c7fd --- /dev/null +++ b/src/services/keywords/first.rs @@ -0,0 +1,21 @@ +use rhai::Dynamic; +use rhai::Engine; + +pub fn first_keyword(engine: &mut Engine) { + engine + .register_custom_syntax(&["FIRST", "$expr$"], false, { + move |context, inputs| { + let input_string = context.eval_expression_tree(&inputs[0])?; + let input_str = input_string.to_string(); + + // Extract first word by splitting on whitespace + let first_word = input_str.split_whitespace() + .next() + .unwrap_or("") + .to_string(); + + Ok(Dynamic::from(first_word)) + } + }) + .unwrap(); +} \ No newline at end of file diff --git a/src/services/keywords/get_website.rs b/src/services/keywords/get_website.rs index 2fb1d1c..42e8b92 100644 --- a/src/services/keywords/get_website.rs +++ b/src/services/keywords/get_website.rs @@ -77,8 +77,8 @@ async fn perform_search( // Extract results let results = extract_search_results(&driver).await?; - driver.quit().await?; - + driver.close_window().await?; + if !results.is_empty() { Ok(results[0].clone()) } else { diff --git a/src/services/keywords/mod.rs b/src/services/keywords/mod.rs index 5395822..c999292 100644 --- a/src/services/keywords/mod.rs +++ b/src/services/keywords/mod.rs @@ -1,6 +1,7 @@ pub mod create_draft; pub mod create_site; pub mod find; +pub mod first; pub mod for_next; pub mod get; pub mod get_website; diff --git a/src/services/keywords/set.rs b/src/services/keywords/set.rs index de2d039..325f7b3 100644 --- a/src/services/keywords/set.rs +++ b/src/services/keywords/set.rs @@ -53,11 +53,13 @@ pub async fn execute_set( table_str, filter_str, updates_str ); - // Parse the filter condition - let (where_clause, filter_params) = utils::parse_filter(filter_str).map_err(|e| e.to_string())?; - - // Parse the updates + // Parse the updates first to know how many parameters we'll have let (set_clause, update_params) = parse_updates(updates_str).map_err(|e| e.to_string())?; + let update_params_count = update_params.len(); + + // Parse the filter condition with an offset for parameter indices + let (where_clause, filter_params) = utils::parse_filter_with_offset(filter_str, update_params_count) + .map_err(|e| e.to_string())?; // Combine all parameters (updates first, then filter) let mut params = update_params; @@ -69,11 +71,13 @@ pub async fn execute_set( ); println!("Executing query: {}", query); - // Execute the update - let result = sqlx::query(&query) - .bind(¶ms[0]) // First update value - .bind(¶ms[1]) // Second update value if exists - .bind(¶ms[2]) // Filter value + // Execute the update with all parameters + let mut query_builder = sqlx::query(&query); + for param in ¶ms { + query_builder = query_builder.bind(param); + } + + let result = query_builder .execute(pool) .await .map_err(|e| { @@ -98,7 +102,7 @@ fn parse_updates(updates_str: &str) -> Result<(String, Vec), Box = update.split('=').collect(); if parts.len() != 2 { return Err("Invalid update format. Expected 'KEY=VALUE'".into()); @@ -112,7 +116,7 @@ fn parse_updates(updates_str: &str) -> Result<(String, Vec), Box Result<(String, Vec), Box Result<(String, Vec), Box> { + let parts: Vec<&str> = filter_str.split('=').collect(); + if parts.len() != 2 { + return Err("Invalid filter format. Expected 'KEY=VALUE'".into()); + } + + let column = parts[0].trim(); + let value = parts[1].trim(); + + // Validate column name to prevent SQL injection + if !column.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') { + return Err("Invalid column name in filter".into()); + } + + // Use the offset + 1 for the parameter number + Ok((format!("{} = ${}", column, offset + 1), vec![value.to_string()])) +}