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 os
import speech_recognition as sr import speech_recognition as sr
from pydub import AudioSegment from pydub import AudioSegment
from gtts import gTTS from gtts import gTTS
import uuid import uuid
import re import re
def transcribe_audio(file_path: str) -> str: def transcribe_audio(file_path: str) -> str:
"""Converte áudio (qualquer formato compatível com pydub) para WAV e transcreve com Google Speech.""" """Converte áudio (qualquer formato compatível com pydub) para WAV e transcreve com Google Speech."""
recognizer = sr.Recognizer() recognizer = sr.Recognizer()
# Se não for wav, converte usando pydub (precisa de ffmpeg na VPS) # Se não for wav, converte usando pydub (precisa de ffmpeg na VPS)
temp_wav = f"/tmp/{uuid.uuid4()}.wav" temp_wav = f"/tmp/{uuid.uuid4()}.wav"
try: try:
audio = AudioSegment.from_file(file_path) audio = AudioSegment.from_file(file_path)
audio.export(temp_wav, format="wav") audio.export(temp_wav, format="wav")
with sr.AudioFile(temp_wav) as source: with sr.AudioFile(temp_wav) as source:
audio_data = recognizer.record(source) audio_data = recognizer.record(source)
text = recognizer.recognize_google(audio_data, language="pt-BR") text = recognizer.recognize_google(audio_data, language="pt-BR")
return text return text
finally: finally:
if os.path.exists(temp_wav): if os.path.exists(temp_wav):
os.remove(temp_wav) os.remove(temp_wav)
def text_to_speech(text: str) -> str: def text_to_speech(text: str) -> str:
"""Sintetiza texto em áudio MP3, removendo tags visuais e emojis.""" """Sintetiza texto em áudio MP3, removendo tags visuais e emojis."""
# Limpeza para narração # Limpeza para narração
texto_limpo = text.replace("🤖", "").replace("🧑‍🏫", "").replace("*", "").replace("`", "") texto_limpo = text.replace("🤖", "").replace("🧑‍🏫", "").replace("*", "").replace("`", "")
# Remove o bloco <REFINED> se houver, pois ele é para leitura visual apenas # 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() 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 # Se sobrar texto vazio após limpar o refinado (raro), fala algo genérico
if not texto_limpo: if not texto_limpo:
texto_limpo = "Relatório processado. Os detalhes estão no painel visual." texto_limpo = "Relatório processado. Os detalhes estão no painel visual."
filename = f"audio_reply_{uuid.uuid4().hex[:8]}.mp3" filename = f"audio_reply_{uuid.uuid4().hex[:8]}.mp3"
filepath = os.path.join("/tmp", filename) filepath = os.path.join("/tmp", filename)
tts = gTTS(text=texto_limpo, lang='pt-br', tld='com.br', slow=False) tts = gTTS(text=texto_limpo, lang='pt-br', tld='com.br', slow=False)
tts.save(filepath) tts.save(filepath)
return filename return filename

View File

@@ -1,28 +1,28 @@
import json import json
import os import os
CONFIG_FILE = "/app/data/config.json" CONFIG_FILE = "/app/data/config.json"
def get_config(): def get_config():
if not os.path.exists("/app/data"): if not os.path.exists("/app/data"):
os.makedirs("/app/data", exist_ok=True) os.makedirs("/app/data", exist_ok=True)
if os.path.exists(CONFIG_FILE): if os.path.exists(CONFIG_FILE):
try: try:
with open(CONFIG_FILE, "r") as f: with open(CONFIG_FILE, "r") as f:
return json.load(f) return json.load(f)
except Exception: except Exception:
pass pass
# Configuração Padrão # Configuração Padrão
return { return {
"active_provider": "gemini", "active_provider": "gemini",
"gemini_api_key": "", "gemini_api_key": "",
"web_password": "@@Gi05Br;;" "web_password": "@@Gi05Br;;"
} }
def save_config(cfg): def save_config(cfg):
if not os.path.exists("/app/data"): if not os.path.exists("/app/data"):
os.makedirs("/app/data", exist_ok=True) os.makedirs("/app/data", exist_ok=True)
with open(CONFIG_FILE, "w") as f: with open(CONFIG_FILE, "w") as f:
json.dump(cfg, f, indent=4) 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_url(): return "https://supabase.reifonas.cloud"
def supabase_anon_key(): return get_segredo("supabase", "ANON_KEY") def supabase_anon_key(): return get_segredo("supabase", "ANON_KEY")
def supabase_service_role_key(): return get_segredo("supabase", "SERVICE_ROLE_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 json
import asyncio import asyncio
from fastapi import FastAPI, Request, Header, Depends, HTTPException, status 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 fastapi.templating import Jinja2Templates
from dotenv import load_dotenv from dotenv import load_dotenv
from starlette.concurrency import run_in_threadpool from starlette.concurrency import run_in_threadpool
from ai_agent import query_agent from ai_agent import query_agent
from config import get_config, save_config 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 ( from orchestrator import (
orchestrate_async, handle_message_async, get_orchestrator_status, orchestrate_async, handle_message_async, get_orchestrator_status,
get_llm_config, set_llm_config, format_confirmation_message, get_llm_config, set_llm_config, format_confirmation_message,
@@ -30,8 +30,7 @@ templates = Jinja2Templates(directory="templates")
@app.on_event("startup") @app.on_event("startup")
async def startup_event(): async def startup_event():
print("[INIT] Sincronizando credenciais...") print("[INIT] Sincronizando credenciais...")
sync_from_gitea_repo() await fetch_from_gitea_repo_async(force=True)
sync_credentials()
# --- SEGURANÇA --- # --- SEGURANÇA ---
async def verify_password(x_web_password: str = Header(None)): 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 return True
# --- WEB UI --- # --- WEB UI ---
@app.get("/", response_class=HTMLResponse) @app.get("/", response_class=FileResponse)
async def read_root(request: Request): async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request}) return FileResponse("templates/index.html")
@app.get("/api/status") @app.get("/api/status")
async def get_system_status(is_auth: bool = Depends(verify_password)): async def get_system_status(is_auth: bool = Depends(verify_password)):

View File

@@ -1,13 +1,13 @@
#!/bin/bash #!/bin/bash
# Tenta limpar processos conflitantes no host se tiver acesso privilégido # Tenta limpar processos conflitantes no host se tiver acesso privilégido
if [ -d "/host_root" ]; then if [ -d "/host_root" ]; then
echo "Limpando processos conflitantes no HOST..." 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 telegram_bot.js" || true
chroot /host_root /bin/bash -c "pkill -f bot_logic.py" || true chroot /host_root /bin/bash -c "pkill -f bot_logic.py" || true
fi fi
# Inicia o serviço web # Inicia o serviço web
uvicorn main:app --host 0.0.0.0 --port 8000 & uvicorn main:app --host 0.0.0.0 --port 8000 &
# Inicia o Polling do Bot # Inicia o Polling do Bot
python bot_logic.py python bot_logic.py

View File

@@ -1,15 +1,15 @@
#!/bin/bash #!/bin/bash
# Script de deploy e sincronização automática # Script de deploy e sincronização automática
echo "🚀 Iniciando deploy e push para o Gitea..." echo "🚀 Iniciando deploy e push para o Gitea..."
# 1. Build do Docker # 1. Build do Docker
echo "📦 Reconstruindo container..." echo "📦 Reconstruindo container..."
docker compose down && docker compose build && docker compose up -d docker compose down && docker compose build && docker compose up -d
# 2. Sincronização com Git (Gitea) # 2. Sincronização com Git (Gitea)
echo "git Pushing para o Gitea..." echo "git Pushing para o Gitea..."
git add . git add .
git commit -m "🔒 Implementação de segurança: Login Web fixo e proteção de API" git commit -m "🔒 Implementação de segurança: Login Web fixo e proteção de API"
git push origin master git push origin master
echo "✅ Sucesso! Agente atualizado e código no Gitea." echo "✅ Sucesso! Agente atualizado e código no Gitea."