diff --git a/add-req.sh b/add-req.sh index 6435579da..018428293 100755 --- a/add-req.sh +++ b/add-req.sh @@ -2,7 +2,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$SCRIPT_DIR" -OUTPUT_FILE="$SCRIPT_DIR/prompt.out" +OUTPUT_FILE="/tmp/prompt.out" rm -f "$OUTPUT_FILE" echo "Consolidated LLM Context" > "$OUTPUT_FILE" @@ -10,7 +10,6 @@ echo "Consolidated LLM Context" > "$OUTPUT_FILE" prompts=( "./prompts/dev/shared.md" "./Cargo.toml" - "./prompts/dev/generation.md" ) for file in "${prompts[@]}"; do @@ -24,19 +23,19 @@ dirs=( #"auth" #"automation" #"basic" - #"bot" + "bot" #"channels" "config" - #"context" + "context" #"email" - #"file" - #"llm" + "file" + "llm" #"llm_legacy" #"org" "session" "shared" #"tests" - #"tools" + "tools" #"web_automation" #"whatsapp" ) @@ -59,25 +58,10 @@ done # Additional specific files files=( "$PROJECT_ROOT/src/main.rs" - "$PROJECT_ROOT/scripts/containers/proxy.sh" - "$PROJECT_ROOT/scripts/containers/directory.sh" - "$PROJECT_ROOT/scripts/containers/bot.sh" - "$PROJECT_ROOT/scripts/containers/system.sh" - "$PROJECT_ROOT/scripts/containers/social.sh" - "$PROJECT_ROOT/scripts/containers/alm-ci.sh" - "$PROJECT_ROOT/scripts/containers/drive.sh" - "$PROJECT_ROOT/scripts/containers/tables.sh" - "$PROJECT_ROOT/scripts/containers/dns.sh" - "$PROJECT_ROOT/scripts/containers/doc-editor.sh" - "$PROJECT_ROOT/scripts/containers/host.sh" - "$PROJECT_ROOT/scripts/containers/vector-db.sh" - "$PROJECT_ROOT/scripts/containers/cache.sh" - "$PROJECT_ROOT/scripts/containers/desktop.sh" - "$PROJECT_ROOT/scripts/containers/meeting.sh" - "$PROJECT_ROOT/scripts/containers/email.sh" - "$PROJECT_ROOT/scripts/containers/alm.sh" - "$PROJECT_ROOT/scripts/containers/table-editor.sh" - "$PROJECT_ROOT/scripts/containers/webmail.sh" + "$PROJECT_ROOT/src/basic/keywords/mod.rs" + "$PROJECT_ROOT/src/basic/keywords/get.rs" + "$PROJECT_ROOT/src/basic/keywords/find.rs" + "$PROJECT_ROOT/src/basic/keywords/hear_talk.rs" ) @@ -108,3 +92,4 @@ echo "Context size: $FILE_SIZE bytes" cat "$OUTPUT_FILE" | xclip -selection clipboard echo "Content copied to clipboard (xclip)" +rm -f "$OUTPUT_FILE" diff --git a/prompts/dev/platform/add-container.sh b/prompts/dev/platform/add-container.sh deleted file mode 100644 index 5ad3e639f..000000000 --- a/prompts/dev/platform/add-container.sh +++ /dev/null @@ -1,16 +0,0 @@ -do not comment or echo anything - -keep lines condensed -always call it not own name. Eg.: proxy instead of Caddy. alm instead of forgejo. -use KISS priciple - -use local /opt/gbo/{logs, data, conf} exposed as - HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/" - HOST_DATA="$HOST_BASE/data" - HOST_CONF="$HOST_BASE/conf" - HOST_LOGS="$HOST_BASE/logs" - instead of using app original paths. -and use /opt/gbo/bin to put local binaries of installations -during sh exection, never touch files in /opt/gbo/{logs, data, conf} -use wget -use gbuser as system user diff --git a/scripts/containers/alm-ci.sh b/scripts/containers/alm-ci.sh deleted file mode 100644 index 5f34c98cb..000000000 --- a/scripts/containers/alm-ci.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/bash - -# Configuration -ALM_CI_NAME="CI" -ALM_CI_LABELS="gbo" -FORGEJO_RUNNER_VERSION="v6.3.1" -FORGEJO_RUNNER_BINARY="forgejo-runner-6.3.1-linux-amd64" -CONTAINER_IMAGE="images:debian/12" - -# Paths -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/alm-ci" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" -BIN_PATH="/opt/gbo/bin" -CONTAINER_NAME="${PARAM_TENANT}-alm-ci" - -# Create host directories -mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" || exit 1 -chmod -R 750 "$HOST_BASE" || exit 1 - -# Launch container -if ! lxc launch "$CONTAINER_IMAGE" "$CONTAINER_NAME" -c security.privileged=true; then - echo "Failed to launch container" - exit 1 -fi - -# Wait for container to be ready -for i in {1..10}; do - if lxc exec "$CONTAINER_NAME" -- bash -c "true"; then - break - fi - sleep 3 -done - - -# Container setup -lxc exec "$CONTAINER_NAME" -- bash -c " -set -e - -useradd --system --no-create-home --shell /bin/false $CONTAINER_NAME - -# Update and install dependencies -apt-get update && apt-get install -y wget git || { echo 'Package installation failed'; exit 1; } - -sudo apt update -sudo apt install -y curl gnupg ca-certificates git -apt-get update && apt-get install -y \ -build-essential cmake git pkg-config libjpeg-dev libtiff-dev \ -libpng-dev libavcodec-dev libavformat-dev libswscale-dev \ -libv4l-dev libatlas-base-dev gfortran python3-dev cpulimit \ -expect libxtst-dev libpng-dev - -sudo apt-get install -y libcairo2-dev libpango1.0-dev libgif-dev librsvg2-dev -sudo apt install xvfb -y - -sudo apt install -y \ - libnss3 \ - libatk1.0-0 \ - libatk-bridge2.0-0 \ - libcups2 \ - libdrm2 \ - libxkbcommon0 \ - libxcomposite1 \ - libxdamage1 \ - libxfixes3 \ - libxrandr2 \ - libgbm1 \ - libasound2 \ - libpangocairo-1.0-0 - -export OPENCV4NODEJS_DISABLE_AUTOBUILD=1 -export OPENCV_LIB_DIR=/usr/lib/x86_64-linux-gnu - -sudo apt install -y curl gnupg ca-certificates git - -# Install Node.js 22.x -curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash - -sudo apt install -y nodejs -npm install -g pnpm@latest - -# Install rust 1.85 -apt-get install -y libssl-dev pkg-config -sudo apt-get install -y \ - apt-transport-https \ - software-properties-common \ - gnupg \ - cmake \ - build-essential \ - clang \ - libclang-dev \ - libz-dev \ - libssl-dev \ - pkg-config - -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain 1.85.1 -y -source ~/.cargo/env -rustc --version - - -# Install Xvfb and other dependencies -sudo apt install -y xvfb libgbm-dev lxd-client - -# Create directories -mkdir -p \"$BIN_PATH\" /opt/gbo/data /opt/gbo/conf /opt/gbo/logs || { echo 'Directory creation failed'; exit 1; } - -# Download and install forgejo-runner -wget -O \"$BIN_PATH/forgejo-runner\" \"https://code.forgejo.org/forgejo/runner/releases/download/$FORGEJO_RUNNER_VERSION/$FORGEJO_RUNNER_BINARY\" || { echo 'Download failed'; exit 1; } -chmod +x \"$BIN_PATH/forgejo-runner\" || { echo 'chmod failed'; exit 1; } - -cd \"$BIN_PATH\" - -# Register runner -\"$BIN_PATH/forgejo-runner\" register --no-interactive \\ - --name \"$ALM_CI_NAME\" \\ - --instance \"$PARAM_ALM_CI_INSTANCE\" \\ - --token \"$PARAM_ALM_CI_TOKEN\" \\ - --labels \"$ALM_CI_LABELS\" || { echo 'Runner registration failed'; exit 1; } - -chown -R $CONTAINER_NAME:$CONTAINER_NAME /opt/gbo/bin /opt/gbo/data /opt/gbo/conf /opt/gbo/logs - -" - -# Set permissions -echo "[CONTAINER] Setting permissions..." -EMAIL_UID=$(lxc exec "$PARAM_TENANT"-alm-ci -- id -u $CONTAINER_NAME) -EMAIL_GID=$(lxc exec "$PARAM_TENANT"-alm-ci -- id -g $CONTAINER_NAME) -HOST_EMAIL_UID=$((100000 + EMAIL_UID)) -HOST_EMAIL_GID=$((100000 + EMAIL_GID)) -sudo chown -R "$HOST_EMAIL_UID:$HOST_EMAIL_GID" "$HOST_BASE" - - -# Add directory mappings -lxc config device add "$CONTAINER_NAME" almdata disk source="$HOST_DATA" path=/opt/gbo/data || exit 1 -lxc config device add "$CONTAINER_NAME" almconf disk source="$HOST_CONF" path=/opt/gbo/conf || exit 1 -lxc config device add "$CONTAINER_NAME" almlogs disk source="$HOST_LOGS" path=/opt/gbo/logs || exit 1 - - -lxc exec "$CONTAINER_NAME" -- bash -c " -# Create systemd service -cat > /etc/systemd/system/alm-ci.service < /etc/systemd/system/alm.service </dev/null || true -lxc config device add "$PARAM_TENANT"-alm alm-proxy proxy \ - listen=tcp:0.0.0.0:"$PARAM_ALM_PORT" \ - connect=tcp:127.0.0.1:"$PARAM_ALM_PORT" \ No newline at end of file diff --git a/scripts/containers/bot.sh b/scripts/containers/bot.sh deleted file mode 100644 index da226d591..000000000 --- a/scripts/containers/bot.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/bash - -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/bot" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" - -mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -chmod -R 750 "$HOST_BASE" - -lxc launch images:debian/12 "$PARAM_TENANT"-bot -c security.privileged=true -sleep 15 - -lxc exec "$PARAM_TENANT"-bot -- bash -c " - -apt-get update && apt-get install -y \ -build-essential cmake git pkg-config libjpeg-dev libtiff-dev \ -libpng-dev libavcodec-dev libavformat-dev libswscale-dev \ -libv4l-dev libatlas-base-dev gfortran python3-dev cpulimit \ -expect libxtst-dev libpng-dev - -sudo apt-get install -y libcairo2-dev libpango1.0-dev libgif-dev librsvg2-dev -sudo apt install xvfb -y - -sudo apt install -y \ - libnss3 \ - libatk1.0-0 \ - libatk-bridge2.0-0 \ - libcups2 \ - libdrm2 \ - libxkbcommon0 \ - libxcomposite1 \ - libxdamage1 \ - libxfixes3 \ - libxrandr2 \ - libgbm1 \ - libasound2 \ - libpangocairo-1.0-0 - -export OPENCV4NODEJS_DISABLE_AUTOBUILD=1 -export OPENCV_LIB_DIR=/usr/lib/x86_64-linux-gnu - -useradd --system --no-create-home --shell /bin/false gbuser -" - -BOT_UID=$(lxc exec "$PARAM_TENANT"-bot -- id -u gbuser) -BOT_GID=$(lxc exec "$PARAM_TENANT"-bot -- id -g gbuser) -HOST_BOT_UID=$((100000 + BOT_UID)) -HOST_BOT_GID=$((100000 + BOT_GID)) -chown -R "$HOST_BOT_UID:$HOST_BOT_GID" "$HOST_BASE" - -lxc config device add "$PARAM_TENANT"-bot botdata disk source="$HOST_DATA" path=/opt/gbo/data -lxc config device add "$PARAM_TENANT"-bot botconf disk source="$HOST_CONF" path=/opt/gbo/conf -lxc config device add "$PARAM_TENANT"-bot botlogs disk source="$HOST_LOGS" path=/opt/gbo/logs - -lxc exec "$PARAM_TENANT"-bot -- bash -c ' -mkdir -p /opt/gbo/data /opt/gbo/conf /opt/gbo/logs - -sudo apt update -sudo apt install -y curl gnupg ca-certificates git - -curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash - -sudo apt install -y nodejs - -sudo apt install -y xvfb libgbm-dev - -wget https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_128.0.6613.119-1_amd64.deb -sudo apt install ./google-chrome-stable_128.0.6613.119-1_amd64.deb - -cd /opt/gbo/data -git clone https://alm.pragmatismo.com.br/generalbots/botserver.git -cd botserver -npm install - -./node_modules/.bin/tsc -cd packages/default.gbui -npm install -npm run build - -chown -R gbuser:gbuser /opt/gbo - -# Create systemd service -sudo tee /etc/systemd/system/bot.service > /dev/null </dev/null || true -lxc config device add "$PARAM_TENANT"-bot bot-proxy proxy \ - listen=tcp:0.0.0.0:"$PARAM_BOT_PORT" \ - connect=tcp:127.0.0.1:"$PARAM_BOT_PORT" diff --git a/scripts/containers/cache.sh b/scripts/containers/cache.sh deleted file mode 100644 index 1e78013e9..000000000 --- a/scripts/containers/cache.sh +++ /dev/null @@ -1,7 +0,0 @@ -curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/valkey.gpg -echo "deb [signed-by=/usr/share/keyrings/valkey.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/valkey.list -sudo apt update -sudo apt install valkey-server - -sudo systemctl enable valkey-server -sudo systemctl start valkey-server diff --git a/scripts/containers/desktop.sh b/scripts/containers/desktop.sh deleted file mode 100644 index 6a3c9a4f5..000000000 --- a/scripts/containers/desktop.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/desktop" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" - -mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -chmod -R 750 "$HOST_BASE" - -lxc launch images:debian/12 "$PARAM_TENANT"-desktop -c security.privileged=true -sleep 15 - -lxc exec "$PARAM_TENANT"-desktop -- bash -c " - -apt-get update -apt-get install -y xvfb xrdp xfce4 xfce4-goodies -cat > /etc/xrdp/startwm.sh < /root/.xsession -chmod +x /root/.xsession - -apt install -y curl apt-transport-https gnupg -curl -s https://brave-browser-apt-release.s3.brave.com/brave-core.asc | gpg --dearmor > /usr/share/keyrings/brave-browser-archive-keyring.gpg -echo "deb [arch=amd64 signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main" > /etc/apt/sources.list.d/brave-browser-release.list -apt update && apt install -y brave-browser - -sudo apt install gnome-tweaks -/etc/environment - GTK_IM_MODULE=cedilla - QT_IM_MODULE=cedilla - -" -port=3389 -lxc config device remove "$PARAM_TENANT"-desktop "port-$port" 2>/dev/null || true -lxc config device add "$PARAM_TENANT"-desktop "port-$port" proxy listen=tcp:0.0.0.0:$port connect=tcp:127.0.0.1:$port diff --git a/scripts/containers/directory.sh b/scripts/containers/directory.sh deleted file mode 100644 index d6231d98e..000000000 --- a/scripts/containers/directory.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash - -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/directory" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" - -sudo mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -sudo chmod -R 750 "$HOST_BASE" - -lxc launch images:debian/12 "$PARAM_TENANT"-directory -c security.privileged=true -sleep 15 - -lxc exec "$PARAM_TENANT"-directory -- bash -c " -apt-get update && apt-get install -y wget libcap2-bin -wget -c https://github.com/zitadel/zitadel/releases/download/v2.71.2/zitadel-linux-amd64.tar.gz -O - | tar -xz -C /tmp -mkdir -p /opt/gbo/bin -mv /tmp/zitadel-linux-amd64/zitadel /opt/gbo/bin/zitadel -chmod +x /opt/gbo/bin/zitadel -sudo setcap 'cap_net_bind_service=+ep' /opt/gbo/bin/zitadel - -useradd --system --no-create-home --shell /bin/false gbuser -mkdir -p /opt/gbo/data /opt/gbo/conf /opt/gbo/logs -chown -R gbuser:gbuser /opt/gbo/data /opt/gbo/conf /opt/gbo/logs /opt/gbo/bin -" - -GBUSER_UID=$(lxc exec "$PARAM_TENANT"-directory -- id -u gbuser) -GBUSER_GID=$(lxc exec "$PARAM_TENANT"-directory -- id -g gbuser) -HOST_GBUSER_UID=$((100000 + GBUSER_UID)) -HOST_GBUSER_GID=$((100000 + GBUSER_GID)) -sudo chown -R "$HOST_GBUSER_UID:$HOST_GBUSER_GID" "$HOST_BASE" - -lxc config device add "$PARAM_TENANT"-directory directorydata disk source="$HOST_DATA" path=/opt/gbo/data -lxc config device add "$PARAM_TENANT"-directory directoryconf disk source="$HOST_CONF" path=/opt/gbo/conf -lxc config device add "$PARAM_TENANT"-directory directorylogs disk source="$HOST_LOGS" path=/opt/gbo/logs - -lxc exec "$PARAM_TENANT"-directory -- bash -c " -chown -R gbuser:gbuser /opt/gbo/data /opt/gbo/conf /opt/gbo/logs /opt/gbo/bin - -cat > /etc/systemd/system/directory.service </dev/null || true -lxc config device add "$PARAM_TENANT"-directory directory-proxy proxy \ - listen=tcp:0.0.0.0:"$PARAM_DIRECTORY_PORT" \ - connect=tcp:127.0.0.1:"$PARAM_DIRECTORY_PORT" diff --git a/scripts/containers/dns.sh b/scripts/containers/dns.sh deleted file mode 100644 index a5e3d21ce..000000000 --- a/scripts/containers/dns.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/bash -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/dns" -HOST_CONF="$HOST_BASE/conf" -HOST_DATA="$HOST_BASE/data" -HOST_LOGS="$HOST_BASE/logs" -mkdir -p "$HOST_BASE" "$HOST_CONF" "$HOST_DATA" "$HOST_LOGS" -chmod -R 750 "$HOST_BASE" - -lxc network set lxdbr0 user.dns.nameservers $PARAM_DNS_INTERNAL_IP,8.8.8.8,1.1.1.1 -lxc network set lxdbr0 dns.mode managed - -# Clear existing rules -sudo iptables -F - -# Allow DNS traffic -sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT -sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT -sudo iptables -A FORWARD -p udp --dport 53 -j ACCEPT -sudo iptables -A FORWARD -p tcp --dport 53 -j ACCEPT - -# Enable NAT -sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE - -# Save rules (if using iptables-persistent) -sudo netfilter-persistent save - -lxc launch images:debian/12 "${PARAM_TENANT}-dns" -c security.privileged=true -until lxc exec "${PARAM_TENANT}-dns" -- true; do sleep 3; done - -lxc config device remove pragmatismo-dns dns-udp -lxc config device remove pragmatismo-dns dns-tcp - -# Forward HOST's public IP:53 → CONTAINER's 0.0.0.0:53 -lxc config device add pragmatismo-dns dns-udp proxy listen=udp:$GB_PUBLIC_IP:53 connect=udp:0.0.0.0:53 -lxc config device add pragmatismo-dns dns-tcp proxy listen=tcp:$GB_PUBLIC_IP:53 connect=tcp:0.0.0.0:53 - - -lxc exec "${PARAM_TENANT}-dns" -- bash -c " -mkdir /opt/gbo -mkdir /opt/gbo/{bin,conf,data,logs} - -echo 'nameserver 8.8.8.8' > /etc/resolv.conf - - -apt-get upgrade -y && apt-get install -y wget -wget -qO /opt/gbo/bin/coredns https://github.com/coredns/coredns/releases/download/v1.12.4/coredns_1.12.4_linux_amd64.tgz -tar -xzf /opt/gbo/bin/coredns -C /opt/gbo/bin/ -useradd --system --no-create-home --shell /bin/false gbuser -setcap cap_net_bind_service=+ep /opt/gbo/bin/coredns - - -cat > /etc/systemd/system/dns.service < /etc/apt/sources.list.d/collaboraonline.sources -Types: deb -URIs: https://www.collaboraoffice.com/repos/CollaboraOnline/24.04/customer-deb-$customer_hash -Suites: ./ -Signed-By: /usr/share/keyrings/collaboraonline-release-keyring.gpg -EOF - -apt update && apt install coolwsd collabora-online-brand -" - -lxc config device remove "$PARAM_TENANT"-doc-editor doc-proxy 2>/dev/null || true -lxc config device add "$PARAM_TENANT"-doc-editor doc-proxy proxy \ - listen=tcp:0.0.0.0:"$PARAM_DOC_PORT" \ - connect=tcp:127.0.0.1:9980 \ No newline at end of file diff --git a/scripts/containers/drive.sh b/scripts/containers/drive.sh deleted file mode 100644 index 4a9eda378..000000000 --- a/scripts/containers/drive.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -STORAGE_PATH="/opt/gbo/tenants/$PARAM_TENANT/drive/data" -LOGS_PATH="/opt/gbo/tenants/$PARAM_TENANT/drive/logs" - -mkdir -p "${STORAGE_PATH}" "${LOGS_PATH}" -chmod -R 770 "${STORAGE_PATH}" "${LOGS_PATH}" -chown -R 100999:100999 "${STORAGE_PATH}" "${LOGS_PATH}" - -lxc launch images:debian/12 "${PARAM_TENANT}-drive" -c security.privileged=true -sleep 15 - -lxc config device add "${PARAM_TENANT}-drive" storage disk source="${STORAGE_PATH}" path=/data -lxc config device add "${PARAM_TENANT}-drive" logs disk source="${LOGS_PATH}" path=/var/log/minio - -lxc exec "${PARAM_TENANT}-drive" -- bash -c ' -apt-get update && apt-get install -y wget -wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /usr/local/bin/minio -chmod +x /usr/local/bin/minio - -wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /usr/local/bin/mc -chmod +x /usr/local/bin/mc - - -useradd -r -s /bin/false minio-user || true -mkdir -p /var/log/minio /data -chown -R minio-user:minio-user /var/log/minio /data - -cat > /etc/systemd/system/minio.service </dev/null || true -lxc config device add "${PARAM_TENANT}-drive" minio-proxy proxy \ - listen=tcp:0.0.0.0:"${PARAM_DRIVE_API_PORT}" \ - connect=tcp:127.0.0.1:"${PARAM_DRIVE_API_PORT}" - -lxc config device remove "${PARAM_TENANT}-drive" console-proxy 2>/dev/null || true -lxc config device add "${PARAM_TENANT}-drive" console-proxy proxy \ - listen=tcp:0.0.0.0:"${PARAM_DRIVE_PORT}" \ - connect=tcp:127.0.0.1:"${PARAM_DRIVE_PORT}" diff --git a/scripts/containers/email.sh b/scripts/containers/email.sh deleted file mode 100644 index 94a166cee..000000000 --- a/scripts/containers/email.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/bash -PUBLIC_INTERFACE="eth0" # Your host's public network interface - -# Configure firewall -echo "[HOST] Configuring firewall..." -sudo iptables -A FORWARD -i $PUBLIC_INTERFACE -o lxcbr0 -p tcp -m multiport --dports 25,80,110,143,465,587,993,995,4190 -j ACCEPT -sudo iptables -A FORWARD -i lxcbr0 -o $PUBLIC_INTERFACE -m state --state RELATED,ESTABLISHED -j ACCEPT -sudo iptables -t nat -A POSTROUTING -o $PUBLIC_INTERFACE -j MASQUERADE - -# IPv6 firewall -sudo ip6tables -A FORWARD -i $PUBLIC_INTERFACE -o lxcbr0 -p tcp -m multiport --dports 25,80,110,143,465,587,993,995,4190 -j ACCEPT -sudo ip6tables -A FORWARD -i lxcbr0 -o $PUBLIC_INTERFACE -m state --state RELATED,ESTABLISHED -j ACCEPT - -# Save iptables rules permanently (adjust based on your distro) -if command -v iptables-persistent >/dev/null; then - sudo iptables-save | sudo tee /etc/iptables/rules.v4 - sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 -fi - - -# ------------------------- CONTAINER SETUP ------------------------- - -# Create directory structure -echo "[CONTAINER] Creating directories..." -HOST_BASE="/opt/email" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" - -sudo mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -sudo chmod -R 750 "$HOST_BASE" - -# Launch container -echo "[CONTAINER] Launching LXC container..." -lxc launch images:debian/12 "$PARAM_TENANT"-email -c security.privileged=true -sleep 15 - -echo "[CONTAINER] Installing Stalwart Mail..." -lxc exec "$PARAM_TENANT"-email -- bash -c " - -echo "nameserver $PARAM_DNS_INTERNAL_IP" > /etc/resolv.conf - -apt install resolvconf -y -apt-get update && apt-get install -y wget libcap2-bin -wget -O /tmp/stalwart.tar.gz https://github.com/stalwartlabs/stalwart/releases/download/v0.13.1/stalwart-x86_64-unknown-linux-gnu.tar.gz - -tar -xzf /tmp/stalwart.tar.gz -C /tmp -mkdir -p /opt/gbo/bin -mv /tmp/stalwart /opt/gbo/bin/stalwart -chmod +x /opt/gbo/bin/stalwart -sudo setcap 'cap_net_bind_service=+ep' /opt/gbo/bin/stalwart -rm /tmp/stalwart.tar.gz - -useradd --system --no-create-home --shell /bin/false email -mkdir -p /opt/gbo/data /opt/gbo/conf /opt/gbo/logs -chown -R email:email /opt/gbo/data /opt/gbo/conf /opt/gbo/logs /opt/gbo/bin -" - -# Set permissions -echo "[CONTAINER] Setting permissions..." -EMAIL_UID=$(lxc exec "$PARAM_TENANT"-email -- id -u email) -EMAIL_GID=$(lxc exec "$PARAM_TENANT"-email -- id -g email) -HOST_EMAIL_UID=$((100000 + EMAIL_UID)) -HOST_EMAIL_GID=$((100000 + EMAIL_GID)) -sudo chown -R "$HOST_EMAIL_UID:$HOST_EMAIL_GID" "$HOST_BASE" - -# Mount directories -echo "[CONTAINER] Mounting directories..." -lxc config device add "$PARAM_TENANT"-email emaildata disk source="$HOST_DATA" path=/opt/gbo/data -lxc config device add "$PARAM_TENANT"-email emailconf disk source="$HOST_CONF" path=/opt/gbo/conf -lxc config device add "$PARAM_TENANT"-email emaillogs disk source="$HOST_LOGS" path=/opt/gbo/logs - -# Create systemd service -echo "[CONTAINER] Creating email service..." -lxc exec "$PARAM_TENANT"-email -- bash -c " -chown -R email:email /opt/gbo/data /opt/gbo/conf /opt/gbo/logs /opt/gbo/bin - -cat > /etc/systemd/system/email.service </dev/null || true - lxc config device add "$PARAM_TENANT"-email "port-$port" proxy \ - listen=tcp:0.0.0.0:$port \ - listen=tcp:[::]:$port \ - connect=tcp:127.0.0.1:$port -done diff --git a/scripts/containers/host.sh b/scripts/containers/host.sh deleted file mode 100644 index 27ad2c96c..000000000 --- a/scripts/containers/host.sh +++ /dev/null @@ -1,30 +0,0 @@ -sudo apt install sshfs -y -lxc init -lxc storage create default dir -lxc profile device add default root disk path=/ pool=default - -sudo apt update && sudo apt install -y bridge-utils - -# Enable IP forwarding -echo "[HOST] Enabling IP forwarding..." -echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf -sudo sysctl -p - -wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb -sudo dpkg -i cuda-keyring_1.1-1_all.deb -sudo apt-get update - - - - - - - - -sudo apt purge '^nvidia-*' # Clean existing drivers -sudo add-apt-repository ppa:graphics-drivers/ppa -sudo apt update -sudo apt install nvidia-driver-470-server # Most stable for Kepler GPUs - -wget https://developer.download.nvidia.com/compute/cuda/11.0.3/local_installers/cuda_11.0.3_450.51.06_linux.run -sudo sh cuda_11.0.3_450.51.06_linux.run --override diff --git a/scripts/containers/meeting.sh b/scripts/containers/meeting.sh deleted file mode 100644 index 192d70921..000000000 --- a/scripts/containers/meeting.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash - -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/meeting" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" - -mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -chmod -R 750 "$HOST_BASE" - -lxc launch images:debian/12 "$PARAM_TENANT"-meeting -c security.privileged=true -sleep 15 - -lxc exec "$PARAM_TENANT"-meeting -- bash -c " - -apt-get update && apt-get install -y wget coturn -mkdir -p /opt/gbo/bin -cd /opt/gbo/bin -wget -q https://github.com/livekit/livekit/releases/download/v1.8.4/livekit_1.8.4_linux_amd64.tar.gz -tar -xzf livekit*.tar.gz -rm livekit_1.8.4_linux_amd64.tar.gz -chmod +x livekit-server - -while netstat -tuln | grep -q \":$PARAM_MEETING_TURN_PORT \"; do - ((PARAM_MEETING_TURN_PORT++)) -done - -useradd --system --no-create-home --shell /bin/false gbuser - -" - -MEETING_UID=$(lxc exec "$PARAM_TENANT"-meeting -- id -u gbuser) -MEETING_GID=$(lxc exec "$PARAM_TENANT"-meeting -- id -g gbuser) -HOST_MEETING_UID=$((100000 + MEETING_UID)) -HOST_MEETING_GID=$((100000 + MEETING_GID)) -chown -R "$HOST_MEETING_UID:$HOST_MEETING_GID" "$HOST_BASE" - -lxc config device add "$PARAM_TENANT"-meeting meetingdata disk source="$HOST_DATA" path=/opt/gbo/data -lxc config device add "$PARAM_TENANT"-meeting meetingconf disk source="$HOST_CONF" path=/opt/gbo/conf -lxc config device add "$PARAM_TENANT"-meeting meetinglogs disk source="$HOST_LOGS" path=/opt/gbo/logs - -lxc exec "$PARAM_TENANT"-meeting -- bash -c " - -mkdir -p /opt/gbo/data /opt/gbo/conf /opt/gbo/logs -chown -R gbuser:gbuser /opt/gbo/data /opt/gbo/conf /opt/gbo/logs - -sudo chown gbuser:gbuser /var/run/turnserver.pid - - -cat > /etc/systemd/system/meeting.service < /etc/systemd/system/meeting-turn.service </dev/null || true -lxc config device add "$PARAM_TENANT"-meeting meeting-proxy proxy \ - listen=tcp:0.0.0.0:"$PARAM_MEETING_PORT" \ - connect=tcp:127.0.0.1:"$PARAM_MEETING_PORT" \ No newline at end of file diff --git a/scripts/containers/proxy.sh b/scripts/containers/proxy.sh deleted file mode 100644 index 97bbee605..000000000 --- a/scripts/containers/proxy.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/proxy" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" -mkdir -p "$HOST_BASE" "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -chmod 750 "$HOST_BASE" "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" - -lxc launch images:debian/12 "$PARAM_TENANT"-proxy -c security.privileged=true -sleep 15 - -lxc exec "$PARAM_TENANT"-proxy -- bash -c " -mkdir -p /opt/gbo/{bin,data,conf,logs} -apt-get update && apt-get install -y wget libcap2-bin -wget -q https://github.com/caddyserver/caddy/releases/download/v2.10.0-beta.3/caddy_2.10.0-beta.3_linux_amd64.tar.gz -tar -xzf caddy_2.10.0-beta.3_linux_amd64.tar.gz -C /opt/gbo/bin -rm caddy_2.10.0-beta.3_linux_amd64.tar.gz -chmod 750 /opt/gbo/bin/caddy -setcap 'cap_net_bind_service=+ep' /opt/gbo/bin/caddy -useradd --create-home --system --shell /usr/sbin/nologin gbuser -chown -R gbuser:gbuser /opt/gbo/{bin,data,conf,logs} -" - -lxc config device add "$PARAM_TENANT"-proxy data disk source="$HOST_DATA" path=/opt/gbo/data -lxc config device add "$PARAM_TENANT"-proxy conf disk source="$HOST_CONF" path=/opt/gbo/conf -lxc config device add "$PARAM_TENANT"-proxy logs disk source="$HOST_LOGS" path=/opt/gbo/logs - -lxc exec "$PARAM_TENANT"-proxy -- bash -c " -cat > /etc/systemd/system/proxy.service </dev/null || true - lxc config device add "$PARAM_TENANT"-proxy "port-$port" proxy listen=tcp:0.0.0.0:$port connect=tcp:127.0.0.1:$port - done - -lxc config set "$PARAM_TENANT"-proxy security.syscalls.intercept.mknod true -lxc config set "$PARAM_TENANT"-proxy security.syscalls.intercept.setxattr true diff --git a/scripts/containers/social.sh b/scripts/containers/social.sh deleted file mode 100644 index 1db61e526..000000000 --- a/scripts/containers/social.sh +++ /dev/null @@ -1 +0,0 @@ -https://www.brasil247.com/mundo/meta-quer-automatizar-totalmente-publicidade-com-ia-ate-2026-diz-wsj \ No newline at end of file diff --git a/scripts/containers/system.sh b/scripts/containers/system.sh deleted file mode 100644 index 66973d4d2..000000000 --- a/scripts/containers/system.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/system" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" -HOST_BIN="$HOST_BASE/bin" -BIN_PATH="/opt/gbo/bin" -CONTAINER_NAME="${PARAM_TENANT}-system" - -# Create host directories -mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" || exit 1 -chmod -R 750 "$HOST_BASE" || exit 1 - - -lxc launch images:debian/12 $CONTAINER_NAME -c security.privileged=true -sleep 15 - -lxc exec $CONTAINER_NAME -- bash -c ' - -apt-get update && apt-get install -y wget curl unzip git - - -useradd -r -s /bin/false gbuser || true -mkdir -p /opt/gbo/logs /opt/gbo/bin /opt/gbo/data /opt/gbo/conf -chown -R gbuser:gbuser /opt/gbo/ - -wget https://github.com/ggml-org/llama.cpp/releases/download/b6148/llama-b6148-bin-ubuntu-x64.zip -mkdir llm -mv llama-b6148-bin-ubuntu-x64.zip llm -cd llm -unzip llama-b6148-bin-ubuntu-x64.zip -mv build/bin/* . -rm build/bin -r -rm llama-b6148-bin-ubuntu-x64.zip - -sudo apt install lib-pq -wget https://huggingface.co/bartowski/DeepSeek-R1-Distill-Qwen-1.5B-GGUF/resolve/main/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf -wget https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf/resolve/main/bge-small-en-v1.5-f32.gguf - -sudo curl -fsSLo /usr/share/keyrings/brave-browser-beta-archive-keyring.gpg https://brave-browser-apt-beta.s3.brave.com/brave-browser-beta-archive-keyring.gpg -sudo curl -fsSLo /etc/apt/sources.list.d/brave-browser-beta.sources https://brave-browser-apt-beta.s3.brave.com/brave-browser.sources -sudo apt update - -sudo apt install brave-browser-beta - -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -source "$HOME/.cargo/env" -git clone https://alm.pragmatismo.com.br/generalbots/gbserver - -apt install -y build-essential \ - pkg-config \ - libssl-dev \ - gcc-multilib \ - g++-multilib \ - clang \ - lld \ - binutils-dev \ - libudev-dev \ - libdbus-1-dev - - -cat > /etc/systemd/system/system.service </dev/null || true -lxc config device add $CONTAINER_NAME proxy proxy \ - listen=tcp:0.0.0.0:"${PARAM_SYSTEM_PORT}" \ - connect=tcp:127.0.0.1:"${PARAM_SYSTEM_PORT}" diff --git a/scripts/containers/table-editor.sh b/scripts/containers/table-editor.sh deleted file mode 100644 index 3231f25e3..000000000 --- a/scripts/containers/table-editor.sh +++ /dev/null @@ -1,86 +0,0 @@ - #!/bin/bash - -# Fixed container name -CONTAINER_NAME="$PARAM_TENANT-table-editor" - -TABLE_EDITOR_PORT="5757" - -# Paths -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/table-editor" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" -BIN_PATH="/opt/gbo/bin" - -# Create host directories -mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -chmod -R 750 "$HOST_BASE" - -# Launch container -lxc launch images:debian/12 "$CONTAINER_NAME" -c security.privileged=true - -# Wait for container to be ready -sleep 10 - -# Container setup -lxc exec "$CONTAINER_NAME" -- bash -c " -useradd --system --no-create-home --shell /bin/false gbuser -apt-get update -apt-get install -y wget curl - -# Create directories -mkdir -p \"$BIN_PATH\" /opt/gbo/data /opt/gbo/conf /opt/gbo/logs - -# Download and install NocoDB binary -cd \"$BIN_PATH\" -curl http://get.nocodb.com/linux-x64 -o nocodb -L -chmod +x nocodb -" - -# Set permissions -TE_UID=$(lxc exec "$CONTAINER_NAME" -- id -u gbuser) -TE_GID=$(lxc exec "$CONTAINER_NAME" -- id -g gbuser) -HOST_TE_UID=$((100000 + TE_UID)) -HOST_TE_GID=$((100000 + TE_GID)) -chown -R "$HOST_TE_UID:$HOST_TE_GID" "$HOST_BASE" - -# Add directory mappings -lxc config device add "$CONTAINER_NAME" tedata disk source="$HOST_DATA" path=/opt/gbo/data -lxc config device add "$CONTAINER_NAME" teconf disk source="$HOST_CONF" path=/opt/gbo/conf -lxc config device add "$CONTAINER_NAME" telogs disk source="$HOST_LOGS" path=/opt/gbo/logs - - - - -# Create systemd service -lxc exec "$CONTAINER_NAME" -- bash -c " -cat > /etc/systemd/system/table-editor.service </dev/null; do - echo \"Waiting for PostgreSQL to start on port $PARAM_TABLES_PORT...\" - sleep 3 -done - -sudo -u postgres psql -p $PARAM_TABLES_PORT -c \"CREATE USER $PARAM_TENANT WITH PASSWORD '$PARAM_TABLES_PASSWORD';\" -sudo -u postgres psql -p $PARAM_TABLES_PORT -c \"CREATE DATABASE ${PARAM_TENANT}_db OWNER $PARAM_TENANT;\" -sudo -u postgres psql -p $PARAM_TABLES_PORT -c \"GRANT ALL PRIVILEGES ON DATABASE ${PARAM_TENANT}_db TO $PARAM_TENANT;\" - -" - - -lxc config device remove "$PARAM_TENANT"-tables postgres-proxy 2>/dev/null || true -lxc config device add "$PARAM_TENANT"-tables postgres-proxy proxy \ - listen=tcp:0.0.0.0:"$PARAM_TABLES_PORT" \ - connect=tcp:127.0.0.1:"$PARAM_TABLES_PORT" - -echo "PostgreSQL setup completed successfully!" -echo "Database: ${PARAM_TENANT}_db" -echo "User: $PARAM_TENANT" -echo "Password: $PARAM_TABLES_PASSWORD" -echo "Port: $PARAM_TABLES_PORT" diff --git a/scripts/containers/vector-db.sh b/scripts/containers/vector-db.sh deleted file mode 100644 index 43c17092c..000000000 --- a/scripts/containers/vector-db.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -wget https://github.com/qdrant/qdrant/releases/latest/download/qdrant-x86_64-unknown-linux-gnu.tar.gz -tar -xzf qdrant-x86_64-unknown-linux-gnu.tar.gz -./qdrant diff --git a/scripts/containers/webmail.sh b/scripts/containers/webmail.sh deleted file mode 100644 index 078791011..000000000 --- a/scripts/containers/webmail.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -HOST_BASE="/opt/gbo/tenants/$PARAM_TENANT/webmail" -HOST_DATA="$HOST_BASE/data" -HOST_CONF="$HOST_BASE/conf" -HOST_LOGS="$HOST_BASE/logs" - -PARAM_RC_VERSION="1.6.6" - -mkdir -p "$HOST_DATA" "$HOST_CONF" "$HOST_LOGS" -chmod -R 750 "$HOST_BASE" - -lxc launch images:debian/12 "$PARAM_TENANT"-webmail -c security.privileged=true -sleep 15 - -RC_PATH="/opt/gbo/data" - -lxc exec "$PARAM_TENANT"-webmail -- bash -c ' -# Install prerequisites -apt install -y ca-certificates apt-transport-https lsb-release gnupg wget - -# Add the Sury PHP repository (official for Debian) -wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg -sh -c '\''echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'\'' - -# Update and install PHP 8.1 -apt update -apt install -y \ - php8.1 \ - php8.1-fpm \ - php8.1-imap \ - php8.1-pgsql \ - php8.1-mbstring \ - php8.1-xml \ - php8.1-curl \ - php8.1-zip \ - php8.1-cli \ - php8.1-intl \ - php8.1-dom - -# Restart PHP-FPM -systemctl restart php8.1-fpm - -mkdir -p '"$RC_PATH"' -wget -q https://github.com/roundcube/roundcubemail/releases/download/'"$PARAM_RC_VERSION"'/roundcubemail-'"$PARAM_RC_VERSION"'-complete.tar.gz -tar -xzf roundcubemail-*.tar.gz -mv roundcubemail-'"$PARAM_RC_VERSION"'/* '"$RC_PATH"' -rm -rf roundcubemail-* - -mkdir -p /opt/gbo/logs - -chmod 750 '"$RC_PATH"' -find '"$RC_PATH"' -type d -exec chmod 750 {} \; -find '"$RC_PATH"' -type f -exec chmod 640 {} \; - -' - -WEBMAIL_UID=$(lxc exec "$PARAM_TENANT"-webmail -- id -u www-data) -WEBMAIL_GID=$(lxc exec "$PARAM_TENANT"-webmail -- id -g www-data) -HOST_WEBMAIL_UID=$((100000 + WEBMAIL_UID)) -HOST_WEBMAIL_GID=$((100000 + WEBMAIL_GID)) -chown -R "$HOST_WEBMAIL_UID:$HOST_WEBMAIL_GID" "$HOST_BASE" - -lxc config device add "$PARAM_TENANT"-webmail webmaildata disk source="$HOST_DATA" path="$RC_PATH" -lxc config device add "$PARAM_TENANT"-webmail webmaillogs disk source="$HOST_LOGS" path=/opt/gbo/logs - -lxc exec "$PARAM_TENANT"-webmail -- bash -c " -chown -R www-data:www-data '"$RC_PATH"' /opt/gbo/logs -cat > /etc/systemd/system/webmail.service </dev/null; then - echo "Port $PARAM_WEBMAIL_PORT is already in use. Please choose a different port." - exit 1 -fi - - -lxc config device remove "$PARAM_TENANT"-webmail webmail-proxy 2>/dev/null || true -lxc config device add "$PARAM_TENANT"-webmail webmail-proxy proxy \ - listen=tcp:0.0.0.0:"$PARAM_WEBMAIL_PORT" \ - connect=tcp:127.0.0.1:"$PARAM_WEBMAIL_PORT" \ No newline at end of file diff --git a/src/auth/mod.rs b/src/auth/mod.rs index 704d13fd2..b27e5d86e 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -1,14 +1,18 @@ +use actix_web::{web, HttpResponse, Result}; use argon2::{ password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, Argon2, }; use diesel::pg::PgConnection; use diesel::prelude::*; +use log::{error, warn}; use redis::Client; +use std::collections::HashMap; use std::sync::Arc; use uuid::Uuid; use crate::shared; +use crate::shared::state::AppState; pub struct AuthService { pub conn: PgConnection, @@ -141,3 +145,91 @@ impl AuthService { Ok(user) } } + +#[actix_web::get("/api/auth")] +async fn auth_handler( + data: web::Data, + web::Query(params): web::Query>, +) -> Result { + let _token = params.get("token").cloned().unwrap_or_default(); + let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(); + let bot_id = if let Ok(bot_guid) = std::env::var("BOT_GUID") { + match Uuid::parse_str(&bot_guid) { + Ok(uuid) => uuid, + Err(e) => { + warn!("Invalid BOT_GUID from env: {}", e); + return Ok(HttpResponse::BadRequest() + .json(serde_json::json!({"error": "Invalid BOT_GUID"}))); + } + } + } else { + warn!("BOT_GUID not set in environment, using nil UUID"); + Uuid::nil() + }; + + let session = { + let mut sm = data.session_manager.lock().await; + match sm.get_or_create_user_session(user_id, bot_id, "Auth Session") { + Ok(Some(s)) => s, + Ok(None) => { + error!("Failed to create session"); + return Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": "Failed to create session"}))); + } + Err(e) => { + error!("Failed to create session: {}", e); + return Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": e.to_string()}))); + } + } + }; + + let session_id_clone = session.id.clone(); + let auth_script_path = "./templates/annoucements.gbai/annoucements.gbdialog/auth.bas"; + let auth_script = match std::fs::read_to_string(auth_script_path) { + Ok(content) => content, + Err(_) => r#"SET_USER "00000000-0000-0000-0000-000000000001""#.to_string(), + }; + + let script_service = crate::basic::ScriptService::new(Arc::clone(&data), session.clone()); + match script_service + .compile(&auth_script) + .and_then(|ast| script_service.run(&ast)) + { + Ok(result) => { + if result.to_string() == "false" { + error!("Auth script returned false, authentication failed"); + return Ok(HttpResponse::Unauthorized() + .json(serde_json::json!({"error": "Authentication failed"}))); + } + } + Err(e) => { + error!("Failed to run auth script: {}", e); + return Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": "Auth failed"}))); + } + } + + let session = { + let mut sm = data.session_manager.lock().await; + match sm.get_session_by_id(session_id_clone) { + Ok(Some(s)) => s, + Ok(None) => { + error!("Failed to retrieve session"); + return Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": "Failed to retrieve session"}))); + } + Err(e) => { + error!("Failed to retrieve session: {}", e); + return Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": e.to_string()}))); + } + } + }; + + Ok(HttpResponse::Ok().json(serde_json::json!({ + "user_id": session.user_id, + "session_id": session.id, + "status": "authenticated" + }))) +} diff --git a/src/bot/mod.rs b/src/bot/mod.rs index 3e03805d3..e67679b1b 100644 --- a/src/bot/mod.rs +++ b/src/bot/mod.rs @@ -7,7 +7,6 @@ use chrono::Utc; use log::{debug, error, info, warn}; use serde_json; use std::collections::HashMap; -use std::fs; use std::sync::Arc; use tokio::sync::mpsc; use uuid::Uuid; @@ -857,186 +856,6 @@ async fn websocket_handler( Ok(res) } -#[actix_web::get("/api/auth")] -async fn auth_handler( - data: web::Data, - web::Query(params): web::Query>, -) -> Result { - let _token = params.get("token").cloned().unwrap_or_default(); - let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(); - let bot_id = if let Ok(bot_guid) = std::env::var("BOT_GUID") { - match Uuid::parse_str(&bot_guid) { - Ok(uuid) => uuid, - Err(e) => { - warn!("Invalid BOT_GUID from env: {}", e); - return Ok(HttpResponse::BadRequest() - .json(serde_json::json!({"error": "Invalid BOT_GUID"}))); - } - } - } else { - warn!("BOT_GUID not set in environment, using nil UUID"); - Uuid::nil() - }; - - let session = { - let mut sm = data.session_manager.lock().await; - match sm.get_or_create_user_session(user_id, bot_id, "Auth Session") { - Ok(Some(s)) => s, - Ok(None) => { - error!("Failed to create session"); - return Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": "Failed to create session"}))); - } - Err(e) => { - error!("Failed to create session: {}", e); - return Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": e.to_string()}))); - } - } - }; - - let session_id_clone = session.id.clone(); - let auth_script_path = "./templates/annoucements.gbai/annoucements.gbdialog/auth.bas"; - let auth_script = match std::fs::read_to_string(auth_script_path) { - Ok(content) => content, - Err(_) => r#"SET_USER "00000000-0000-0000-0000-000000000001""#.to_string(), - }; - - let script_service = crate::basic::ScriptService::new(Arc::clone(&data), session.clone()); - match script_service - .compile(&auth_script) - .and_then(|ast| script_service.run(&ast)) - { - Ok(result) => { - if result.to_string() == "false" { - error!("Auth script returned false, authentication failed"); - return Ok(HttpResponse::Unauthorized() - .json(serde_json::json!({"error": "Authentication failed"}))); - } - } - Err(e) => { - error!("Failed to run auth script: {}", e); - return Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": "Auth failed"}))); - } - } - - let session = { - let mut sm = data.session_manager.lock().await; - match sm.get_session_by_id(session_id_clone) { - Ok(Some(s)) => s, - Ok(None) => { - error!("Failed to retrieve session"); - return Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": "Failed to retrieve session"}))); - } - Err(e) => { - error!("Failed to retrieve session: {}", e); - return Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": e.to_string()}))); - } - } - }; - - Ok(HttpResponse::Ok().json(serde_json::json!({ - "user_id": session.user_id, - "session_id": session.id, - "status": "authenticated" - }))) -} - -#[actix_web::get("/api/whatsapp/webhook")] -async fn whatsapp_webhook_verify( - data: web::Data, - web::Query(params): web::Query>, -) -> Result { - let empty = String::new(); - let mode = params.get("hub.mode").unwrap_or(&empty); - let token = params.get("hub.verify_token").unwrap_or(&empty); - let challenge = params.get("hub.challenge").unwrap_or(&empty); - info!( - "Verification params - mode: {}, token: {}, challenge: {}", - mode, token, challenge - ); - - match data.whatsapp_adapter.verify_webhook(mode, token, challenge) { - Ok(challenge_response) => Ok(HttpResponse::Ok().body(challenge_response)), - Err(_) => { - warn!("WhatsApp webhook verification failed"); - Ok(HttpResponse::Forbidden().body("Verification failed")) - } - } -} - -#[actix_web::post("/api/voice/start")] -async fn voice_start( - data: web::Data, - info: web::Json, -) -> Result { - let session_id = info - .get("session_id") - .and_then(|s| s.as_str()) - .unwrap_or(""); - let user_id = info - .get("user_id") - .and_then(|u| u.as_str()) - .unwrap_or("user"); - info!( - "Voice session start request - session: {}, user: {}", - session_id, user_id - ); - - match data - .voice_adapter - .start_voice_session(session_id, user_id) - .await - { - Ok(token) => { - info!( - "Voice session started successfully for session {}", - session_id - ); - Ok(HttpResponse::Ok().json(serde_json::json!({"token": token, "status": "started"}))) - } - Err(e) => { - error!( - "Failed to start voice session for session {}: {}", - session_id, e - ); - Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": e.to_string()}))) - } - } -} - -#[actix_web::post("/api/voice/stop")] -async fn voice_stop( - data: web::Data, - info: web::Json, -) -> Result { - let session_id = info - .get("session_id") - .and_then(|s| s.as_str()) - .unwrap_or(""); - match data.voice_adapter.stop_voice_session(session_id).await { - Ok(()) => { - info!( - "Voice session stopped successfully for session {}", - session_id - ); - Ok(HttpResponse::Ok().json(serde_json::json!({"status": "stopped"}))) - } - Err(e) => { - error!( - "Failed to stop voice session for session {}: {}", - session_id, e - ); - Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": e.to_string()}))) - } - } -} - #[actix_web::post("/api/start")] async fn start_session( data: web::Data, @@ -1110,130 +929,6 @@ async fn start_session( } } -#[actix_web::post("/api/sessions")] -async fn create_session(data: web::Data) -> Result { - let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(); - let bot_id = if let Ok(bot_guid) = std::env::var("BOT_GUID") { - match Uuid::parse_str(&bot_guid) { - Ok(uuid) => uuid, - Err(e) => { - warn!("Invalid BOT_GUID from env: {}", e); - return Ok(HttpResponse::BadRequest() - .json(serde_json::json!({"error": "Invalid BOT_GUID"}))); - } - } - } else { - warn!("BOT_GUID not set in environment, using nil UUID"); - Uuid::nil() - }; - - let session = { - let mut session_manager = data.session_manager.lock().await; - match session_manager.get_or_create_user_session(user_id, bot_id, "New Conversation") { - Ok(Some(s)) => s, - Ok(None) => { - error!("Failed to create session"); - return Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": "Failed to create session"}))); - } - Err(e) => { - error!("Failed to create session: {}", e); - return Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": e.to_string()}))); - } - } - }; - - Ok(HttpResponse::Ok().json(serde_json::json!({ - "session_id": session.id, - "title": "New Conversation", - "created_at": Utc::now() - }))) -} - -#[actix_web::get("/api/sessions")] -async fn get_sessions(data: web::Data) -> Result { - let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(); - let orchestrator = BotOrchestrator::new(Arc::clone(&data)); - match orchestrator.get_user_sessions(user_id).await { - Ok(sessions) => Ok(HttpResponse::Ok().json(sessions)), - Err(e) => { - error!("Failed to get sessions: {}", e); - Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": e.to_string()}))) - } - } -} - -#[actix_web::get("/api/sessions/{session_id}")] -async fn get_session_history( - data: web::Data, - path: web::Path, -) -> Result { - let session_id = path.into_inner(); - let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(); - - match Uuid::parse_str(&session_id) { - Ok(session_uuid) => { - let orchestrator = BotOrchestrator::new(Arc::clone(&data)); - match orchestrator - .get_conversation_history(session_uuid, user_id) - .await - { - Ok(history) => { - info!( - "Retrieved {} history entries for session {}", - history.len(), - session_id - ); - Ok(HttpResponse::Ok().json(history)) - } - Err(e) => { - error!("Failed to get session history for {}: {}", session_id, e); - Ok(HttpResponse::InternalServerError() - .json(serde_json::json!({"error": e.to_string()}))) - } - } - } - Err(_) => { - warn!("Invalid session ID format: {}", session_id); - Ok(HttpResponse::BadRequest().json(serde_json::json!({"error": "Invalid session ID"}))) - } - } -} - -#[actix_web::post("/api/set_mode")] -async fn set_mode_handler( - data: web::Data, - info: web::Json>, -) -> Result { - let default_user = "default_user".to_string(); - let default_bot = "default_bot".to_string(); - let default_mode = "0".to_string(); - let user_id = info.get("user_id").unwrap_or(&default_user); - let bot_id = info.get("bot_id").unwrap_or(&default_bot); - let mode_str = info.get("mode").unwrap_or(&default_mode); - let mode = mode_str.parse::().unwrap_or(0); - - info!( - "Setting mode - user: {}, bot: {}, mode: {}", - user_id, bot_id, mode - ); - - let orchestrator = BotOrchestrator::new(Arc::clone(&data)); - if let Err(e) = orchestrator - .set_user_answer_mode(user_id, bot_id, mode) - .await - { - error!("Failed to set answer mode: {}", e); - return Ok( - HttpResponse::InternalServerError().json(serde_json::json!({"error": e.to_string()})) - ); - } - - Ok(HttpResponse::Ok().json(serde_json::json!({"status": "mode_updated"}))) -} - #[actix_web::post("/api/warn")] async fn send_warning_handler( data: web::Data, @@ -1264,41 +959,3 @@ async fn send_warning_handler( Ok(HttpResponse::Ok().json(serde_json::json!({"status": "warning_sent"}))) } - -#[actix_web::get("/")] -async fn index() -> Result { - match fs::read_to_string("web/index.html") { - Ok(html) => Ok(HttpResponse::Ok().content_type("text/html").body(html)), - Err(e) => { - error!("Failed to load index page: {}", e); - Ok(HttpResponse::InternalServerError().body("Failed to load index page")) - } - } -} - -#[actix_web::get("/static/{filename:.*}")] -async fn static_files(req: HttpRequest) -> Result { - let filename = req.match_info().query("filename"); - let path = format!("web/static/{}", filename); - match fs::read(&path) { - Ok(content) => { - debug!( - "Static file {} loaded successfully, size: {} bytes", - filename, - content.len() - ); - let content_type = match filename { - f if f.ends_with(".js") => "application/javascript", - f if f.ends_with(".css") => "text/css", - f if f.ends_with(".png") => "image/png", - f if f.ends_with(".jpg") | f.ends_with(".jpeg") => "image/jpeg", - _ => "text/plain", - }; - Ok(HttpResponse::Ok().content_type(content_type).body(content)) - } - Err(e) => { - warn!("Static file not found: {} - {}", filename, e); - Ok(HttpResponse::NotFound().body("File not found")) - } - } -} diff --git a/src/main.rs b/src/main.rs index a5e5606e0..5ed035ee4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,18 +18,17 @@ mod email; mod file; mod llm; mod llm_legacy; +mod meet; mod org; mod package_manager; mod session; mod shared; mod tools; +mod web_server; mod whatsapp; +use crate::auth::auth_handler; use crate::automation::AutomationService; -use crate::bot::{ - auth_handler, create_session, get_session_history, get_sessions, index, set_mode_handler, - start_session, static_files, voice_start, voice_stop, websocket_handler, - whatsapp_webhook_verify, -}; +use crate::bot::{start_session, websocket_handler}; use crate::channels::{VoiceAdapter, WebChannelAdapter}; use crate::config::AppConfig; #[cfg(feature = "email")] @@ -40,7 +39,11 @@ use crate::file::{init_drive, upload_file}; use crate::llm_legacy::llm_local::{ chat_completions_local, embeddings_local, ensure_llama_servers_running, }; +use crate::meet::{voice_start, voice_stop}; +use crate::session::{create_session, get_session_history, get_sessions}; use crate::shared::state::AppState; +use crate::web_server::{index, static_files}; +use crate::whatsapp::whatsapp_webhook_verify; use crate::whatsapp::WhatsAppAdapter; #[actix_web::main] @@ -269,7 +272,6 @@ async fn main() -> std::io::Result<()> { .service(get_sessions) .service(start_session) .service(get_session_history) - .service(set_mode_handler) .service(chat_completions_local) .service(embeddings_local); diff --git a/src/session/mod.rs b/src/session/mod.rs index 98af282ae..cd30c6a44 100644 --- a/src/session/mod.rs +++ b/src/session/mod.rs @@ -1,4 +1,7 @@ +use crate::bot::BotOrchestrator; use crate::shared::models::UserSession; +use crate::shared::state::AppState; +use actix_web::{web, HttpResponse, Result}; use chrono::Utc; use diesel::prelude::*; use diesel::PgConnection; @@ -333,3 +336,95 @@ impl SessionManager { Ok(()) } } + +#[actix_web::post("/api/sessions")] +async fn create_session(data: web::Data) -> Result { + let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(); + let bot_id = if let Ok(bot_guid) = std::env::var("BOT_GUID") { + match Uuid::parse_str(&bot_guid) { + Ok(uuid) => uuid, + Err(e) => { + warn!("Invalid BOT_GUID from env: {}", e); + return Ok(HttpResponse::BadRequest() + .json(serde_json::json!({"error": "Invalid BOT_GUID"}))); + } + } + } else { + warn!("BOT_GUID not set in environment, using nil UUID"); + Uuid::nil() + }; + + let session = { + let mut session_manager = data.session_manager.lock().await; + match session_manager.get_or_create_user_session(user_id, bot_id, "New Conversation") { + Ok(Some(s)) => s, + Ok(None) => { + error!("Failed to create session"); + return Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": "Failed to create session"}))); + } + Err(e) => { + error!("Failed to create session: {}", e); + return Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": e.to_string()}))); + } + } + }; + + Ok(HttpResponse::Ok().json(serde_json::json!({ + "session_id": session.id, + "title": "New Conversation", + "created_at": Utc::now() + }))) +} + +#[actix_web::get("/api/sessions")] +async fn get_sessions(data: web::Data) -> Result { + let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(); + let orchestrator = BotOrchestrator::new(Arc::clone(&data)); + match orchestrator.get_user_sessions(user_id).await { + Ok(sessions) => Ok(HttpResponse::Ok().json(sessions)), + Err(e) => { + error!("Failed to get sessions: {}", e); + Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": e.to_string()}))) + } + } +} + +#[actix_web::get("/api/sessions/{session_id}")] +async fn get_session_history( + data: web::Data, + path: web::Path, +) -> Result { + let session_id = path.into_inner(); + let user_id = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(); + + match Uuid::parse_str(&session_id) { + Ok(session_uuid) => { + let orchestrator = BotOrchestrator::new(Arc::clone(&data)); + match orchestrator + .get_conversation_history(session_uuid, user_id) + .await + { + Ok(history) => { + info!( + "Retrieved {} history entries for session {}", + history.len(), + session_id + ); + Ok(HttpResponse::Ok().json(history)) + } + Err(e) => { + error!("Failed to get session history for {}: {}", session_id, e); + Ok(HttpResponse::InternalServerError() + .json(serde_json::json!({"error": e.to_string()}))) + } + } + } + Err(_) => { + warn!("Invalid session ID format: {}", session_id); + Ok(HttpResponse::BadRequest().json(serde_json::json!({"error": "Invalid session ID"}))) + } + } +} diff --git a/src/whatsapp/mod.rs b/src/whatsapp/mod.rs index 7bfe5764d..84a51c321 100644 --- a/src/whatsapp/mod.rs +++ b/src/whatsapp/mod.rs @@ -1,5 +1,6 @@ +use actix_web::{web, HttpResponse, Result}; use async_trait::async_trait; -use log::info; +use log::{info, warn}; use reqwest::Client; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -7,6 +8,7 @@ use std::sync::Arc; use tokio::sync::Mutex; use crate::shared::models::BotResponse; +use crate::shared::state::AppState; #[derive(Debug, Deserialize)] pub struct WhatsAppMessage { @@ -198,3 +200,26 @@ impl crate::channels::ChannelAdapter for WhatsAppAdapter { .await } } + +#[actix_web::get("/api/whatsapp/webhook")] +async fn whatsapp_webhook_verify( + data: web::Data, + web::Query(params): web::Query>, +) -> Result { + let empty = String::new(); + let mode = params.get("hub.mode").unwrap_or(&empty); + let token = params.get("hub.verify_token").unwrap_or(&empty); + let challenge = params.get("hub.challenge").unwrap_or(&empty); + info!( + "Verification params - mode: {}, token: {}, challenge: {}", + mode, token, challenge + ); + + match data.whatsapp_adapter.verify_webhook(mode, token, challenge) { + Ok(challenge_response) => Ok(HttpResponse::Ok().body(challenge_response)), + Err(_) => { + warn!("WhatsApp webhook verification failed"); + Ok(HttpResponse::Forbidden().body("Verification failed")) + } + } +} diff --git a/templates/announcements.gbai/announcements.gbdialog/start.bas b/templates/announcements.gbai/announcements.gbdialog/start.bas index d0c8576dd..c3890cc8f 100644 --- a/templates/announcements.gbai/announcements.gbdialog/start.bas +++ b/templates/announcements.gbai/announcements.gbdialog/start.bas @@ -4,4 +4,4 @@ TALK resume let text = GET "default.gbdrive/default.pdf" SET_CONTEXT "Este é o documento que você deve usar para responder dúvidas: " + text -TALK "Olá, pode me perguntar sobre qualquer coisa desta circular..." +TALK "Olá, pode me perguntar sobre qualquer coisa destas circulares..."