Refactor: fix async errors, CRLF line endings and bot tokens.
This commit is contained in:
@@ -1,42 +1,42 @@
|
||||
import os
|
||||
import speech_recognition as sr
|
||||
from pydub import AudioSegment
|
||||
from gtts import gTTS
|
||||
import uuid
|
||||
import re
|
||||
|
||||
def transcribe_audio(file_path: str) -> str:
|
||||
"""Converte áudio (qualquer formato compatível com pydub) para WAV e transcreve com Google Speech."""
|
||||
recognizer = sr.Recognizer()
|
||||
|
||||
# Se não for wav, converte usando pydub (precisa de ffmpeg na VPS)
|
||||
temp_wav = f"/tmp/{uuid.uuid4()}.wav"
|
||||
try:
|
||||
audio = AudioSegment.from_file(file_path)
|
||||
audio.export(temp_wav, format="wav")
|
||||
|
||||
with sr.AudioFile(temp_wav) as source:
|
||||
audio_data = recognizer.record(source)
|
||||
text = recognizer.recognize_google(audio_data, language="pt-BR")
|
||||
return text
|
||||
finally:
|
||||
if os.path.exists(temp_wav):
|
||||
os.remove(temp_wav)
|
||||
|
||||
def text_to_speech(text: str) -> str:
|
||||
"""Sintetiza texto em áudio MP3, removendo tags visuais e emojis."""
|
||||
# Limpeza para narração
|
||||
texto_limpo = text.replace("🤖", "").replace("🧑🏫", "").replace("*", "").replace("`", "")
|
||||
# Remove o bloco <REFINED> se houver, pois ele é para leitura visual apenas
|
||||
texto_limpo = re.sub(r'<REFINED>.*?</REFINED>', '', texto_limpo, flags=re.DOTALL).strip()
|
||||
|
||||
# Se sobrar texto vazio após limpar o refinado (raro), fala algo genérico
|
||||
if not texto_limpo:
|
||||
texto_limpo = "Relatório processado. Os detalhes estão no painel visual."
|
||||
|
||||
filename = f"audio_reply_{uuid.uuid4().hex[:8]}.mp3"
|
||||
filepath = os.path.join("/tmp", filename)
|
||||
|
||||
tts = gTTS(text=texto_limpo, lang='pt-br', tld='com.br', slow=False)
|
||||
tts.save(filepath)
|
||||
return filename
|
||||
import os
|
||||
import speech_recognition as sr
|
||||
from pydub import AudioSegment
|
||||
from gtts import gTTS
|
||||
import uuid
|
||||
import re
|
||||
|
||||
def transcribe_audio(file_path: str) -> str:
|
||||
"""Converte áudio (qualquer formato compatível com pydub) para WAV e transcreve com Google Speech."""
|
||||
recognizer = sr.Recognizer()
|
||||
|
||||
# Se não for wav, converte usando pydub (precisa de ffmpeg na VPS)
|
||||
temp_wav = f"/tmp/{uuid.uuid4()}.wav"
|
||||
try:
|
||||
audio = AudioSegment.from_file(file_path)
|
||||
audio.export(temp_wav, format="wav")
|
||||
|
||||
with sr.AudioFile(temp_wav) as source:
|
||||
audio_data = recognizer.record(source)
|
||||
text = recognizer.recognize_google(audio_data, language="pt-BR")
|
||||
return text
|
||||
finally:
|
||||
if os.path.exists(temp_wav):
|
||||
os.remove(temp_wav)
|
||||
|
||||
def text_to_speech(text: str) -> str:
|
||||
"""Sintetiza texto em áudio MP3, removendo tags visuais e emojis."""
|
||||
# Limpeza para narração
|
||||
texto_limpo = text.replace("🤖", "").replace("🧑🏫", "").replace("*", "").replace("`", "")
|
||||
# Remove o bloco <REFINED> se houver, pois ele é para leitura visual apenas
|
||||
texto_limpo = re.sub(r'<REFINED>.*?</REFINED>', '', texto_limpo, flags=re.DOTALL).strip()
|
||||
|
||||
# Se sobrar texto vazio após limpar o refinado (raro), fala algo genérico
|
||||
if not texto_limpo:
|
||||
texto_limpo = "Relatório processado. Os detalhes estão no painel visual."
|
||||
|
||||
filename = f"audio_reply_{uuid.uuid4().hex[:8]}.mp3"
|
||||
filepath = os.path.join("/tmp", filename)
|
||||
|
||||
tts = gTTS(text=texto_limpo, lang='pt-br', tld='com.br', slow=False)
|
||||
tts.save(filepath)
|
||||
return filename
|
||||
|
||||
56
config.py
56
config.py
@@ -1,28 +1,28 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
CONFIG_FILE = "/app/data/config.json"
|
||||
|
||||
def get_config():
|
||||
if not os.path.exists("/app/data"):
|
||||
os.makedirs("/app/data", exist_ok=True)
|
||||
|
||||
if os.path.exists(CONFIG_FILE):
|
||||
try:
|
||||
with open(CONFIG_FILE, "r") as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Configuração Padrão
|
||||
return {
|
||||
"active_provider": "gemini",
|
||||
"gemini_api_key": "",
|
||||
"web_password": "@@Gi05Br;;"
|
||||
}
|
||||
|
||||
def save_config(cfg):
|
||||
if not os.path.exists("/app/data"):
|
||||
os.makedirs("/app/data", exist_ok=True)
|
||||
with open(CONFIG_FILE, "w") as f:
|
||||
json.dump(cfg, f, indent=4)
|
||||
import json
|
||||
import os
|
||||
|
||||
CONFIG_FILE = "/app/data/config.json"
|
||||
|
||||
def get_config():
|
||||
if not os.path.exists("/app/data"):
|
||||
os.makedirs("/app/data", exist_ok=True)
|
||||
|
||||
if os.path.exists(CONFIG_FILE):
|
||||
try:
|
||||
with open(CONFIG_FILE, "r") as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Configuração Padrão
|
||||
return {
|
||||
"active_provider": "gemini",
|
||||
"gemini_api_key": "",
|
||||
"web_password": "@@Gi05Br;;"
|
||||
}
|
||||
|
||||
def save_config(cfg):
|
||||
if not os.path.exists("/app/data"):
|
||||
os.makedirs("/app/data", exist_ok=True)
|
||||
with open(CONFIG_FILE, "w") as f:
|
||||
json.dump(cfg, f, indent=4)
|
||||
|
||||
@@ -148,4 +148,3 @@ def gitea_api_url(): return GITEA_API_URL
|
||||
def supabase_url(): return "https://supabase.reifonas.cloud"
|
||||
def supabase_anon_key(): return get_segredo("supabase", "ANON_KEY")
|
||||
def supabase_service_role_key(): return get_segredo("supabase", "SERVICE_ROLE_KEY")
|
||||
print(f" Coolify API: {coolify_api_base()}")
|
||||
|
||||
11
main.py
11
main.py
@@ -5,14 +5,14 @@ import time
|
||||
import json
|
||||
import asyncio
|
||||
from fastapi import FastAPI, Request, Header, Depends, HTTPException, status
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from fastapi.responses import HTMLResponse, JSONResponse, FileResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from dotenv import load_dotenv
|
||||
from starlette.concurrency import run_in_threadpool
|
||||
|
||||
from ai_agent import query_agent
|
||||
from config import get_config, save_config
|
||||
from credential_manager import sync_credentials, sync_from_gitea_repo
|
||||
from credential_manager import fetch_from_gitea_repo_async
|
||||
from orchestrator import (
|
||||
orchestrate_async, handle_message_async, get_orchestrator_status,
|
||||
get_llm_config, set_llm_config, format_confirmation_message,
|
||||
@@ -30,8 +30,7 @@ templates = Jinja2Templates(directory="templates")
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
print("[INIT] Sincronizando credenciais...")
|
||||
sync_from_gitea_repo()
|
||||
sync_credentials()
|
||||
await fetch_from_gitea_repo_async(force=True)
|
||||
|
||||
# --- SEGURANÇA ---
|
||||
async def verify_password(x_web_password: str = Header(None)):
|
||||
@@ -41,9 +40,9 @@ async def verify_password(x_web_password: str = Header(None)):
|
||||
return True
|
||||
|
||||
# --- WEB UI ---
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
@app.get("/", response_class=FileResponse)
|
||||
async def read_root(request: Request):
|
||||
return templates.TemplateResponse("index.html", {"request": request})
|
||||
return FileResponse("templates/index.html")
|
||||
|
||||
@app.get("/api/status")
|
||||
async def get_system_status(is_auth: bool = Depends(verify_password)):
|
||||
|
||||
26
start.sh
26
start.sh
@@ -1,13 +1,13 @@
|
||||
#!/bin/bash
|
||||
# Tenta limpar processos conflitantes no host se tiver acesso privilégido
|
||||
if [ -d "/host_root" ]; then
|
||||
echo "Limpando processos conflitantes no HOST..."
|
||||
chroot /host_root /bin/bash -c "pkill -f telegram_bot.js" || true
|
||||
chroot /host_root /bin/bash -c "pkill -f bot_logic.py" || true
|
||||
fi
|
||||
|
||||
# Inicia o serviço web
|
||||
uvicorn main:app --host 0.0.0.0 --port 8000 &
|
||||
|
||||
# Inicia o Polling do Bot
|
||||
python bot_logic.py
|
||||
#!/bin/bash
|
||||
# Tenta limpar processos conflitantes no host se tiver acesso privilégido
|
||||
if [ -d "/host_root" ]; then
|
||||
echo "Limpando processos conflitantes no HOST..."
|
||||
chroot /host_root /bin/bash -c "pkill -f telegram_bot.js" || true
|
||||
chroot /host_root /bin/bash -c "pkill -f bot_logic.py" || true
|
||||
fi
|
||||
|
||||
# Inicia o serviço web
|
||||
uvicorn main:app --host 0.0.0.0 --port 8000 &
|
||||
|
||||
# Inicia o Polling do Bot
|
||||
python bot_logic.py
|
||||
|
||||
30
update.sh
30
update.sh
@@ -1,15 +1,15 @@
|
||||
#!/bin/bash
|
||||
# Script de deploy e sincronização automática
|
||||
echo "🚀 Iniciando deploy e push para o Gitea..."
|
||||
|
||||
# 1. Build do Docker
|
||||
echo "📦 Reconstruindo container..."
|
||||
docker compose down && docker compose build && docker compose up -d
|
||||
|
||||
# 2. Sincronização com Git (Gitea)
|
||||
echo "git Pushing para o Gitea..."
|
||||
git add .
|
||||
git commit -m "🔒 Implementação de segurança: Login Web fixo e proteção de API"
|
||||
git push origin master
|
||||
|
||||
echo "✅ Sucesso! Agente atualizado e código no Gitea."
|
||||
#!/bin/bash
|
||||
# Script de deploy e sincronização automática
|
||||
echo "🚀 Iniciando deploy e push para o Gitea..."
|
||||
|
||||
# 1. Build do Docker
|
||||
echo "📦 Reconstruindo container..."
|
||||
docker compose down && docker compose build && docker compose up -d
|
||||
|
||||
# 2. Sincronização com Git (Gitea)
|
||||
echo "git Pushing para o Gitea..."
|
||||
git add .
|
||||
git commit -m "🔒 Implementação de segurança: Login Web fixo e proteção de API"
|
||||
git push origin master
|
||||
|
||||
echo "✅ Sucesso! Agente atualizado e código no Gitea."
|
||||
|
||||
Reference in New Issue
Block a user