feat(threads): support nested replies in thread API and panel
All checks were successful
CI / test (push) Successful in 31s
All checks were successful
CI / test (push) Successful in 31s
This commit is contained in:
@@ -152,6 +152,34 @@ async def list_message_thread(
|
||||
return list(result.scalars().all())
|
||||
|
||||
|
||||
async def list_messages_by_parent_ids(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
chat_id: int,
|
||||
user_id: int,
|
||||
parent_ids: list[int],
|
||||
limit: int = 200,
|
||||
) -> list[Message]:
|
||||
if not parent_ids:
|
||||
return []
|
||||
stmt = (
|
||||
select(Message)
|
||||
.outerjoin(
|
||||
MessageHidden,
|
||||
(MessageHidden.message_id == Message.id) & (MessageHidden.user_id == user_id),
|
||||
)
|
||||
.where(
|
||||
Message.chat_id == chat_id,
|
||||
MessageHidden.id.is_(None),
|
||||
Message.reply_to_message_id.in_(parent_ids),
|
||||
)
|
||||
.order_by(Message.id.asc())
|
||||
.limit(max(1, min(limit, 500)))
|
||||
)
|
||||
result = await db.execute(stmt)
|
||||
return list(result.scalars().all())
|
||||
|
||||
|
||||
async def delete_message(db: AsyncSession, message: Message) -> None:
|
||||
await db.delete(message)
|
||||
|
||||
|
||||
@@ -188,7 +188,29 @@ async def get_message_thread(
|
||||
if not root:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Message not found")
|
||||
await ensure_chat_membership(db, chat_id=root.chat_id, user_id=user_id)
|
||||
return await repository.list_message_thread(db, root_message_id=message_id, user_id=user_id, limit=limit)
|
||||
safe_limit = max(1, min(limit, 500))
|
||||
collected: dict[int, Message] = {root.id: root}
|
||||
frontier: list[int] = [root.id]
|
||||
remaining = safe_limit - 1
|
||||
while frontier and remaining > 0:
|
||||
batch = await repository.list_messages_by_parent_ids(
|
||||
db,
|
||||
chat_id=root.chat_id,
|
||||
user_id=user_id,
|
||||
parent_ids=frontier,
|
||||
limit=min(remaining, 200),
|
||||
)
|
||||
next_frontier: list[int] = []
|
||||
for message in batch:
|
||||
if message.id in collected:
|
||||
continue
|
||||
collected[message.id] = message
|
||||
next_frontier.append(message.id)
|
||||
remaining -= 1
|
||||
if remaining <= 0:
|
||||
break
|
||||
frontier = next_frontier
|
||||
return sorted(collected.values(), key=lambda item: item.id)
|
||||
|
||||
|
||||
async def update_message(
|
||||
|
||||
Reference in New Issue
Block a user