feat(messages): support forwarding to multiple chats

This commit is contained in:
2026-03-08 09:55:39 +03:00
parent 8cdcd9531d
commit 7c4a5f990d
4 changed files with 99 additions and 8 deletions

View File

@@ -5,6 +5,7 @@ from app.auth.service import get_current_user
from app.database.session import get_db
from app.messages.schemas import (
MessageCreateRequest,
MessageForwardBulkRequest,
MessageForwardRequest,
MessageReactionRead,
MessageReactionToggleRequest,
@@ -17,6 +18,7 @@ from app.messages.service import (
delete_message,
delete_message_for_all,
forward_message,
forward_message_bulk,
get_messages,
list_message_reactions,
search_messages,
@@ -116,6 +118,19 @@ async def forward_message_endpoint(
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,

View File

@@ -10,6 +10,7 @@ from app.messages.models import Message
from app.messages.spam_guard import enforce_message_spam_policy
from app.messages.schemas import (
MessageCreateRequest,
MessageForwardBulkRequest,
MessageForwardRequest,
MessageReactionRead,
MessageReactionToggleRequest,
@@ -276,6 +277,49 @@ async def forward_message(
return forwarded
async def forward_message_bulk(
db: AsyncSession,
*,
source_message_id: int,
sender_id: int,
payload: MessageForwardBulkRequest,
) -> list[Message]:
source = await repository.get_message_by_id(db, source_message_id)
if not source:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Source message not found")
await ensure_chat_membership(db, chat_id=source.chat_id, user_id=sender_id)
target_chat_ids = list(dict.fromkeys(payload.target_chat_ids))
if not target_chat_ids:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="No target chats")
forwarded_messages: list[Message] = []
for target_chat_id in target_chat_ids:
await ensure_chat_membership(db, chat_id=target_chat_id, user_id=sender_id)
target_chat = await chats_repository.get_chat_by_id(db, target_chat_id)
if not target_chat:
continue
target_membership = await chats_repository.get_chat_member(db, chat_id=target_chat_id, user_id=sender_id)
if not target_membership:
continue
if target_chat.type == ChatType.CHANNEL and target_membership.role == ChatMemberRole.MEMBER:
continue
forwarded = await repository.create_message(
db,
chat_id=target_chat_id,
sender_id=sender_id,
reply_to_message_id=None,
forwarded_from_message_id=source.id,
message_type=source.type,
text=source.text,
)
forwarded_messages.append(forwarded)
await db.commit()
for message in forwarded_messages:
await db.refresh(message)
return forwarded_messages
async def list_message_reactions(
db: AsyncSession,
*,