Chepuhagram/srv/app/api/endpoints/messages.py

165 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import Depends, APIRouter, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, delete
from app.db import models
from app.core.security import get_current_user
from app.api import schemas
from fastapi.encoders import jsonable_encoder
from typing import Optional, List
from datetime import datetime, timezone
from pydantic import BaseModel
async def get_db():
async with models.AsyncSessionLocal() as db:
try:
yield db
finally:
await db.close()
messagesRouter = APIRouter(
prefix="/messages",
tags=[],
)
@messagesRouter.get("/history/{contact_id}")
async def get_chat_history(
contact_id: int,
current_user: models.User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
limit: int = 50,
offset: int = 0,
v2_pagination: bool = False,
anchor_id: int = None,
limit_before: int = 20,
limit_after: int = 20
):
chat_filter = (
((models.Message.sender_id == current_user.id) & (models.Message.receiver_id == contact_id)) |
((models.Message.sender_id == contact_id) & (models.Message.receiver_id == current_user.id))
)
if not v2_pagination:
res = await db.execute(
select(models.Message)
.where(chat_filter)
.order_by(models.Message.id.desc())
.offset(offset)
.limit(limit)
)
messages = res.scalars().all()
print(f"DEBUG history (Legacy): user={current_user.id}, contact={contact_id}, count={len(messages)}")
return jsonable_encoder(messages)
if anchor_id is None:
unread_res = await db.execute(
select(models.Message)
.where(chat_filter, models.Message.sender_id == contact_id, models.Message.read_at == None)
.order_by(models.Message.id.asc())
)
first_unread = unread_res.scalars().first()
if first_unread:
anchor_id = first_unread.id
print(f"DEBUG server-anchor: Found unread message ID {anchor_id}")
else:
res = await db.execute(
select(models.Message)
.where(chat_filter)
.order_by(models.Message.id.desc())
.limit(limit_before)
)
messages = res.scalars().all()
return {
"anchor_id": None,
"messages": jsonable_encoder(messages)
}
older_res = await db.execute(
select(models.Message)
.where(chat_filter, models.Message.id < anchor_id)
.order_by(models.Message.id.desc())
.limit(limit_before)
)
older_messages = older_res.scalars().all()
anchor_res = await db.execute(
select(models.Message)
.where(chat_filter, models.Message.id == anchor_id)
)
anchor_message = anchor_res.scalars().first()
newer_res = await db.execute(
select(models.Message)
.where(chat_filter, models.Message.id > anchor_id)
.order_by(models.Message.id.asc())
.limit(limit_after)
)
newer_messages = newer_res.scalars().all()
combined_messages = older_messages + ([anchor_message] if anchor_message else []) + newer_messages
combined_messages.sort(key=lambda msg: msg.id, reverse=True)
return {
"anchor_id": anchor_id,
"messages": jsonable_encoder(combined_messages)
}
@messagesRouter.get("/last")
async def get_last_messages(
contact_id: int,
current_user: models.User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
limit: int = 2
):
res = await db.execute(
select(models.Message)
.where(
((models.Message.sender_id == current_user.id) & (models.Message.receiver_id == contact_id)) |
((models.Message.sender_id == contact_id) & (models.Message.receiver_id == current_user.id))
)
.order_by(models.Message.timestamp.desc())
.limit(limit)
)
messages = res.scalars().all()
return jsonable_encoder(messages)
@messagesRouter.delete("/all")
async def delete_all_messages(
current_user: models.User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
# 1. Находим всех пользователей, с которыми у current_user были диалоги
res = await db.execute(
select(models.Message.sender_id, models.Message.receiver_id)
.where(
(models.Message.sender_id == current_user.id) | (models.Message.receiver_id == current_user.id)
)
)
rows = res.all()
contact_ids = set()
for row in rows:
if row[0] != current_user.id:
contact_ids.add(row[0])
if row[1] != current_user.id:
contact_ids.add(row[1])
# 2. Удаляем все сообщения
await db.execute(
delete(models.Message)
.where(
(models.Message.sender_id == current_user.id) | (models.Message.receiver_id == current_user.id)
)
)
await db.commit()
# 3. Оповещаем остальных через WebSocket
from app.websocket.connection_manager import manager
for contact_id in contact_ids:
await manager.send_personal_message({
"type": "chat_deleted",
"contact_id": current_user.id
}, str(contact_id))
return {"status": "ok", "detail": "Все сообщения удалены"}