140 lines
4.4 KiB
Python
140 lines
4.4 KiB
Python
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),
|
||
):
|
||
await db.execute(
|
||
delete(models.Message)
|
||
.where(
|
||
(models.Message.sender_id == current_user.id) | (models.Message.receiver_id == current_user.id)
|
||
)
|
||
)
|
||
await db.commit()
|
||
return {"status": "ok", "detail": "Все сообщения удалены"}
|
||
|