Add container setup scripts for various services
Some checks failed
GBCI / build (push) Has been cancelled
Some checks failed
GBCI / build (push) Has been cancelled
- Implemented ALM container setup with Forgejo installation and systemd service configuration. - Created Bot container setup with necessary dependencies and Node.js application installation. - Developed Desktop container setup with XRDP and Brave browser installation. - Established Directory container setup with Zitadel installation and service configuration. - Added Doc Editor container setup for Collabora Online integration. - Implemented Drive container setup with MinIO installation and service configuration. - Created Email container setup with Stalwart Mail installation and service configuration. - Developed Meeting container setup with LiveKit and TURN server configuration. - Added Proxy container setup with Caddy installation and service configuration. - Implemented System container setup for general bots with service configuration. - Created Table Editor container setup with NocoDB installation and service configuration. - Developed Tables container setup with PostgreSQL installation and configuration. - Added Webmail container setup with Roundcube installation and service configuration. - Included prompt guidelines for container setup scripts.
This commit is contained in:
parent
7131911313
commit
a4206ad63d
7 changed files with 264 additions and 27 deletions
|
@ -15,7 +15,7 @@ actix-ws="0.3.0"
|
|||
bytes = "1.1"
|
||||
futures-util = "0.3"
|
||||
reqwest = { version = "0.11", features = ["json", "stream"] }
|
||||
rhai = "1.0"
|
||||
rhai = "1.22.2"
|
||||
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
dotenv = "0.15"
|
||||
|
|
32
src/main.rs
32
src/main.rs
|
@ -10,7 +10,8 @@ use services::email::*;
|
|||
use services::file::*;
|
||||
use services::state::*;
|
||||
use services::llm::*;
|
||||
|
||||
use sqlx::PgPool;
|
||||
//use services:: find::*;
|
||||
mod services;
|
||||
|
||||
#[actix_web::main]
|
||||
|
@ -18,14 +19,23 @@ async fn main() -> std::io::Result<()> {
|
|||
dotenv().ok();
|
||||
let config = AppConfig::from_env();
|
||||
|
||||
|
||||
// let table_str = "rob";
|
||||
// let filter_str = "ACTION=EMUL1";
|
||||
|
||||
// match execute_find(table_str, filter_str) {
|
||||
// Ok(result) => println!("{}", result),
|
||||
// Err(e) => eprintln!("Error: {}", e),
|
||||
// }
|
||||
|
||||
|
||||
let script_service = ScriptService::new();
|
||||
|
||||
let script = r#"
|
||||
let json = FIND "users", "name=John"
|
||||
let x=2
|
||||
|
||||
let list = FIND "rob", "ACTION=EMUL1"
|
||||
let text = GET "example.com"
|
||||
let nome = "table"
|
||||
let d = FIND nome, "car=2"
|
||||
|
||||
"#;
|
||||
|
||||
match script_service.compile(script) {
|
||||
|
@ -40,16 +50,16 @@ async fn main() -> std::io::Result<()> {
|
|||
|
||||
|
||||
let db_url = config.database_url();
|
||||
//let db = PgPool::connect(&db_url).await.unwrap();
|
||||
let db = PgPool::connect(&db_url).await.unwrap();
|
||||
|
||||
// let minio_client = init_minio(&config)
|
||||
// .await
|
||||
// .expect("Failed to initialize Minio");
|
||||
let minio_client = init_minio(&config)
|
||||
.await
|
||||
.expect("Failed to initialize Minio");
|
||||
|
||||
let app_state = web::Data::new(AppState {
|
||||
db: None,
|
||||
db: db.into(),
|
||||
config: Some(config.clone()),
|
||||
minio_client: None,
|
||||
minio_client: minio_client.into(),
|
||||
});
|
||||
|
||||
// Start HTTP server
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod config;
|
||||
pub mod file;
|
||||
|
||||
pub mod state;
|
||||
pub mod email;
|
||||
pub mod file;
|
||||
pub mod llm;
|
||||
pub mod script;
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
use actix_web::{ web};
|
||||
|
||||
use actix_multipart::Multipart;
|
||||
|
|
232
src/services/find.md
Normal file
232
src/services/find.md
Normal file
|
@ -0,0 +1,232 @@
|
|||
- 100KB Email box
|
||||
|
||||
i need a vb to russt watx
|
||||
first wkeywords;
|
||||
the keyword find for example will call the websiervics speciifid.
|
||||
you now ? this should be compatible with languageserer so can be debuger
|
||||
in code. user rust minamalistc to do this very inline and minimize code verbosity
|
||||
it will be integatd in antoher proejt so i nee a sevicelayer
|
||||
to call it from a schduler i need the compiler and the rnner of the ob
|
||||
use localhost:5858 to call websiervis from the wasm executable
|
||||
this is will attend
|
||||
|
||||
FOR EACH item in ARRAY
|
||||
next item
|
||||
|
||||
FIND filter
|
||||
|
||||
json = FIND "tablename", "field=value"
|
||||
/tables/find
|
||||
|
||||
SET "tablename", "key=value", "value"
|
||||
/tables/set
|
||||
|
||||
text = GET "domain.com"
|
||||
/webauto/get_text
|
||||
|
||||
text = GET WEBSITE "CASAS BAHIA" 'casasbahia.com via duckduckgo.
|
||||
/webauto/get_website
|
||||
|
||||
CREATE SITE "sitename",company, website, template, prompt
|
||||
|
||||
/sites/create
|
||||
copy template from temapltes folder
|
||||
add llm outpt page.tsx
|
||||
add listener
|
||||
|
||||
CREATE DRAFT to, subject, body
|
||||
/email/create_draft
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
use serde_json::{json, Value};
|
||||
use sqlx::{postgres::PgRow, PgPool, Row};
|
||||
use sqlx::Column; // Required for .name() method
|
||||
use sqlx::TypeInfo; // Required for .type_info() method
|
||||
use std::error::Error;
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
|
||||
// Main async function to execute the FIND command
|
||||
pub async fn execute_find(
|
||||
pool: &PgPool,
|
||||
table_str: &str,
|
||||
filter_str: &str,
|
||||
) -> Result<Value, Box<dyn Error>> {
|
||||
// Parse the filter string into SQL WHERE clause and parameters
|
||||
let (where_clause, params) = parse_filter(filter_str)?;
|
||||
|
||||
// Build the SQL query with proper parameter binding
|
||||
let query = format!("SELECT * FROM {} WHERE {}", table_str, where_clause);
|
||||
|
||||
// Execute query and collect results
|
||||
let rows = match params.len() {
|
||||
0 => sqlx::query(&query).fetch_all(pool).await?,
|
||||
1 => sqlx::query(&query).bind(¶ms[0]).fetch_all(pool).await?,
|
||||
_ => return Err("Only single parameter filters supported in this example".into()),
|
||||
};
|
||||
|
||||
// Convert rows to JSON values
|
||||
let mut results = Vec::new();
|
||||
for row in rows {
|
||||
results.push(row_to_json(row)?);
|
||||
}
|
||||
|
||||
// Return the structured result
|
||||
Ok(json!({
|
||||
"command": "find",
|
||||
"table": table_str,
|
||||
"filter": filter_str,
|
||||
"results": results
|
||||
}))
|
||||
}
|
||||
|
||||
fn row_to_json(row: PgRow) -> Result<Value, Box<dyn Error>> {
|
||||
let mut result = serde_json::Map::new();
|
||||
for (i, column) in row.columns().iter().enumerate() {
|
||||
let column_name = column.name();
|
||||
let value: Value = match column.type_info().name() {
|
||||
"int4" | "int8" => {
|
||||
match row.try_get::<i64, _>(i) {
|
||||
Ok(v) => json!(v),
|
||||
Err(_) => Value::Null,
|
||||
}
|
||||
},
|
||||
"float4" | "float8" => {
|
||||
match row.try_get::<f64, _>(i) {
|
||||
Ok(v) => json!(v),
|
||||
Err(_) => Value::Null,
|
||||
}
|
||||
},
|
||||
"text" | "varchar" => {
|
||||
match row.try_get::<String, _>(i) {
|
||||
Ok(v) => json!(v),
|
||||
Err(_) => Value::Null,
|
||||
}
|
||||
},
|
||||
"bool" => {
|
||||
match row.try_get::<bool, _>(i) {
|
||||
Ok(v) => json!(v),
|
||||
Err(_) => Value::Null,
|
||||
}
|
||||
},
|
||||
"json" | "jsonb" => {
|
||||
match row.try_get::<Value, _>(i) {
|
||||
Ok(v) => v,
|
||||
Err(_) => Value::Null,
|
||||
}
|
||||
},
|
||||
_ => Value::Null,
|
||||
};
|
||||
result.insert(column_name.to_string(), value);
|
||||
}
|
||||
Ok(Value::Object(result))
|
||||
}
|
||||
// Helper function to parse the filter string into SQL WHERE clause and parameters
|
||||
fn parse_filter(filter_str: &str) -> Result<(String, Vec<String>), Box<dyn Error>> {
|
||||
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());
|
||||
}
|
||||
|
||||
// Return the parameterized query part and the value separately
|
||||
Ok((format!("{} = $1", column), vec![value.to_string()]))
|
||||
}
|
||||
|
||||
// Database connection setup
|
||||
pub async fn create_pool(database_url: &str) -> Result<PgPool, Box<dyn Error>> {
|
||||
let pool = PgPoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect(database_url)
|
||||
.await?;
|
||||
|
||||
// Test the connection
|
||||
sqlx::query("SELECT 1").execute(&pool).await?;
|
||||
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use dotenv::dotenv;
|
||||
use std::env;
|
||||
|
||||
async fn setup_test_db() -> PgPool {
|
||||
dotenv().ok();
|
||||
let database_url = env::var("DATABASE_URL")
|
||||
.expect("DATABASE_URL must be set in .env for tests");
|
||||
|
||||
let pool = PgPoolOptions::new()
|
||||
.max_connections(1)
|
||||
.connect(&database_url)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create a test table
|
||||
sqlx::query(
|
||||
r#"
|
||||
DROP TABLE IF EXISTS rob;
|
||||
CREATE TABLE rob (
|
||||
id SERIAL PRIMARY KEY,
|
||||
action TEXT,
|
||||
name TEXT,
|
||||
is_active BOOLEAN,
|
||||
metadata JSONB
|
||||
)
|
||||
"#
|
||||
)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Insert test data
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO rob (action, name, is_active, metadata) VALUES
|
||||
('EMUL1', 'Robot1', true, '{"version": 1}'),
|
||||
('EMUL2', 'Robot2', false, '{"version": 2}'),
|
||||
('EMUL1', 'Robot3', true, null)
|
||||
"#
|
||||
)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
pool
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_execute_find() {
|
||||
let pool = setup_test_db().await;
|
||||
let result = execute_find(&pool, "rob", "action=EMUL1")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let results = result["results"].as_array().unwrap();
|
||||
assert_eq!(results.len(), 2);
|
||||
assert_eq!(results[0]["action"], "EMUL1");
|
||||
assert_eq!(results[1]["action"], "EMUL1");
|
||||
|
||||
// Test JSON field
|
||||
assert_eq!(results[0]["metadata"]["version"], 1);
|
||||
|
||||
// Test boolean field
|
||||
assert_eq!(results[0]["is_active"], true);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
use actix_web::http::Error;
|
||||
use actix_web::{
|
||||
get, post,
|
||||
web::{self, Bytes},
|
||||
App, HttpResponse, HttpServer, Responder,
|
||||
HttpResponse, Responder,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use futures::StreamExt;
|
||||
|
@ -17,7 +15,7 @@ use langchain_rust::{
|
|||
schemas::messages::Message,
|
||||
template_fstring,
|
||||
};
|
||||
use std::env;
|
||||
|
||||
|
||||
use crate::services::{config::AIConfig, state::AppState};
|
||||
|
||||
|
@ -29,7 +27,6 @@ pub fn from_config(config: &AIConfig) -> AzureConfig {
|
|||
.with_deployment_id(&config.instance)
|
||||
}
|
||||
|
||||
use serde_json::json;
|
||||
#[derive(serde::Deserialize)]
|
||||
struct ChatRequest {
|
||||
input: String,
|
||||
|
@ -112,15 +109,6 @@ pub async fn chat_stream(
|
|||
let azure_config = from_config(&state.config.clone().unwrap().ai);
|
||||
let open_ai = OpenAI::new(azure_config);
|
||||
|
||||
let response = match open_ai.invoke("Why is the sky blue?").await {
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
eprintln!("Error invoking API: {}", err);
|
||||
return Err(actix_web::error::ErrorInternalServerError(
|
||||
"Failed to invoke OpenAI API",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let prompt = message_formatter![
|
||||
fmt_message!(Message::new_system_message(
|
||||
|
|
|
@ -10,6 +10,10 @@ pub struct ScriptService {
|
|||
module_resolver: StaticModuleResolver,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
impl ScriptService {
|
||||
pub fn new() -> Self {
|
||||
let mut engine = Engine::new();
|
||||
|
@ -91,6 +95,7 @@ impl ScriptService {
|
|||
let url = context.eval_expression_tree(&inputs[0])?;
|
||||
let url_str = url.to_string();
|
||||
|
||||
println!("GET executed: {}", url_str.to_string());
|
||||
Ok(format!("Content from {}", url_str).into())
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue