From 83099a093d57e624e0f5f8ca13f9495658d39979 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 23 Dec 2024 00:53:45 -0700 Subject: [PATCH] enh: message edit --- backend/open_webui/routers/channels.py | 117 ++++++++++++++++++ .../channel/Messages/Message.svelte | 102 ++++++++++++++- 2 files changed, 215 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/routers/channels.py b/backend/open_webui/routers/channels.py index d23cbb169..d15a70798 100644 --- a/backend/open_webui/routers/channels.py +++ b/backend/open_webui/routers/channels.py @@ -217,3 +217,120 @@ async def post_new_message( raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT() ) + + +############################ +# UpdateMessageById +############################ + + +@router.post( + "/{id}/messages/{message_id}/update", response_model=Optional[MessageModel] +) +async def update_message_by_id( + id: str, message_id: str, form_data: MessageForm, user=Depends(get_verified_user) +): + channel = Channels.get_channel_by_id(id) + if not channel: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND + ) + + if not has_access(user.id, type="read", access_control=channel.access_control): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT() + ) + + message = Messages.get_message_by_id(message_id) + if not message: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND + ) + + if message.channel_id != id: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT() + ) + + try: + message = Messages.update_message_by_id(message_id, form_data) + if message: + await sio.emit( + "channel-events", + { + "channel_id": channel.id, + "message_id": message.id, + "data": { + "type": "message:update", + "data": { + **message.model_dump(), + "user": UserNameResponse(**user.model_dump()).model_dump(), + }, + }, + }, + to=f"channel:{channel.id}", + ) + + return MessageModel(**message.model_dump()) + except Exception as e: + log.exception(e) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT() + ) + + +############################ +# DeleteMessageById +############################ + + +@router.delete("/{id}/messages/{message_id}/delete", response_model=bool) +async def delete_message_by_id( + id: str, message_id: str, user=Depends(get_verified_user) +): + channel = Channels.get_channel_by_id(id) + if not channel: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND + ) + + if not has_access(user.id, type="read", access_control=channel.access_control): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT() + ) + + message = Messages.get_message_by_id(message_id) + if not message: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND + ) + + if message.channel_id != id: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT() + ) + + try: + Messages.delete_message_by_id(message_id) + await sio.emit( + "channel-events", + { + "channel_id": channel.id, + "message_id": message.id, + "data": { + "type": "message:delete", + "data": { + **message.model_dump(), + "user": UserNameResponse(**user.model_dump()).model_dump(), + }, + }, + }, + to=f"channel:{channel.id}", + ) + + return True + except Exception as e: + log.exception(e) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT() + ) diff --git a/src/lib/components/channel/Messages/Message.svelte b/src/lib/components/channel/Messages/Message.svelte index 07bdd3307..4d7b5b88f 100644 --- a/src/lib/components/channel/Messages/Message.svelte +++ b/src/lib/components/channel/Messages/Message.svelte @@ -18,10 +18,20 @@ import Markdown from '$lib/components/chat/Messages/Markdown.svelte'; import ProfileImage from '$lib/components/chat/Messages/ProfileImage.svelte'; import Name from '$lib/components/chat/Messages/Name.svelte'; + import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte'; + import GarbageBin from '$lib/components/icons/GarbageBin.svelte'; + import Pencil from '$lib/components/icons/Pencil.svelte'; export let message; export let showUserProfile = true; + export let onDelete: Function = () => {}; + export let onEdit: Function = () => {}; + + let edit = false; + let editedContent = null; + let showDeleteConfirmDialog = false; + const formatDate = (inputDate) => { const date = dayjs(inputDate); const now = dayjs(); @@ -36,14 +46,46 @@ }; + { + await onDelete(message.id); + }} +/> + {#if message}
+ +
{/if} -
- -
+ {#if edit} +
+