Skip to content

Commit c911a8b

Browse files
daksh-rDaksh
andauthored
Feat: Added Delete for me support on behalf of a user (#204)
* feat: delete for me * fix linter issues * fix flag * fix tests * fix tests * fix lint * upadte testst * tests --------- Co-authored-by: Daksh <[email protected]>
1 parent 91beb00 commit c911a8b

File tree

5 files changed

+94
-11
lines changed

5 files changed

+94
-11
lines changed

stream_chat/async_chat/client.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ async def _make_request(
109109
headers["Authorization"] = self.auth_token
110110
headers["stream-auth-type"] = "jwt"
111111

112-
if method.__name__ in ["post", "put", "patch"]:
112+
if method.__name__ in ["post", "put", "patch", "delete"]:
113113
serialized = json.dumps(data)
114114

115115
async with method(
@@ -134,8 +134,10 @@ async def post(
134134
async def get(self, relative_url: str, params: Dict = None) -> StreamResponse:
135135
return await self._make_request(self.session.get, relative_url, params, None)
136136

137-
async def delete(self, relative_url: str, params: Dict = None) -> StreamResponse:
138-
return await self._make_request(self.session.delete, relative_url, params, None)
137+
async def delete(
138+
self, relative_url: str, params: Dict = None, data: Any = None
139+
) -> StreamResponse:
140+
return await self._make_request(self.session.delete, relative_url, params, data)
139141

140142
async def patch(
141143
self, relative_url: str, params: Dict = None, data: Any = None
@@ -355,8 +357,23 @@ async def update_message_partial(
355357
data.update(options)
356358
return await self.put(f"messages/{message_id}", data=data)
357359

358-
async def delete_message(self, message_id: str, **options: Any) -> StreamResponse:
359-
return await self.delete(f"messages/{message_id}", options)
360+
async def delete_message(
361+
self,
362+
message_id: str,
363+
delete_for_me: bool = False,
364+
deleted_by: str = None,
365+
**options: Any,
366+
) -> StreamResponse:
367+
if delete_for_me and not deleted_by:
368+
raise ValueError("deleted_by is required when delete_for_me is True")
369+
370+
params = options.copy()
371+
if delete_for_me:
372+
body = {"delete_for_me": True, "user": {"id": deleted_by}}
373+
return await self.delete(f"messages/{message_id}", None, body)
374+
if deleted_by:
375+
params["deleted_by"] = deleted_by
376+
return await self.delete(f"messages/{message_id}", params)
360377

361378
async def undelete_message(self, message_id: str, user_id: str) -> StreamResponse:
362379
return await self.post(

stream_chat/base/client.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,20 @@ def update_message_partial(
560560

561561
@abc.abstractmethod
562562
def delete_message(
563-
self, message_id: str, **options: Any
563+
self,
564+
message_id: str,
565+
delete_for_me: bool = False,
566+
deleted_by: str = None,
567+
**options: Any,
564568
) -> Union[StreamResponse, Awaitable[StreamResponse]]:
565569
"""
566570
Deletes a message.
571+
572+
Args:
573+
message_id: The ID of the message to delete
574+
delete_for_me: If True, deletes the message only for the specified user
575+
deleted_by: The user ID who is deleting the message (required when delete_for_me is True)
576+
**options: Additional options to pass to the delete request
567577
"""
568578
pass
569579

stream_chat/client.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ def _make_request(
8484
data: Any = None,
8585
) -> StreamResponse:
8686
params = params or {}
87+
# Convert boolean values to lowercase strings for consistency with async implementation
88+
params = {
89+
k: str(v).lower() if isinstance(v, bool) else v for k, v in params.items()
90+
}
8791
data = data or {}
8892
serialized = None
8993
default_params = self.get_default_params()
@@ -94,7 +98,9 @@ def _make_request(
9498

9599
url = f"{self.base_url}/{relative_url}"
96100

97-
if method.__name__ in ["post", "put", "patch"]:
101+
if method.__name__ in ["post", "put", "patch"] or (
102+
method.__name__ == "delete" and data
103+
):
98104
serialized = json.dumps(data)
99105

100106
response = method(
@@ -119,8 +125,10 @@ def post(
119125
def get(self, relative_url: str, params: Dict = None) -> StreamResponse:
120126
return self._make_request(self.session.get, relative_url, params, None)
121127

122-
def delete(self, relative_url: str, params: Dict = None) -> StreamResponse:
123-
return self._make_request(self.session.delete, relative_url, params, None)
128+
def delete(
129+
self, relative_url: str, params: Dict = None, data: Any = None
130+
) -> StreamResponse:
131+
return self._make_request(self.session.delete, relative_url, params, data)
124132

125133
def patch(
126134
self, relative_url: str, params: Dict = None, data: Any = None
@@ -342,8 +350,24 @@ def update_message_partial(
342350
data.update(options)
343351
return self.put(f"messages/{message_id}", data=data)
344352

345-
def delete_message(self, message_id: str, **options: Any) -> StreamResponse:
346-
return self.delete(f"messages/{message_id}", options)
353+
def delete_message(
354+
self,
355+
message_id: str,
356+
delete_for_me: bool = False,
357+
deleted_by: str = None,
358+
**options: Any,
359+
) -> StreamResponse:
360+
if delete_for_me and not deleted_by:
361+
raise ValueError("deleted_by is required when delete_for_me is True")
362+
363+
params = options.copy()
364+
if delete_for_me:
365+
# Send in body with acting user for server-side auth compatibility
366+
body = {"delete_for_me": True, "user": {"id": deleted_by}}
367+
return self.delete(f"messages/{message_id}", None, body)
368+
if deleted_by:
369+
params["deleted_by"] = deleted_by
370+
return self.delete(f"messages/{message_id}", params)
347371

348372
def undelete_message(self, message_id: str, user_id: str) -> StreamResponse:
349373
return self.post(

stream_chat/tests/async_chat/test_client.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,23 @@ async def test_delete_message(
462462
)
463463
await client.delete_message(msg_id, hard=True)
464464

465+
async def test_delete_message_for_me(
466+
self, client: StreamChatAsync, channel: Channel, random_user: Dict
467+
):
468+
"""Test deleting a message for a specific user (delete for me functionality)"""
469+
msg_id = str(uuid.uuid4())
470+
await channel.send_message(
471+
{"id": msg_id, "text": "helloworld"}, random_user["id"]
472+
)
473+
474+
# Delete message for the user
475+
response = await client.delete_message(
476+
msg_id, delete_for_me=True, deleted_by=random_user["id"]
477+
)
478+
479+
# Verify the request succeeded
480+
assert response.is_ok()
481+
465482
async def test_flag_message(
466483
self, client: StreamChatAsync, channel: Channel, random_user, server_user: Dict
467484
):

stream_chat/tests/test_client.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,21 @@ def test_delete_message(self, client: StreamChat, channel, random_user: Dict):
509509
channel.send_message({"id": msg_id, "text": "helloworld"}, random_user["id"])
510510
client.delete_message(msg_id, hard=True)
511511

512+
def test_delete_message_for_me(
513+
self, client: StreamChat, channel, random_user: Dict
514+
):
515+
"""Test deleting a message for a specific user (delete for me functionality)"""
516+
msg_id = str(uuid.uuid4())
517+
channel.send_message({"id": msg_id, "text": "helloworld"}, random_user["id"])
518+
519+
# Delete message for the user
520+
response = client.delete_message(
521+
msg_id, delete_for_me=True, deleted_by=random_user["id"]
522+
)
523+
524+
# Verify the request succeeded
525+
assert response.is_ok()
526+
512527
def test_flag_message(
513528
self, client: StreamChat, channel, random_user, server_user: Dict
514529
):

0 commit comments

Comments
 (0)