Refactor: fix async errors, CRLF line endings and bot tokens.

This commit is contained in:
2026-03-24 00:02:56 +00:00
parent b7e6239216
commit cb729809a9
6 changed files with 103 additions and 105 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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
View File

@@ -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)):

View File

@@ -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

View File

@@ -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."