v1.6.0: max_bot fixes — feature keys, flush→commit, test-run, categories, broadcast page, proxy error handling, deploy scripts
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import uuid
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
ALLOWED_EXTENSIONS = {".pdf", ".docx", ".xlsx", ".txt", ".jpg", ".jpeg", ".png", ".gif"}
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FileStorage:
|
||||
def __init__(self, base_dir: str = "uploads/bot"):
|
||||
self.base_dir = Path(base_dir)
|
||||
self.base_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
async def save_file(self, file_bytes: bytes, filename: str, conversation_id: int,
|
||||
file_type: str = "document", db=None) -> str:
|
||||
ext = Path(filename).suffix.lower()
|
||||
if ext not in ALLOWED_EXTENSIONS:
|
||||
ext = ".bin"
|
||||
safe_name = f"{uuid.uuid4().hex}{ext}"
|
||||
conv_dir = self.base_dir / str(conversation_id)
|
||||
conv_dir.mkdir(parents=True, exist_ok=True)
|
||||
file_path = conv_dir / safe_name
|
||||
file_path.write_bytes(file_bytes)
|
||||
|
||||
meta = {
|
||||
"type": "conversation",
|
||||
"id": conversation_id,
|
||||
"filename": filename,
|
||||
"file_type": file_type,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"local_path": str(file_path),
|
||||
}
|
||||
meta_path = conv_dir / "metadata.json"
|
||||
if meta_path.exists():
|
||||
try:
|
||||
existing = json.loads(meta_path.read_text())
|
||||
if "attachments" not in existing:
|
||||
existing["attachments"] = []
|
||||
existing["attachments"].append({"filename": safe_name, "original": filename})
|
||||
meta_path.write_text(json.dumps(existing, ensure_ascii=False, indent=2))
|
||||
except Exception:
|
||||
meta_path.write_text(json.dumps(meta, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
meta["attachments"] = [{"filename": safe_name, "original": filename}]
|
||||
meta_path.write_text(json.dumps(meta, ensure_ascii=False, indent=2))
|
||||
|
||||
# Queue for Yandex Disk sync (service portal picks this up)
|
||||
if db is not None:
|
||||
try:
|
||||
from app.models.models import FileSyncQueue
|
||||
remote_path = f"bot/conversations/{conversation_id}/{safe_name}"
|
||||
queue = FileSyncQueue(
|
||||
local_path=str(file_path),
|
||||
remote_path=remote_path,
|
||||
entity_type="conversation",
|
||||
entity_id=conversation_id,
|
||||
status="pending",
|
||||
)
|
||||
db.add(queue)
|
||||
await db.flush()
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to queue file sync: {e}")
|
||||
|
||||
return str(file_path)
|
||||
|
||||
def get_file_type(self, filename: str) -> str:
|
||||
ext = Path(filename).suffix.lower()
|
||||
if ext in {".jpg", ".jpeg", ".png", ".gif"}:
|
||||
return "image"
|
||||
if ext in {".pdf", ".docx", ".xlsx", ".txt"}:
|
||||
return "document"
|
||||
return "other"
|
||||
|
||||
|
||||
storage = FileStorage()
|
||||
Reference in New Issue
Block a user