#!/usr/bin/env bash # install.sh — instaleaza puntea WhatsApp+RAG a lui Maria pe LXC 171 (claude-agent). # # IDEMPOTENT: se poate rula de cate ori vrei. Nu suprascrie niciodata # ~/.maria-bridge/env (acolo sta configuratia completata de om). # # ./ops/install.sh # instaleaza / actualizeaza, NU porneste serviciile # ./ops/install.sh --start # in plus porneste bridge+rag (bridge cere QR scanat) # # Controlul (start/stop/restart, documente, reindexare, sincronizare Drive) se # face din dashboard-ul PUNTII DISCORD (discord-bridge/dashboard/), sectiunea # "Maria — WhatsApp + RAG" — decizie deliberata: un singur panou comun, nu un # dashboard separat per serviciu. Vezi discord-bridge/README.md. # # Ce face: # 1. ~/.maria-bridge/ cu 0700, subdirectoare (logs/, documents/, whatsapp-auth/) # 2. env 0600 din ops/env.example (doar daca lipseste) # 3. npm install pentru whatsapp/ (Baileys) # 4. venv + pip install pentru rag/requirements.txt # 5. loginctl enable-linger (serviciile de utilizator supravietuiesc logout-ului) # 6. symlink-uri unit -> ~/.config/systemd/user/ (bridge, rag, timer sync) # 7. systemd-analyze verify + enable set -uo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SRC="$(dirname "$HERE")" # .../maria-whatsapp-bridge STATE_DIR="$HOME/.maria-bridge" UNIT_DIR="$HOME/.config/systemd/user" UNITS=(maria-whatsapp.service maria-rag.service maria-sync.service maria-sync.timer) DO_START=0 [ "${1:-}" = "--start" ] && DO_START=1 info() { printf ' \033[32m*\033[0m %s\n' "$*"; } warn() { printf ' \033[33m!\033[0m %s\n' "$*"; } die() { printf ' \033[31mX\033[0m %s\n' "$*" >&2; exit 1; } [ "$(id -u)" -eq 0 ] && die "NU rula ca root. Serviciile Maria sunt servicii de utilizator (claude)." echo "== Punte WhatsApp+RAG Maria: instalare ==" echo " sursa: $SRC" # --- 1. director de stare -------------------------------------------------- mkdir -p "$STATE_DIR/logs" "$STATE_DIR/documents" "$STATE_DIR/whatsapp-auth" chmod 0700 "$STATE_DIR" info "director de stare: $STATE_DIR (0700)" # --- 2. env ---------------------------------------------------------------- if [ -f "$STATE_DIR/env" ]; then chmod 0600 "$STATE_DIR/env" info "env exista deja, nu se atinge" else cp "$HERE/env.example" "$STATE_DIR/env" chmod 0600 "$STATE_DIR/env" info "env creat din env.example (0600) — completeaza LLM_URL/DRIVE_REMOTE dupa caz" fi # --- 3. dependinte Node (whatsapp/) ----------------------------------------- if command -v npm >/dev/null 2>&1; then if [ -d "$SRC/whatsapp/node_modules" ]; then info "node_modules exista deja in whatsapp/" else (cd "$SRC/whatsapp" && npm install --omit=dev) \ && info "npm install: gata (Baileys si dependinte)" \ || warn "npm install a esuat (retea?) — reia cu: cd $SRC/whatsapp && npm install" fi else warn "npm lipseste din PATH — instaleaza Node (nvm) inainte de a porni puntea" fi # --- 4. venv + dependinte Python (rag/) ------------------------------------- if [ ! -x "$STATE_DIR/venv/bin/python" ]; then python3 -m venv "$STATE_DIR/venv" || die "crearea venv a esuat" info "venv creat: $STATE_DIR/venv" else info "venv exista deja" fi "$STATE_DIR/venv/bin/python" -m pip install --quiet --upgrade pip >/dev/null 2>&1 if "$STATE_DIR/venv/bin/python" -m pip install --quiet -r "$SRC/rag/requirements.txt"; then info "dependinte Python instalate din rag/requirements.txt" else warn "instalarea dependintelor Python a esuat (retea?) — reia cu: $STATE_DIR/venv/bin/pip install -r $SRC/rag/requirements.txt" fi # --- 5. linger --------------------------------------------------------------- if [ "$(loginctl show-user "$USER" -p Linger --value 2>/dev/null)" = "yes" ]; then info "linger deja activ pentru $USER" else if loginctl enable-linger "$USER" 2>/dev/null; then info "linger activat pentru $USER" elif sudo -n loginctl enable-linger "$USER" 2>/dev/null; then info "linger activat pentru $USER (prin sudo)" else warn "nu am putut activa linger; ruleaza manual: sudo loginctl enable-linger $USER" fi fi # --- 6. unit-uri ------------------------------------------------------------- mkdir -p "$UNIT_DIR" for u in "${UNITS[@]}"; do ln -sfn "$HERE/$u" "$UNIT_DIR/$u" info "unit legat: $UNIT_DIR/$u -> $HERE/$u" done systemctl --user daemon-reload 2>/dev/null || warn "daemon-reload a esuat (sesiune fara systemd de utilizator?)" if systemd-analyze verify "$UNIT_DIR/maria-whatsapp.service" 2>&1 | grep -vE 'Unknown key|^$' | grep -q .; then systemd-analyze verify "$UNIT_DIR/maria-whatsapp.service" 2>&1 | sed 's/^/ /' warn "systemd-analyze verify a raportat probleme (vezi mai sus)" else info "systemd-analyze verify: curat" fi # --- 7. rclone (optional, pentru sincronizare Drive) ------------------------ if command -v rclone >/dev/null 2>&1; then info "rclone gasit: $(command -v rclone)" if ! grep -qE '^DRIVE_REMOTE=.+' "$STATE_DIR/env" 2>/dev/null; then warn "DRIVE_REMOTE necompletat — sincronizarea cu Google Drive ramane dezactivata" warn "vezi README.md, sectiunea 'Sincronizare cu Google Drive'" fi else warn "rclone nu e instalat — sincronizarea automata cu Google Drive nu va functiona" warn "instaleaza cu: sudo apt-get install -y rclone (apoi vezi README.md)" fi # --- 7b. tesseract (OCR pentru capturile de ecran primite) ------------------- # Fara el, Maria raspunde in continuare la text, dar la o captura cu eroare # raspunde ca nu poate citi imaginea. Vezi rag/ocr.py. if command -v tesseract >/dev/null 2>&1; then if tesseract --list-langs 2>/dev/null | grep -qx ron; then info "tesseract gasit, cu limba romana" else warn "tesseract nu are pachetul de limba romana (ron) — OCR-ul va fi mai slab" warn "instaleaza cu: sudo apt-get install -y tesseract-ocr-ron" fi else warn "tesseract nu e instalat — capturile de ecran primite pe WhatsApp nu pot fi citite" warn "instaleaza cu: sudo apt-get install -y tesseract-ocr tesseract-ocr-ron" fi # --- 8. enable / start ------------------------------------------------------- for u in maria-whatsapp.service maria-rag.service; do systemctl --user enable "$u" >/dev/null 2>&1 \ && info "$u enabled (porneste la boot)" \ || warn "enable pentru $u a esuat" done systemctl --user enable --now maria-sync.timer >/dev/null 2>&1 \ && info "timer de sincronizare Drive activat (la fiecare 10 min)" \ || warn "enable pentru maria-sync.timer a esuat" if [ "$DO_START" -eq 1 ]; then systemctl --user restart maria-whatsapp.service && info "punte WhatsApp pornita" echo echo " Deschide dashboard-ul puntii Discord (sectiunea 'Maria — WhatsApp + RAG')" echo " si asociaza WhatsApp din cardul 'Conectare WhatsApp' inainte sa pornesti" echo " maria-rag: fie scanezi codul QR, fie ceri un cod de asociere pentru numar." systemctl --user restart maria-rag.service && info "consumer RAG pornit" systemctl --user --no-pager status maria-whatsapp.service | sed 's/^/ /' else echo echo " Serviciile bridge/rag NU au fost pornite (intentionat: bridge-ul cere" echo " asocierea WhatsApp — cod QR sau cod de asociere — actiune manuala)." echo " Dupa ce completezi $STATE_DIR/env: $0 --start" fi echo "== gata =="