- add backend media-group endpoint with atomic message and attachment creation - switch web composer to send multi-media albums through the new endpoint - switch Android batch media sending to upload first and create one album message with caption
187 lines
6.7 KiB
Python
187 lines
6.7 KiB
Python
from fastapi import APIRouter, Depends, status
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.auth.service import get_current_user
|
|
from app.database.session import get_db
|
|
from app.messages.schemas import (
|
|
MessageCreateRequest,
|
|
MessageForwardBulkRequest,
|
|
MessageForwardRequest,
|
|
MessageMediaGroupCreateRequest,
|
|
MessageMediaGroupRead,
|
|
MessageReactionRead,
|
|
MessageReactionToggleRequest,
|
|
MessageRead,
|
|
MessageStatusUpdateRequest,
|
|
MessageUpdateRequest,
|
|
)
|
|
from app.messages.repository import get_message_by_id
|
|
from app.messages.service import (
|
|
create_chat_message,
|
|
create_chat_media_group,
|
|
delete_message,
|
|
delete_message_for_all,
|
|
forward_message,
|
|
forward_message_bulk,
|
|
get_message_thread,
|
|
get_messages,
|
|
list_message_reactions,
|
|
search_messages,
|
|
toggle_message_reaction,
|
|
update_message,
|
|
)
|
|
from app.realtime.schemas import MessageStatusPayload
|
|
from app.realtime.service import realtime_gateway
|
|
from app.users.models import User
|
|
|
|
router = APIRouter(prefix="/messages", tags=["messages"])
|
|
|
|
|
|
@router.post("", response_model=MessageRead, status_code=status.HTTP_201_CREATED)
|
|
async def create_message(
|
|
payload: MessageCreateRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> MessageRead:
|
|
message = await create_chat_message(db, sender_id=current_user.id, payload=payload)
|
|
await realtime_gateway.publish_message_created(
|
|
message=message,
|
|
sender_id=current_user.id,
|
|
client_message_id=payload.client_message_id,
|
|
)
|
|
return message
|
|
|
|
|
|
@router.post("/media-group", response_model=MessageMediaGroupRead, status_code=status.HTTP_201_CREATED)
|
|
async def create_media_group(
|
|
payload: MessageMediaGroupCreateRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> MessageMediaGroupRead:
|
|
result = await create_chat_media_group(db, sender_id=current_user.id, payload=payload)
|
|
await realtime_gateway.publish_message_created(
|
|
message=result.message,
|
|
sender_id=current_user.id,
|
|
client_message_id=payload.client_message_id,
|
|
)
|
|
return result
|
|
|
|
|
|
@router.get("/search", response_model=list[MessageRead])
|
|
async def search_messages_endpoint(
|
|
query: str,
|
|
chat_id: int | None = None,
|
|
limit: int = 50,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> list[MessageRead]:
|
|
return await search_messages(db, user_id=current_user.id, query=query, chat_id=chat_id, limit=limit)
|
|
|
|
|
|
@router.get("/{message_id}/thread", response_model=list[MessageRead])
|
|
async def message_thread(
|
|
message_id: int,
|
|
limit: int = 100,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> list[MessageRead]:
|
|
return await get_message_thread(db, message_id=message_id, user_id=current_user.id, limit=limit)
|
|
|
|
|
|
@router.get("/{chat_id}", response_model=list[MessageRead])
|
|
async def list_messages(
|
|
chat_id: int,
|
|
limit: int = 50,
|
|
before_id: int | None = None,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> list[MessageRead]:
|
|
return await get_messages(db, chat_id=chat_id, user_id=current_user.id, limit=limit, before_id=before_id)
|
|
|
|
|
|
@router.put("/{message_id}", response_model=MessageRead)
|
|
async def edit_message(
|
|
message_id: int,
|
|
payload: MessageUpdateRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> MessageRead:
|
|
message = await update_message(db, message_id=message_id, user_id=current_user.id, payload=payload)
|
|
await realtime_gateway.publish_message_updated(message=message)
|
|
return message
|
|
|
|
|
|
@router.delete("/{message_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def remove_message(
|
|
message_id: int,
|
|
for_all: bool = False,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> None:
|
|
if for_all:
|
|
message = await get_message_by_id(db, message_id)
|
|
await delete_message_for_all(db, message_id=message_id, user_id=current_user.id)
|
|
if message:
|
|
await realtime_gateway.publish_message_deleted(chat_id=message.chat_id, message_id=message_id)
|
|
await realtime_gateway.publish_chat_updated(chat_id=message.chat_id)
|
|
return
|
|
await delete_message(db, message_id=message_id, user_id=current_user.id)
|
|
|
|
|
|
@router.post("/status")
|
|
async def update_status(
|
|
payload: MessageStatusUpdateRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> dict[str, int]:
|
|
return await realtime_gateway.handle_message_status(
|
|
db,
|
|
user_id=current_user.id,
|
|
payload=MessageStatusPayload(chat_id=payload.chat_id, message_id=payload.message_id),
|
|
event=payload.status,
|
|
)
|
|
|
|
|
|
@router.post("/{message_id}/forward", response_model=MessageRead, status_code=status.HTTP_201_CREATED)
|
|
async def forward_message_endpoint(
|
|
message_id: int,
|
|
payload: MessageForwardRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> MessageRead:
|
|
message = await forward_message(db, source_message_id=message_id, sender_id=current_user.id, payload=payload)
|
|
await realtime_gateway.publish_message_created(message=message, sender_id=current_user.id)
|
|
return message
|
|
|
|
|
|
@router.post("/{message_id}/forward-bulk", response_model=list[MessageRead], status_code=status.HTTP_201_CREATED)
|
|
async def forward_message_bulk_endpoint(
|
|
message_id: int,
|
|
payload: MessageForwardBulkRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> list[MessageRead]:
|
|
messages = await forward_message_bulk(db, source_message_id=message_id, sender_id=current_user.id, payload=payload)
|
|
for message in messages:
|
|
await realtime_gateway.publish_message_created(message=message, sender_id=current_user.id)
|
|
return messages
|
|
|
|
|
|
@router.get("/{message_id}/reactions", response_model=list[MessageReactionRead])
|
|
async def list_reactions_endpoint(
|
|
message_id: int,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> list[MessageReactionRead]:
|
|
return await list_message_reactions(db, message_id=message_id, user_id=current_user.id)
|
|
|
|
|
|
@router.post("/{message_id}/reactions/toggle", response_model=list[MessageReactionRead])
|
|
async def toggle_reaction_endpoint(
|
|
message_id: int,
|
|
payload: MessageReactionToggleRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> list[MessageReactionRead]:
|
|
return await toggle_message_reaction(db, message_id=message_id, user_id=current_user.id, payload=payload)
|