deltachat-rpc-client 2.14.0__tar.gz → 2.16.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of deltachat-rpc-client might be problematic. Click here for more details.

Files changed (33) hide show
  1. {deltachat_rpc_client-2.14.0/src/deltachat_rpc_client.egg-info → deltachat_rpc_client-2.16.0}/PKG-INFO +1 -1
  2. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/pyproject.toml +1 -1
  3. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/account.py +6 -0
  4. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/chat.py +10 -0
  5. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/const.py +4 -0
  6. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/message.py +12 -0
  7. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0/src/deltachat_rpc_client.egg-info}/PKG-INFO +1 -1
  8. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client.egg-info/SOURCES.txt +1 -0
  9. deltachat_rpc_client-2.16.0/tests/test_calls.py +86 -0
  10. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_something.py +48 -0
  11. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/LICENSE +0 -0
  12. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/README.md +0 -0
  13. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/setup.cfg +0 -0
  14. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/__init__.py +0 -0
  15. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/_utils.py +0 -0
  16. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/client.py +0 -0
  17. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/contact.py +0 -0
  18. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/deltachat.py +0 -0
  19. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/events.py +0 -0
  20. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/py.typed +0 -0
  21. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/pytestplugin.py +0 -0
  22. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client/rpc.py +0 -0
  23. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client.egg-info/dependency_links.txt +0 -0
  24. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client.egg-info/entry_points.txt +0 -0
  25. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/src/deltachat_rpc_client.egg-info/top_level.txt +0 -0
  26. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_account_events.py +0 -0
  27. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_chatlist_events.py +0 -0
  28. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_iroh_webxdc.py +0 -0
  29. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_key_transfer.py +0 -0
  30. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_multidevice.py +0 -0
  31. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_securejoin.py +0 -0
  32. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_vcard.py +0 -0
  33. {deltachat_rpc_client-2.14.0 → deltachat_rpc_client-2.16.0}/tests/test_webxdc.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deltachat-rpc-client
3
- Version: 2.14.0
3
+ Version: 2.16.0
4
4
  Summary: Python client for Delta Chat core JSON-RPC interface
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Intended Audience :: Developers
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deltachat-rpc-client"
7
- version = "2.14.0"
7
+ version = "2.16.0"
8
8
  description = "Python client for Delta Chat core JSON-RPC interface"
9
9
  classifiers = [
10
10
  "Development Status :: 5 - Production/Stable",
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
5
6
  from dataclasses import dataclass
6
7
  from typing import TYPE_CHECKING, Optional, Union
7
8
  from warnings import warn
@@ -470,3 +471,8 @@ class Account:
470
471
  def initiate_autocrypt_key_transfer(self) -> None:
471
472
  """Send Autocrypt Setup Message."""
472
473
  return self._rpc.initiate_autocrypt_key_transfer(self.id)
474
+
475
+ def ice_servers(self) -> list:
476
+ """Return ICE servers for WebRTC configuration."""
477
+ ice_servers_json = self._rpc.ice_servers(self.id)
478
+ return json.loads(ice_servers_json)
@@ -168,6 +168,11 @@ class Chat:
168
168
  msg_id = self._rpc.send_sticker(self.account.id, self.id, path)
169
169
  return Message(self.account, msg_id)
170
170
 
171
+ def resend_messages(self, messages: list[Message]) -> None:
172
+ """Resend a list of messages to this chat."""
173
+ msg_ids = [msg.id for msg in messages]
174
+ self._rpc.resend_messages(self.account.id, msg_ids)
175
+
171
176
  def forward_messages(self, messages: list[Message]) -> None:
172
177
  """Forward a list of messages to this chat."""
173
178
  msg_ids = [msg.id for msg in messages]
@@ -289,3 +294,8 @@ class Chat:
289
294
  f.write(vcard.encode())
290
295
  f.flush()
291
296
  self._rpc.send_msg(self.account.id, self.id, {"viewtype": ViewType.VCARD, "file": f.name})
297
+
298
+ def place_outgoing_call(self, place_call_info: str) -> Message:
299
+ """Starts an outgoing call."""
300
+ msg_id = self._rpc.place_outgoing_call(self.account.id, self.id, place_call_info)
301
+ return Message(self.account, msg_id)
@@ -73,6 +73,10 @@ class EventType(str, Enum):
73
73
  CHATLIST_ITEM_CHANGED = "ChatlistItemChanged"
74
74
  ACCOUNTS_CHANGED = "AccountsChanged"
75
75
  ACCOUNTS_ITEM_CHANGED = "AccountsItemChanged"
76
+ INCOMING_CALL = "IncomingCall"
77
+ INCOMING_CALL_ACCEPTED = "IncomingCallAccepted"
78
+ OUTGOING_CALL_ACCEPTED = "OutgoingCallAccepted"
79
+ CALL_ENDED = "CallEnded"
76
80
  CONFIG_SYNCED = "ConfigSynced"
77
81
  WEBXDC_REALTIME_DATA = "WebxdcRealtimeData"
78
82
  WEBXDC_REALTIME_ADVERTISEMENT_RECEIVED = "WebxdcRealtimeAdvertisementReceived"
@@ -102,3 +102,15 @@ class Message:
102
102
  def send_webxdc_realtime_data(self, data) -> None:
103
103
  """Send data to the realtime channel."""
104
104
  yield self._rpc.send_webxdc_realtime_data.future(self.account.id, self.id, list(data))
105
+
106
+ def accept_incoming_call(self, accept_call_info):
107
+ """Accepts an incoming call."""
108
+ self._rpc.accept_incoming_call(self.account.id, self.id, accept_call_info)
109
+
110
+ def end_call(self):
111
+ """Ends incoming or outgoing call."""
112
+ self._rpc.end_call(self.account.id, self.id)
113
+
114
+ def get_call_info(self) -> AttrDict:
115
+ """Return information about the call."""
116
+ return AttrDict(self._rpc.call_info(self.account.id, self.id))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deltachat-rpc-client
3
- Version: 2.14.0
3
+ Version: 2.16.0
4
4
  Summary: Python client for Delta Chat core JSON-RPC interface
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Intended Audience :: Developers
@@ -20,6 +20,7 @@ src/deltachat_rpc_client.egg-info/dependency_links.txt
20
20
  src/deltachat_rpc_client.egg-info/entry_points.txt
21
21
  src/deltachat_rpc_client.egg-info/top_level.txt
22
22
  tests/test_account_events.py
23
+ tests/test_calls.py
23
24
  tests/test_chatlist_events.py
24
25
  tests/test_iroh_webxdc.py
25
26
  tests/test_key_transfer.py
@@ -0,0 +1,86 @@
1
+ from deltachat_rpc_client import EventType, Message
2
+
3
+
4
+ def test_calls(acfactory) -> None:
5
+ alice, bob = acfactory.get_online_accounts(2)
6
+
7
+ place_call_info = "offer"
8
+ accept_call_info = "answer"
9
+
10
+ alice_contact_bob = alice.create_contact(bob, "Bob")
11
+ alice_chat_bob = alice_contact_bob.create_chat()
12
+ outgoing_call_message = alice_chat_bob.place_outgoing_call(place_call_info)
13
+ assert outgoing_call_message.get_call_info().state.kind == "Alerting"
14
+
15
+ incoming_call_event = bob.wait_for_event(EventType.INCOMING_CALL)
16
+ assert incoming_call_event.place_call_info == place_call_info
17
+ assert not incoming_call_event.has_video # Cannot be parsed as SDP, so false by default
18
+ incoming_call_message = Message(bob, incoming_call_event.msg_id)
19
+ assert incoming_call_message.get_call_info().state.kind == "Alerting"
20
+ assert not incoming_call_message.get_call_info().has_video
21
+
22
+ incoming_call_message.accept_incoming_call(accept_call_info)
23
+ assert incoming_call_message.get_call_info().sdp_offer == place_call_info
24
+ assert incoming_call_message.get_call_info().state.kind == "Active"
25
+ outgoing_call_accepted_event = alice.wait_for_event(EventType.OUTGOING_CALL_ACCEPTED)
26
+ assert outgoing_call_accepted_event.accept_call_info == accept_call_info
27
+ assert outgoing_call_message.get_call_info().state.kind == "Active"
28
+
29
+ outgoing_call_message.end_call()
30
+ assert outgoing_call_message.get_call_info().state.kind == "Completed"
31
+
32
+ end_call_event = bob.wait_for_event(EventType.CALL_ENDED)
33
+ assert end_call_event.msg_id == outgoing_call_message.id
34
+ assert incoming_call_message.get_call_info().state.kind == "Completed"
35
+
36
+
37
+ def test_video_call(acfactory) -> None:
38
+ # Example from <https://datatracker.ietf.org/doc/rfc9143/>
39
+ # with `s= ` replaced with `s=-`.
40
+ #
41
+ # `s=` cannot be empty according to RFC 3264,
42
+ # so it is more clear as `s=-`.
43
+ place_call_info = """v=0\r
44
+ o=alice 2890844526 2890844526 IN IP6 2001:db8::3\r
45
+ s=-\r
46
+ c=IN IP6 2001:db8::3\r
47
+ t=0 0\r
48
+ a=group:BUNDLE foo bar\r
49
+ \r
50
+ m=audio 10000 RTP/AVP 0 8 97\r
51
+ b=AS:200\r
52
+ a=mid:foo\r
53
+ a=rtcp-mux\r
54
+ a=rtpmap:0 PCMU/8000\r
55
+ a=rtpmap:8 PCMA/8000\r
56
+ a=rtpmap:97 iLBC/8000\r
57
+ a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid\r
58
+ \r
59
+ m=video 10002 RTP/AVP 31 32\r
60
+ b=AS:1000\r
61
+ a=mid:bar\r
62
+ a=rtcp-mux\r
63
+ a=rtpmap:31 H261/90000\r
64
+ a=rtpmap:32 MPV/90000\r
65
+ a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid\r
66
+ """
67
+
68
+ alice, bob = acfactory.get_online_accounts(2)
69
+
70
+ alice_contact_bob = alice.create_contact(bob, "Bob")
71
+ alice_chat_bob = alice_contact_bob.create_chat()
72
+ alice_chat_bob.place_outgoing_call(place_call_info)
73
+
74
+ incoming_call_event = bob.wait_for_event(EventType.INCOMING_CALL)
75
+ assert incoming_call_event.place_call_info == place_call_info
76
+ assert incoming_call_event.has_video
77
+
78
+ incoming_call_message = Message(bob, incoming_call_event.msg_id)
79
+ assert incoming_call_message.get_call_info().has_video
80
+
81
+
82
+ def test_ice_servers(acfactory) -> None:
83
+ alice = acfactory.get_online_account()
84
+
85
+ ice_servers = alice.ice_servers()
86
+ assert len(ice_servers) == 1
@@ -252,6 +252,7 @@ def test_chat(acfactory) -> None:
252
252
  bob_chat_alice.get_encryption_info()
253
253
 
254
254
  group = alice.create_group("test group")
255
+ to_resend = group.send_text("will be resent")
255
256
  group.add_contact(alice_contact_bob)
256
257
  group.get_qr_code()
257
258
 
@@ -263,6 +264,7 @@ def test_chat(acfactory) -> None:
263
264
 
264
265
  msg = group.send_message(text="hi")
265
266
  assert (msg.get_snapshot()).text == "hi"
267
+ group.resend_messages([to_resend])
266
268
  group.forward_messages([msg])
267
269
 
268
270
  group.set_draft(text="test draft")
@@ -329,6 +331,52 @@ def test_message(acfactory) -> None:
329
331
  assert reactions == snapshot.reactions
330
332
 
331
333
 
334
+ def test_receive_imf_failure(acfactory) -> None:
335
+ alice, bob = acfactory.get_online_accounts(2)
336
+ alice_contact_bob = alice.create_contact(bob, "Bob")
337
+ alice_chat_bob = alice_contact_bob.create_chat()
338
+
339
+ bob.set_config("fail_on_receiving_full_msg", "1")
340
+ alice_chat_bob.send_text("Hello!")
341
+ event = bob.wait_for_incoming_msg_event()
342
+ chat_id = event.chat_id
343
+ msg_id = event.msg_id
344
+ message = bob.get_message_by_id(msg_id)
345
+ snapshot = message.get_snapshot()
346
+ assert snapshot.chat_id == chat_id
347
+ assert snapshot.download_state == DownloadState.AVAILABLE
348
+ assert snapshot.error is not None
349
+ assert snapshot.show_padlock
350
+
351
+ # The failed message doesn't break the IMAP loop.
352
+ bob.set_config("fail_on_receiving_full_msg", "0")
353
+ alice_chat_bob.send_text("Hello again!")
354
+ event = bob.wait_for_incoming_msg_event()
355
+ assert event.chat_id == chat_id
356
+ msg_id = event.msg_id
357
+ message1 = bob.get_message_by_id(msg_id)
358
+ snapshot = message1.get_snapshot()
359
+ assert snapshot.chat_id == chat_id
360
+ assert snapshot.download_state == DownloadState.DONE
361
+ assert snapshot.error is None
362
+
363
+ # The failed message can be re-downloaded later.
364
+ bob._rpc.download_full_message(bob.id, message.id)
365
+ event = bob.wait_for_event(EventType.MSGS_CHANGED)
366
+ message = bob.get_message_by_id(event.msg_id)
367
+ snapshot = message.get_snapshot()
368
+ assert snapshot.download_state == DownloadState.IN_PROGRESS
369
+ event = bob.wait_for_event(EventType.MSGS_CHANGED)
370
+ assert event.chat_id == chat_id
371
+ msg_id = event.msg_id
372
+ message = bob.get_message_by_id(msg_id)
373
+ snapshot = message.get_snapshot()
374
+ assert snapshot.chat_id == chat_id
375
+ assert snapshot.download_state == DownloadState.DONE
376
+ assert snapshot.error is None
377
+ assert snapshot.text == "Hello!"
378
+
379
+
332
380
  def test_selfavatar_sync(acfactory, data, log) -> None:
333
381
  alice = acfactory.get_online_account()
334
382