First commit
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from database import get_db
|
||||
import models
|
||||
import schemas
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
from auth import get_current_user
|
||||
from fastapi.responses import StreamingResponse
|
||||
from io import BytesIO
|
||||
from integrations.chats import TelegramChatSingleton
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# ATTACHMENT CRUD
|
||||
|
||||
@router.post("/attachments/", response_model=schemas.AttachmentResponse, tags=['Attachments'])
|
||||
def create_attachment(attachment: schemas.AttachmentCreate, db: Session = Depends(get_db)):
|
||||
# Verificar que el mensaje existe (FK compuesta)
|
||||
db_message = db.query(models.Message).filter(
|
||||
models.Message.id_mess_g == attachment.message_id,
|
||||
models.Message.group_id == attachment.group_id
|
||||
).first()
|
||||
if not db_message:
|
||||
raise HTTPException(status_code=404, detail="Message not found")
|
||||
|
||||
db_attachment = models.Attachment(**attachment.model_dump())
|
||||
db.add(db_attachment)
|
||||
db.commit()
|
||||
db.refresh(db_attachment)
|
||||
return db_attachment
|
||||
|
||||
@router.get("/attachments/", response_model=List[schemas.AttachmentResponse], tags=['Attachments'])
|
||||
def read_attachments(skip: int = 0, limit: int = 100, db: Session = Depends(get_db), current_user: str = Depends(get_current_user)):
|
||||
attachments = db.query(models.Attachment).offset(skip).limit(limit).all()
|
||||
return attachments
|
||||
|
||||
@router.get("/attachments/{attachment_id}", response_model=schemas.AttachmentResponse, tags=['Attachments'])
|
||||
def read_attachment(attachment_id: int, db: Session = Depends(get_db), current_user: str = Depends(get_current_user)):
|
||||
db_attachment = db.query(models.Attachment).filter(models.Attachment.id == attachment_id).first()
|
||||
if not db_attachment:
|
||||
raise HTTPException(status_code=404, detail="Attachment not found")
|
||||
return db_attachment
|
||||
|
||||
@router.put("/attachments/{attachment_id}", response_model=schemas.AttachmentResponse, tags=['Attachments'])
|
||||
def update_attachment(attachment_id: int, attachment: schemas.AttachmentCreate, db: Session = Depends(get_db), current_user: str = Depends(get_current_user)):
|
||||
db_attachment = db.query(models.Attachment).filter(models.Attachment.id == attachment_id).first()
|
||||
if not db_attachment:
|
||||
raise HTTPException(status_code=404, detail="Attachment not found")
|
||||
|
||||
for field, value in attachment.model_dump().items():
|
||||
setattr(db_attachment, field, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_attachment)
|
||||
return db_attachment
|
||||
|
||||
@router.delete("/attachments/{attachment_id}", tags=['Attachments'])
|
||||
def delete_attachment(attachment_id: int, db: Session = Depends(get_db), current_user: str = Depends(get_current_user)):
|
||||
db_attachment = db.query(models.Attachment).filter(models.Attachment.id == attachment_id).first()
|
||||
if not db_attachment:
|
||||
raise HTTPException(status_code=404, detail="Attachment not found")
|
||||
|
||||
db.delete(db_attachment)
|
||||
db.commit()
|
||||
return {"message": "Attachment deleted successfully"}
|
||||
|
||||
def _download_sync(group_id: int, message_id: int) -> bytes:
|
||||
"""
|
||||
Descarga el media de un mensaje de Telegram de forma síncrona.
|
||||
Pensado para correrse dentro de asyncio.to_thread().
|
||||
|
||||
Usa el TelegramChatSingleton existente para no abrir una segunda sesión.
|
||||
"""
|
||||
scraper = TelegramChatSingleton.get_scraper()
|
||||
client = scraper.client # TelegramClient ya conectado y autorizado
|
||||
|
||||
# get_messages es una corrutina de Telethon — la corremos en el event loop
|
||||
# del cliente, que es síncrono en el contexto del scraper
|
||||
message = client.loop.run_until_complete(
|
||||
client.get_messages(group_id, ids=message_id)
|
||||
)
|
||||
|
||||
if message is None:
|
||||
raise ValueError(f"Mensaje {message_id} no encontrado en grupo {group_id}")
|
||||
|
||||
if not message.media:
|
||||
raise ValueError(f"El mensaje {message_id} no tiene media adjunta")
|
||||
|
||||
buffer = BytesIO()
|
||||
client.loop.run_until_complete(
|
||||
client.download_media(message, file=buffer)
|
||||
)
|
||||
buffer.seek(0)
|
||||
return buffer.read()
|
||||
|
||||
@router.get("/attachments/{attachment_id}/download", tags=["Attachments"])
|
||||
def download_attachment(
|
||||
attachment_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: str = Depends(get_current_user),
|
||||
):
|
||||
db_attachment = db.query(models.Attachment).filter(
|
||||
models.Attachment.id == attachment_id
|
||||
).first()
|
||||
if not db_attachment:
|
||||
raise HTTPException(status_code=404, detail="Attachment not found")
|
||||
|
||||
print(f"[DL] attachment encontrado: id={db_attachment.id}, type={db_attachment.type}, "
|
||||
f"group_id={db_attachment.group_id}, message_id={db_attachment.message_id}")
|
||||
|
||||
try:
|
||||
scraper = TelegramChatSingleton.get_tmp_scraper()
|
||||
print(f"[DL] scraper obtenido: {scraper}")
|
||||
except Exception as e:
|
||||
msg = f"No se pudo obtener el scraper: {type(e).__name__}: {e}"
|
||||
print(f"[DL] ERROR — {msg}")
|
||||
raise HTTPException(status_code=503, detail=msg)
|
||||
|
||||
try:
|
||||
buffer = scraper.download_attachment_to_buffer(
|
||||
db_attachment.group_id,
|
||||
db_attachment.message_id
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
except Exception as e:
|
||||
msg = f"{type(e).__name__}: {e}"
|
||||
print(f"[DL] ERROR en download_attachment_to_buffer — {msg}")
|
||||
raise HTTPException(status_code=503, detail=msg)
|
||||
|
||||
content_type_map = {
|
||||
"photo": ("image/jpeg", "jpg"),
|
||||
"video": ("video/mp4", "mp4"),
|
||||
"audio": ("audio/mpeg", "mp3"),
|
||||
"voice": ("audio/ogg", "ogg"),
|
||||
"sticker": ("image/webp", "webp"),
|
||||
"document": ("application/octet-stream", "bin"),
|
||||
"gif": ("image/gif", "gif"),
|
||||
"zip": ("application/zip", ".zip"),
|
||||
"pdf": ("application/pdf", ".pdf"),
|
||||
"msword": ("application/msword", ".doc"),
|
||||
"vnd.openxmlformats-officedocument.wordprocessingml.document": ("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx"),
|
||||
"vnd.ms-excel": ("application/vnd.ms-excel", ".xls"),
|
||||
"vnd.openxmlformats-officedocument.spreadsheetml.sheet": ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx"),
|
||||
"plain": ("text/plain", ".txt"),
|
||||
"csv": ("text/csv", ".csv"),
|
||||
}
|
||||
adj_type = db_attachment.type or "document"
|
||||
content_type, ext = content_type_map.get(adj_type, ("application/octet-stream", "bin"))
|
||||
filename = f"attachment_{attachment_id}.{ext}"
|
||||
|
||||
return StreamingResponse(
|
||||
buffer,
|
||||
media_type=content_type,
|
||||
headers={"Content-Disposition": f"attachment; filename={filename}"}
|
||||
)
|
||||
Reference in New Issue
Block a user