New keywords format and last.
This commit is contained in:
parent
4e762a1a5d
commit
97e442f20a
12 changed files with 351 additions and 36 deletions
45
.vscode/launch.json
vendored
Normal file
45
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug executable 'gbserver'",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"--bin=gbserver",
|
||||||
|
"--package=gbserver"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "gbserver",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug unit tests in executable 'gbserver'",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--no-run",
|
||||||
|
"--bin=gbserver",
|
||||||
|
"--package=gbserver"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "gbserver",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
19
Cargo.lock
generated
19
Cargo.lock
generated
|
|
@ -409,6 +409,12 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert-json-diff"
|
name = "assert-json-diff"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
|
|
@ -1750,6 +1756,7 @@ dependencies = [
|
||||||
"mailparse",
|
"mailparse",
|
||||||
"minio",
|
"minio",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
|
"num-format",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest 0.11.27",
|
"reqwest 0.11.27",
|
||||||
"rhai",
|
"rhai",
|
||||||
|
|
@ -2599,7 +2606,7 @@ version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec 0.5.2",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
|
@ -2994,6 +3001,16 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-format"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec 0.7.6",
|
||||||
|
"itoa",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.46"
|
version = "0.1.46"
|
||||||
|
|
|
||||||
|
|
@ -60,3 +60,4 @@ urlencoding = "2.1"
|
||||||
regex = "1.10"
|
regex = "1.10"
|
||||||
uuid = { version = "1.4", features = ["serde", "v4"] } # v4, v7, etc. as needed
|
uuid = { version = "1.4", features = ["serde", "v4"] } # v4, v7, etc. as needed
|
||||||
zip = "4.3.0"
|
zip = "4.3.0"
|
||||||
|
num-format = "0.4"
|
||||||
|
|
@ -52,7 +52,7 @@ impl AutomationService {
|
||||||
sqlx::query_as::<_, Automation>(
|
sqlx::query_as::<_, Automation>(
|
||||||
r#"
|
r#"
|
||||||
SELECT id, kind, target, schedule, param, is_active, last_triggered
|
SELECT id, kind, target, schedule, param, is_active, last_triggered
|
||||||
FROM system_automations
|
FROM public.system_automations
|
||||||
WHERE is_active = true
|
WHERE is_active = true
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
|
|
@ -122,7 +122,7 @@ impl AutomationService {
|
||||||
async fn update_last_triggered(&self, automation_id: Uuid) {
|
async fn update_last_triggered(&self, automation_id: Uuid) {
|
||||||
if let Some(pool) = &self.state.db {
|
if let Some(pool) = &self.state.db {
|
||||||
if let Err(e) = sqlx::query!(
|
if let Err(e) = sqlx::query!(
|
||||||
"UPDATE system_automations SET last_triggered = $1 WHERE id = $2",
|
"UPDATE public.system_automations SET last_triggered = $1 WHERE id = $2",
|
||||||
Utc::now(),
|
Utc::now(),
|
||||||
automation_id
|
automation_id
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -497,7 +497,7 @@ pub async fn save_click(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
let (campaign_id, email) = path.into_inner();
|
let (campaign_id, email) = path.into_inner();
|
||||||
let _ = sqlx::query("INSERT INTO clicks (campaign_id, email, updated_at) VALUES ($1, $2, NOW()) ON CONFLICT (campaign_id, email) DO UPDATE SET updated_at = NOW()")
|
let _ = sqlx::query("INSERT INTO public.clicks (campaign_id, email, updated_at) VALUES ($1, $2, NOW()) ON CONFLICT (campaign_id, email) DO UPDATE SET updated_at = NOW()")
|
||||||
.bind(campaign_id)
|
.bind(campaign_id)
|
||||||
.bind(email)
|
.bind(email)
|
||||||
.execute(state.db.as_ref().unwrap())
|
.execute(state.db.as_ref().unwrap())
|
||||||
|
|
|
||||||
193
src/services/keywords/format.rs
Normal file
193
src/services/keywords/format.rs
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
use rhai::{Dynamic, Engine};
|
||||||
|
use chrono::{NaiveDateTime, Timelike, Datelike};
|
||||||
|
use num_format::{Locale, ToFormattedString};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
pub fn format_keyword(engine: &mut Engine) {
|
||||||
|
engine
|
||||||
|
.register_custom_syntax(&["FORMAT", "$expr$", "$expr$"], false, {
|
||||||
|
move |context, inputs| {
|
||||||
|
let value_dyn = context.eval_expression_tree(&inputs[0])?;
|
||||||
|
let pattern_dyn = context.eval_expression_tree(&inputs[1])?;
|
||||||
|
|
||||||
|
let value_str = value_dyn.to_string();
|
||||||
|
let pattern = pattern_dyn.to_string();
|
||||||
|
|
||||||
|
// --- NUMÉRICO ---
|
||||||
|
if let Ok(num) = f64::from_str(&value_str) {
|
||||||
|
let formatted = if pattern.starts_with("N") || pattern.starts_with("C") {
|
||||||
|
// extrai partes: prefixo, casas decimais, locale
|
||||||
|
let (prefix, decimals, locale_tag) = parse_pattern(&pattern);
|
||||||
|
|
||||||
|
let locale = get_locale(&locale_tag);
|
||||||
|
let symbol = if prefix == "C" {
|
||||||
|
get_currency_symbol(&locale_tag)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
let int_part = num.trunc() as i64;
|
||||||
|
let frac_part = num.fract();
|
||||||
|
|
||||||
|
if decimals == 0 {
|
||||||
|
format!("{}{}", symbol, int_part.to_formatted_string(&locale))
|
||||||
|
} else {
|
||||||
|
let frac_scaled =
|
||||||
|
((frac_part * 10f64.powi(decimals as i32)).round()) as i64;
|
||||||
|
format!(
|
||||||
|
"{}{}.{:0width$}",
|
||||||
|
symbol,
|
||||||
|
int_part.to_formatted_string(&locale),
|
||||||
|
frac_scaled,
|
||||||
|
width = decimals
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match pattern.as_str() {
|
||||||
|
"n" => format!("{:.2}", num),
|
||||||
|
"F" => format!("{:.2}", num),
|
||||||
|
"f" => format!("{}", num),
|
||||||
|
"0%" => format!("{:.0}%", num * 100.0),
|
||||||
|
_ => format!("{}", num),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(Dynamic::from(formatted));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- DATA ---
|
||||||
|
if let Ok(dt) = NaiveDateTime::parse_from_str(&value_str, "%Y-%m-%d %H:%M:%S") {
|
||||||
|
let formatted = apply_date_format(&dt, &pattern);
|
||||||
|
return Ok(Dynamic::from(formatted));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- TEXTO ---
|
||||||
|
let formatted = apply_text_placeholders(&value_str, &pattern);
|
||||||
|
Ok(Dynamic::from(formatted))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// Extração de locale + precisão
|
||||||
|
// ======================
|
||||||
|
fn parse_pattern(pattern: &str) -> (String, usize, String) {
|
||||||
|
let mut prefix = String::new();
|
||||||
|
let mut decimals: usize = 2; // padrão 2 casas
|
||||||
|
let mut locale_tag = "en".to_string();
|
||||||
|
|
||||||
|
// ex: "C2[pt]" ou "N3[fr]"
|
||||||
|
if pattern.starts_with('C') {
|
||||||
|
prefix = "C".to_string();
|
||||||
|
} else if pattern.starts_with('N') {
|
||||||
|
prefix = "N".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// procura número após prefixo
|
||||||
|
let rest = &pattern[1..];
|
||||||
|
let mut num_part = String::new();
|
||||||
|
for ch in rest.chars() {
|
||||||
|
if ch.is_ascii_digit() {
|
||||||
|
num_part.push(ch);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !num_part.is_empty() {
|
||||||
|
decimals = num_part.parse().unwrap_or(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// procura locale entre colchetes
|
||||||
|
if let Some(start) = pattern.find('[') {
|
||||||
|
if let Some(end) = pattern.find(']') {
|
||||||
|
if end > start {
|
||||||
|
locale_tag = pattern[start + 1..end].to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(prefix, decimals, locale_tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_locale(tag: &str) -> Locale {
|
||||||
|
match tag {
|
||||||
|
"en" => Locale::en,
|
||||||
|
"fr" => Locale::fr,
|
||||||
|
"de" => Locale::de,
|
||||||
|
"pt" => Locale::pt,
|
||||||
|
"it" => Locale::it,
|
||||||
|
"es" => Locale::es,
|
||||||
|
_ => Locale::en,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_currency_symbol(tag: &str) -> &'static str {
|
||||||
|
match tag {
|
||||||
|
"en" => "$",
|
||||||
|
"pt" => "R$ ",
|
||||||
|
"fr" | "de" | "es" | "it" => "€",
|
||||||
|
_ => "$",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// SUPORTE A DATAS
|
||||||
|
// ==================
|
||||||
|
fn apply_date_format(dt: &NaiveDateTime, pattern: &str) -> String {
|
||||||
|
let mut output = pattern.to_string();
|
||||||
|
|
||||||
|
let year = dt.year();
|
||||||
|
let month = dt.month();
|
||||||
|
let day = dt.day();
|
||||||
|
let hour24 = dt.hour();
|
||||||
|
let minute = dt.minute();
|
||||||
|
let second = dt.second();
|
||||||
|
let millis = dt.and_utc().timestamp_subsec_millis();
|
||||||
|
|
||||||
|
output = output.replace("yyyy", &format!("{:04}", year));
|
||||||
|
output = output.replace("yy", &format!("{:02}", year % 100));
|
||||||
|
output = output.replace("MM", &format!("{:02}", month));
|
||||||
|
output = output.replace("M", &format!("{}", month));
|
||||||
|
output = output.replace("dd", &format!("{:02}", day));
|
||||||
|
output = output.replace("d", &format!("{}", day));
|
||||||
|
|
||||||
|
output = output.replace("HH", &format!("{:02}", hour24));
|
||||||
|
output = output.replace("H", &format!("{}", hour24));
|
||||||
|
|
||||||
|
let mut hour12 = hour24 % 12;
|
||||||
|
if hour12 == 0 { hour12 = 12; }
|
||||||
|
output = output.replace("hh", &format!("{:02}", hour12));
|
||||||
|
output = output.replace("h", &format!("{}", hour12));
|
||||||
|
|
||||||
|
output = output.replace("mm", &format!("{:02}", minute));
|
||||||
|
output = output.replace("m", &format!("{}", minute));
|
||||||
|
|
||||||
|
output = output.replace("ss", &format!("{:02}", second));
|
||||||
|
output = output.replace("s", &format!("{}", second));
|
||||||
|
|
||||||
|
output = output.replace("fff", &format!("{:03}", millis));
|
||||||
|
|
||||||
|
output = output.replace("tt", if hour24 < 12 { "AM" } else { "PM" });
|
||||||
|
output = output.replace("t", if hour24 < 12 { "A" } else { "P" });
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// SUPORTE A TEXTO
|
||||||
|
// ==================
|
||||||
|
fn apply_text_placeholders(value: &str, pattern: &str) -> String {
|
||||||
|
let mut result = String::new();
|
||||||
|
|
||||||
|
for ch in pattern.chars() {
|
||||||
|
match ch {
|
||||||
|
'@' => result.push_str(value),
|
||||||
|
'&' | '<' => result.push_str(&value.to_lowercase()),
|
||||||
|
'>' | '!' => result.push_str(&value.to_uppercase()),
|
||||||
|
_ => result.push(ch), // copia qualquer caractere literal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
22
src/services/keywords/last.rs
Normal file
22
src/services/keywords/last.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
use rhai::Dynamic;
|
||||||
|
use rhai::Engine;
|
||||||
|
|
||||||
|
pub fn last_keyword(engine: &mut Engine) {
|
||||||
|
engine
|
||||||
|
.register_custom_syntax(&["LAST", "$expr$"], false, {
|
||||||
|
move |context, inputs| {
|
||||||
|
let input_string = context.eval_expression_tree(&inputs[0])?;
|
||||||
|
let input_str = input_string.to_string();
|
||||||
|
|
||||||
|
// Extrai a última palavra dividindo por espaço
|
||||||
|
let last_word = input_str
|
||||||
|
.split_whitespace()
|
||||||
|
.last()
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
Ok(Dynamic::from(last_word))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,8 @@ pub mod create_draft;
|
||||||
pub mod create_site;
|
pub mod create_site;
|
||||||
pub mod find;
|
pub mod find;
|
||||||
pub mod first;
|
pub mod first;
|
||||||
|
pub mod last;
|
||||||
|
pub mod format;
|
||||||
pub mod for_next;
|
pub mod for_next;
|
||||||
pub mod get;
|
pub mod get;
|
||||||
pub mod get_website;
|
pub mod get_website;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use dotenv::dotenv;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::env;
|
use std::{env, process::Command};
|
||||||
use tokio::time::{sleep, Duration};
|
use tokio::time::{sleep, Duration};
|
||||||
|
|
||||||
// OpenAI-compatible request/response structures
|
// OpenAI-compatible request/response structures
|
||||||
|
|
@ -188,15 +188,26 @@ async fn start_llm_server(
|
||||||
std::env::set_var("OMP_PLACES", "cores");
|
std::env::set_var("OMP_PLACES", "cores");
|
||||||
std::env::set_var("OMP_PROC_BIND", "close");
|
std::env::set_var("OMP_PROC_BIND", "close");
|
||||||
|
|
||||||
|
let mut cmd = Command::new("sh");
|
||||||
// "cd {} && numactl --interleave=all ./llama-server -m {} --host 0.0.0.0 --port {} --threads 20 --threads-batch 40 --temp 0.7 --parallel 1 --repeat-penalty 1.1 --ctx-size 8192 --batch-size 8192 -n 4096 --mlock --no-mmap --flash-attn --no-kv-offload --no-mmap &",
|
// "cd {} && numactl --interleave=all ./llama-server -m {} --host 0.0.0.0 --port {} --threads 20 --threads-batch 40 --temp 0.7 --parallel 1 --repeat-penalty 1.1 --ctx-size 8192 --batch-size 8192 -n 4096 --mlock --no-mmap --flash-attn --no-kv-offload --no-mmap &",
|
||||||
|
|
||||||
let mut cmd = tokio::process::Command::new("sh");
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
cmd.arg("-c").arg(format!(
|
cmd.arg("-c").arg(format!(
|
||||||
"cd {} && ./llama-server -m {} --host 0.0.0.0 --port {} --n-gpu-layers 99 &",
|
"cd {} && ./llama-server -m {} --host 0.0.0.0 --port {} --n-gpu-layers 99 &",
|
||||||
llama_cpp_path, model_path, port
|
llama_cpp_path, model_path, port
|
||||||
));
|
));
|
||||||
|
|
||||||
cmd.spawn()?;
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
cmd.arg("/C").arg(format!(
|
||||||
|
"cd {} && llama-server.exe -m {} --host 0.0.0.0 --port {} --n-gpu-layers 99",
|
||||||
|
llama_cpp_path, model_path, port
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,12 +217,24 @@ async fn start_embedding_server(
|
||||||
url: String,
|
url: String,
|
||||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let port = url.split(':').last().unwrap_or("8082");
|
let port = url.split(':').last().unwrap_or("8082");
|
||||||
|
let mut cmd = Command::new("cmd");
|
||||||
|
|
||||||
let mut cmd = tokio::process::Command::new("sh");
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
cmd.arg("/C").arg(format!(
|
||||||
|
"cd {} && llama-server.exe -m {} --host 0.0.0.0 --port {} --embedding --n-gpu-layers 99",
|
||||||
|
llama_cpp_path, model_path, port
|
||||||
|
));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
|
{
|
||||||
cmd.arg("-c").arg(format!(
|
cmd.arg("-c").arg(format!(
|
||||||
"cd {} && ./llama-server -m {} --host 0.0.0.0 --port {} --embedding --n-gpu-layers 99 &",
|
"cd {} && ./llama-server -m {} --host 0.0.0.0 --port {} --embedding --n-gpu-layers 99 &",
|
||||||
llama_cpp_path, model_path, port
|
llama_cpp_path, model_path, port
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
cmd.spawn()?;
|
cmd.spawn()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -431,7 +454,8 @@ struct LlamaCppEmbeddingRequest {
|
||||||
// FIXED: Handle the stupid nested array format
|
// FIXED: Handle the stupid nested array format
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct LlamaCppEmbeddingResponseItem {
|
struct LlamaCppEmbeddingResponseItem {
|
||||||
pub index: usize,
|
#[serde(rename = "index")]
|
||||||
|
pub _index: usize,
|
||||||
pub embedding: Vec<Vec<f32>>, // This is the fucked up part - embedding is an array of arrays
|
pub embedding: Vec<Vec<f32>>, // This is the fucked up part - embedding is an array of arrays
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ use crate::services::keywords::create_draft::create_draft_keyword;
|
||||||
use crate::services::keywords::create_site::create_site_keyword;
|
use crate::services::keywords::create_site::create_site_keyword;
|
||||||
use crate::services::keywords::find::find_keyword;
|
use crate::services::keywords::find::find_keyword;
|
||||||
use crate::services::keywords::first::first_keyword;
|
use crate::services::keywords::first::first_keyword;
|
||||||
|
use crate::services::keywords::last::last_keyword;
|
||||||
|
use crate::services::keywords::format::format_keyword;
|
||||||
use crate::services::keywords::for_next::for_keyword;
|
use crate::services::keywords::for_next::for_keyword;
|
||||||
use crate::services::keywords::get::get_keyword;
|
use crate::services::keywords::get::get_keyword;
|
||||||
use crate::services::keywords::get_website::get_website_keyword;
|
use crate::services::keywords::get_website::get_website_keyword;
|
||||||
|
|
@ -32,6 +34,8 @@ impl ScriptService {
|
||||||
find_keyword(state, &mut engine);
|
find_keyword(state, &mut engine);
|
||||||
for_keyword(state, &mut engine);
|
for_keyword(state, &mut engine);
|
||||||
first_keyword(&mut engine);
|
first_keyword(&mut engine);
|
||||||
|
last_keyword(&mut engine);
|
||||||
|
format_keyword(&mut engine);
|
||||||
llm_keyword(state, &mut engine);
|
llm_keyword(state, &mut engine);
|
||||||
get_website_keyword(state, &mut engine);
|
get_website_keyword(state, &mut engine);
|
||||||
get_keyword(state, &mut engine);
|
get_keyword(state, &mut engine);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::path::PathBuf;
|
||||||
use thirtyfour::{DesiredCapabilities, WebDriver};
|
use thirtyfour::{DesiredCapabilities, WebDriver};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use tokio::sync::Semaphore;
|
use tokio::sync::Semaphore;
|
||||||
|
|
@ -76,8 +77,8 @@ impl BrowserSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn find_brave() -> Result<String, Box<dyn std::error::Error>> {
|
async fn find_brave() -> Result<String, Box<dyn std::error::Error>> {
|
||||||
let possible_paths = vec![
|
let mut possible_paths = vec![
|
||||||
// Windows
|
// Windows - Program Files
|
||||||
String::from(r"C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe"),
|
String::from(r"C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe"),
|
||||||
// macOS
|
// macOS
|
||||||
String::from("/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"),
|
String::from("/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"),
|
||||||
|
|
@ -86,6 +87,13 @@ impl BrowserSetup {
|
||||||
String::from("/usr/bin/brave"),
|
String::from("/usr/bin/brave"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Windows - AppData (usuário atual)
|
||||||
|
if let Ok(local_appdata) = env::var("LOCALAPPDATA") {
|
||||||
|
let mut path = PathBuf::from(local_appdata);
|
||||||
|
path.push("BraveSoftware\\Brave-Browser\\Application\\brave.exe");
|
||||||
|
possible_paths.push(path.to_string_lossy().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
for path in possible_paths {
|
for path in possible_paths {
|
||||||
if fs::metadata(&path).await.is_ok() {
|
if fs::metadata(&path).await.is_ok() {
|
||||||
return Ok(path);
|
return Ok(path);
|
||||||
|
|
@ -93,8 +101,7 @@ impl BrowserSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
Err("Brave browser not found. Please install Brave first.".into())
|
Err("Brave browser not found. Please install Brave first.".into())
|
||||||
}
|
} async fn setup_chromedriver() -> Result<String, Box<dyn std::error::Error>> {
|
||||||
async fn setup_chromedriver() -> Result<String, Box<dyn std::error::Error>> {
|
|
||||||
// Create chromedriver directory in executable's parent directory
|
// Create chromedriver directory in executable's parent directory
|
||||||
let mut chromedriver_dir = env::current_exe()?.parent().unwrap().to_path_buf();
|
let mut chromedriver_dir = env::current_exe()?.parent().unwrap().to_path_buf();
|
||||||
chromedriver_dir.push("chromedriver");
|
chromedriver_dir.push("chromedriver");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue