Refactor: fix async errors, CRLF line endings and bot tokens.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
56
config.py
56
config.py
@@ -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)
|
||||||
|
|||||||
@@ -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
11
main.py
@@ -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)):
|
||||||
|
|||||||
26
start.sh
26
start.sh
@@ -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
|
||||||
|
|||||||
30
update.sh
30
update.sh
@@ -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."
|
||||||
|
|||||||
Reference in New Issue
Block a user