dimp 2.0.0__tar.gz → 2.1.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.
Files changed (54) hide show
  1. {dimp-2.0.0 → dimp-2.1.0}/PKG-INFO +1 -1
  2. {dimp-2.0.0 → dimp-2.1.0}/dimp/__init__.py +2 -2
  3. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/__init__.py +3 -3
  4. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/contents.py +18 -14
  5. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/files.py +30 -13
  6. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/receipt.py +2 -6
  7. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/__init__.py +2 -2
  8. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/contents.py +5 -5
  9. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/files.py +5 -4
  10. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/receipt.py +1 -55
  11. {dimp-2.0.0 → dimp-2.1.0}/dimp.egg-info/PKG-INFO +1 -1
  12. dimp-2.1.0/dimp.egg-info/requires.txt +2 -0
  13. {dimp-2.0.0 → dimp-2.1.0}/setup.py +3 -3
  14. dimp-2.0.0/dimp.egg-info/requires.txt +0 -2
  15. {dimp-2.0.0 → dimp-2.1.0}/README.md +0 -0
  16. {dimp-2.0.0 → dimp-2.1.0}/dimp/barrack.py +0 -0
  17. {dimp-2.0.0 → dimp-2.1.0}/dimp/crypto/__init__.py +0 -0
  18. {dimp-2.0.0 → dimp-2.1.0}/dimp/crypto/keys.py +0 -0
  19. {dimp-2.0.0 → dimp-2.1.0}/dimp/crypto/pnf.py +0 -0
  20. {dimp-2.0.0 → dimp-2.1.0}/dimp/crypto/ted.py +0 -0
  21. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/base.py +0 -0
  22. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/commands.py +0 -0
  23. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/customized.py +0 -0
  24. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/factory.py +0 -0
  25. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/group_admins.py +0 -0
  26. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/groups.py +0 -0
  27. {dimp-2.0.0 → dimp-2.1.0}/dimp/dkd/money.py +0 -0
  28. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/__init__.py +0 -0
  29. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/delegate.py +0 -0
  30. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/docs.py +0 -0
  31. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/document.py +0 -0
  32. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/entity.py +0 -0
  33. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/group.py +0 -0
  34. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/helper.py +0 -0
  35. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/meta.py +0 -0
  36. {dimp-2.0.0 → dimp-2.1.0}/dimp/mkm/user.py +0 -0
  37. {dimp-2.0.0 → dimp-2.1.0}/dimp/msg/__init__.py +0 -0
  38. {dimp-2.0.0 → dimp-2.1.0}/dimp/msg/base.py +0 -0
  39. {dimp-2.0.0 → dimp-2.1.0}/dimp/msg/envelope.py +0 -0
  40. {dimp-2.0.0 → dimp-2.1.0}/dimp/msg/instant.py +0 -0
  41. {dimp-2.0.0 → dimp-2.1.0}/dimp/msg/reliable.py +0 -0
  42. {dimp-2.0.0 → dimp-2.1.0}/dimp/msg/secure.py +0 -0
  43. {dimp-2.0.0 → dimp-2.1.0}/dimp/packer.py +0 -0
  44. {dimp-2.0.0 → dimp-2.1.0}/dimp/processor.py +0 -0
  45. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/commands.py +0 -0
  46. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/customized.py +0 -0
  47. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/docs.py +0 -0
  48. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/groups.py +0 -0
  49. {dimp-2.0.0 → dimp-2.1.0}/dimp/protocol/money.py +0 -0
  50. {dimp-2.0.0 → dimp-2.1.0}/dimp/transceiver.py +0 -0
  51. {dimp-2.0.0 → dimp-2.1.0}/dimp.egg-info/SOURCES.txt +0 -0
  52. {dimp-2.0.0 → dimp-2.1.0}/dimp.egg-info/dependency_links.txt +0 -0
  53. {dimp-2.0.0 → dimp-2.1.0}/dimp.egg-info/top_level.txt +0 -0
  54. {dimp-2.0.0 → dimp-2.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimp
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: Decentralized Instant Messaging Protocol
5
5
  Home-page: https://github.com/dimchat/core-py
6
6
  Author: Albert Moky
@@ -112,7 +112,7 @@ __all__ = [
112
112
 
113
113
  'Command', 'CommandFactory',
114
114
  'MetaCommand', 'DocumentCommand',
115
- 'ReceiptCommand', 'ReceiptCommandMixIn',
115
+ 'ReceiptCommand',
116
116
 
117
117
  'HistoryCommand', 'GroupCommand',
118
118
  'InviteCommand', 'ExpelCommand', 'JoinCommand', 'QuitCommand', 'QueryCommand', 'ResetCommand',
@@ -127,7 +127,7 @@ __all__ = [
127
127
 
128
128
  'BaseCommand',
129
129
  'BaseMetaCommand', 'BaseDocumentCommand',
130
- 'BaseReceipt', 'BaseReceiptCommand',
130
+ 'BaseReceiptCommand',
131
131
 
132
132
  'BaseHistoryCommand', 'BaseGroupCommand',
133
133
  'InviteGroupCommand', 'ExpelGroupCommand', 'JoinGroupCommand',
@@ -39,7 +39,7 @@ from .money import BaseMoneyContent, TransferMoneyContent
39
39
  from .customized import AppCustomizedContent
40
40
 
41
41
  from .commands import BaseMetaCommand, BaseDocumentCommand
42
- from .receipt import BaseReceipt, BaseReceiptCommand
42
+ from .receipt import BaseReceiptCommand
43
43
 
44
44
  from .groups import BaseHistoryCommand, BaseGroupCommand
45
45
  from .groups import InviteGroupCommand, ExpelGroupCommand, JoinGroupCommand
@@ -72,7 +72,7 @@ __all__ = [
72
72
 
73
73
  'Command', 'CommandFactory',
74
74
  'MetaCommand', 'DocumentCommand',
75
- 'ReceiptCommand', 'ReceiptCommandMixIn',
75
+ 'ReceiptCommand',
76
76
 
77
77
  'HistoryCommand', 'GroupCommand',
78
78
  'InviteCommand', 'ExpelCommand', 'JoinCommand', 'QuitCommand', 'QueryCommand', 'ResetCommand',
@@ -93,7 +93,7 @@ __all__ = [
93
93
  #
94
94
  'BaseCommand',
95
95
  'BaseMetaCommand', 'BaseDocumentCommand',
96
- 'BaseReceipt', 'BaseReceiptCommand',
96
+ 'BaseReceiptCommand',
97
97
 
98
98
  'BaseHistoryCommand', 'BaseGroupCommand',
99
99
  'InviteGroupCommand', 'ExpelGroupCommand', 'JoinGroupCommand',
@@ -199,7 +199,7 @@ class WebPageContent(BaseContent, PageContent):
199
199
 
200
200
  def __init__(self, content: Dict[str, Any] = None,
201
201
  url: URI = None, html: str = None, title: str = None,
202
- desc: Optional[str] = None, icon: Optional[URI] = None):
202
+ desc: Optional[str] = None, icon: Optional[PortableNetworkFile] = None):
203
203
  if content is None:
204
204
  # 1. new content with url, title, desc & icon
205
205
  assert url is not None and title is not None, 'page info error: %s, %s, %s, %s' % (url, title, desc, icon)
@@ -208,6 +208,7 @@ class WebPageContent(BaseContent, PageContent):
208
208
  else:
209
209
  # 2. content info from network
210
210
  super().__init__(content)
211
+ self.__icon = None
211
212
  # URL or HTML
212
213
  if url is not None:
213
214
  self.url = url
@@ -237,14 +238,20 @@ class WebPageContent(BaseContent, PageContent):
237
238
  #
238
239
 
239
240
  @property # Override
240
- def icon(self) -> Optional[URI]:
241
- base64 = self.get_str(key='icon', default=None)
242
- # TODO: convert 'data:' URI
243
- return base64
241
+ def icon(self) -> Optional[PortableNetworkFile]:
242
+ img = self.__icon
243
+ if img is None:
244
+ base64 = self.get_str(key='icon', default=None)
245
+ img = self.__icon = PortableNetworkFile.parse(base64)
246
+ return img
244
247
 
245
248
  @icon.setter # Override
246
- def icon(self, base64: URI):
247
- self['icon'] = base64
249
+ def icon(self, img: PortableNetworkFile):
250
+ if img is None:
251
+ self.pop('icon', None)
252
+ else:
253
+ self['icon'] = img.object
254
+ self.__icon = img
248
255
 
249
256
  #
250
257
  # Description
@@ -340,11 +347,8 @@ class NameCardContent(BaseContent, NameCard):
340
347
 
341
348
  @property # Override
342
349
  def avatar(self) -> Optional[PortableNetworkFile]:
343
- if self.__avatar is None:
350
+ img = self.__avatar
351
+ if img is None:
344
352
  url = self.get('avatar')
345
- if isinstance(url, str) and len(url) == 0:
346
- # ignore empty URL
347
- pass
348
- else:
349
- self.__avatar = PortableNetworkFile.parse(url)
350
- return self.__avatar
353
+ img = self.__avatar = PortableNetworkFile.parse(url)
354
+ return img
@@ -30,8 +30,9 @@
30
30
 
31
31
  from typing import Optional, Any, Dict
32
32
 
33
- from mkm.format import TransportableData
34
33
  from mkm.types import URI
34
+ from mkm.format import TransportableData
35
+ from mkm.format import PortableNetworkFile
35
36
  from mkm.crypto import DecryptKey
36
37
 
37
38
  from dkd import ContentType
@@ -115,16 +116,24 @@ class ImageFileContent(BaseFileContent, ImageContent):
115
116
  url: Optional[URI] = None, password: Optional[DecryptKey] = None):
116
117
  msg_type = ContentType.IMAGE.value if content is None else None
117
118
  super().__init__(content, msg_type, data=data, filename=filename, url=url, password=password)
119
+ # small image
120
+ self.__thumbnail: Optional[PortableNetworkFile] = None
118
121
 
119
122
  @property # Override
120
- def thumbnail(self) -> Optional[URI]:
121
- base64 = self.get_str(key='thumbnail', default=None)
122
- # TODO: convert 'data:' URI
123
- return base64
123
+ def thumbnail(self) -> Optional[PortableNetworkFile]:
124
+ img = self.__thumbnail
125
+ if img is None:
126
+ base64 = self.get_str(key='thumbnail', default=None)
127
+ img = self.__thumbnail = PortableNetworkFile.parse(base64)
128
+ return img
124
129
 
125
130
  @thumbnail.setter # Override
126
- def thumbnail(self, base64: URI):
127
- self['thumbnail'] = base64
131
+ def thumbnail(self, img: PortableNetworkFile):
132
+ if img is None:
133
+ self.pop('thumbnail', None)
134
+ else:
135
+ self['thumbnail'] = img.object
136
+ self.__thumbnail = img
128
137
 
129
138
 
130
139
  class AudioFileContent(BaseFileContent, AudioContent):
@@ -153,13 +162,21 @@ class VideoFileContent(BaseFileContent, VideoContent):
153
162
  url: Optional[URI] = None, password: Optional[DecryptKey] = None):
154
163
  msg_type = ContentType.VIDEO.value if content is None else None
155
164
  super().__init__(content, msg_type, data=data, filename=filename, url=url, password=password)
165
+ # small image
166
+ self.__snapshot: Optional[PortableNetworkFile] = None
156
167
 
157
168
  @property # Override
158
- def snapshot(self) -> Optional[URI]:
159
- base64 = self.get_str(key='thumbnail', default=None)
160
- # TODO: convert 'data:' URI
161
- return base64
169
+ def snapshot(self) -> Optional[PortableNetworkFile]:
170
+ img = self.__snapshot
171
+ if img is None:
172
+ base64 = self.get_str(key='snapshot', default=None)
173
+ img = self.__snapshot = PortableNetworkFile.parse(base64)
174
+ return img
162
175
 
163
176
  @snapshot.setter # Override
164
- def snapshot(self, base64: URI):
165
- self['snapshot'] = base64
177
+ def snapshot(self, img: PortableNetworkFile):
178
+ if img is None:
179
+ self.pop('snapshot', None)
180
+ else:
181
+ self['snapshot'] = img.object
182
+ self.__snapshot = img
@@ -42,12 +42,11 @@ from mkm.types import Converter
42
42
  from dkd import Envelope
43
43
 
44
44
  from ..protocol import Command
45
- from ..protocol import ReceiptCommand, ReceiptCommandMixIn
45
+ from ..protocol import ReceiptCommand
46
46
  from .commands import BaseCommand
47
47
 
48
48
 
49
- # noinspection PyAbstractClass
50
- class BaseReceipt(BaseCommand, ReceiptCommand, ABC):
49
+ class BaseReceiptCommand(BaseCommand, ReceiptCommand, ABC):
51
50
  """
52
51
  Receipt Command
53
52
  ~~~~~~~~~~~~~~~
@@ -127,9 +126,6 @@ class BaseReceipt(BaseCommand, ReceiptCommand, ABC):
127
126
  signature = origin.get('signature')
128
127
  return Converter.get_str(value=signature, default=None)
129
128
 
130
-
131
- class BaseReceiptCommand(BaseReceipt, ReceiptCommandMixIn):
132
-
133
129
  @classmethod
134
130
  def from_text(cls, text: str, origin: Dict[str, Any] = None):
135
131
  return cls(text=text, origin=origin)
@@ -58,7 +58,7 @@ from .customized import CustomizedContent
58
58
 
59
59
  from .commands import Command, CommandFactory
60
60
  from .commands import MetaCommand, DocumentCommand
61
- from .receipt import ReceiptCommand, ReceiptCommandMixIn
61
+ from .receipt import ReceiptCommand
62
62
 
63
63
  from .groups import HistoryCommand, GroupCommand
64
64
  from .groups import InviteCommand, ExpelCommand, JoinCommand, QuitCommand, QueryCommand, ResetCommand
@@ -110,7 +110,7 @@ __all__ = [
110
110
 
111
111
  'Command', 'CommandFactory',
112
112
  'MetaCommand', 'DocumentCommand',
113
- 'ReceiptCommand', 'ReceiptCommandMixIn',
113
+ 'ReceiptCommand',
114
114
 
115
115
  'HistoryCommand', 'GroupCommand',
116
116
  'InviteCommand', 'ExpelCommand', 'JoinCommand', 'QuitCommand', 'QueryCommand', 'ResetCommand',
@@ -208,12 +208,12 @@ class PageContent(Content, ABC):
208
208
 
209
209
  @property
210
210
  @abstractmethod
211
- def icon(self) -> Optional[URI]:
211
+ def icon(self) -> Optional[PortableNetworkFile]:
212
212
  raise NotImplemented
213
213
 
214
214
  @icon.setter
215
215
  @abstractmethod
216
- def icon(self, base64: URI):
216
+ def icon(self, img: PortableNetworkFile):
217
217
  raise NotImplemented
218
218
 
219
219
  #
@@ -263,16 +263,16 @@ class PageContent(Content, ABC):
263
263
  #
264
264
  @classmethod
265
265
  def create(cls, url: Optional[URI], html: Optional[str], title: str,
266
- desc: Optional[str], icon: Optional[URI]):
266
+ desc: Optional[str], icon: Optional[PortableNetworkFile]):
267
267
  from ..dkd import WebPageContent
268
268
  return WebPageContent(url=url, html=html, title=title, desc=desc, icon=icon)
269
269
 
270
270
  @classmethod
271
- def create_with_url(cls, url: URI, title: str, desc: Optional[str], icon: Optional[URI]):
271
+ def create_with_url(cls, url: URI, title: str, desc: Optional[str], icon: Optional[PortableNetworkFile]):
272
272
  return cls.create(url=url, html=None, title=title, desc=desc, icon=icon)
273
273
 
274
274
  @classmethod
275
- def create_with_html(cls, html: str, title: str, desc: Optional[str], icon: Optional[URI]):
275
+ def create_with_html(cls, html: str, title: str, desc: Optional[str], icon: Optional[PortableNetworkFile]):
276
276
  return cls.create(url=None, html=html, title=title, desc=desc, icon=icon)
277
277
 
278
278
 
@@ -33,6 +33,7 @@ from typing import Optional
33
33
 
34
34
  from mkm.types import URI
35
35
  from mkm.format import TransportableData
36
+ from mkm.format import PortableNetworkFile
36
37
  from mkm.crypto import DecryptKey
37
38
  from dkd import ContentType, Content
38
39
 
@@ -175,13 +176,13 @@ class ImageContent(FileContent, ABC):
175
176
 
176
177
  @property
177
178
  @abstractmethod
178
- def thumbnail(self) -> Optional[URI]:
179
+ def thumbnail(self) -> Optional[PortableNetworkFile]:
179
180
  # thumbnail of image
180
181
  raise NotImplemented
181
182
 
182
183
  @thumbnail.setter
183
184
  @abstractmethod
184
- def thumbnail(self, base64: URI):
185
+ def thumbnail(self, img: PortableNetworkFile):
185
186
  raise NotImplemented
186
187
 
187
188
 
@@ -247,11 +248,11 @@ class VideoContent(FileContent, ABC):
247
248
 
248
249
  @property
249
250
  @abstractmethod
250
- def snapshot(self) -> Optional[URI]:
251
+ def snapshot(self) -> Optional[PortableNetworkFile]:
251
252
  # snapshot of video
252
253
  raise NotImplemented
253
254
 
254
255
  @snapshot.setter
255
256
  @abstractmethod
256
- def snapshot(self, base64: URI):
257
+ def snapshot(self, img: PortableNetworkFile):
257
258
  raise NotImplemented
@@ -38,7 +38,7 @@
38
38
  from abc import abstractmethod
39
39
  from typing import Optional, Dict, Any
40
40
 
41
- from dkd import Envelope, Content, InstantMessage
41
+ from dkd import Envelope, Content
42
42
 
43
43
  from .commands import Command
44
44
 
@@ -70,11 +70,6 @@ class ReceiptCommand(Command):
70
70
  def text(self) -> str:
71
71
  raise NotImplemented
72
72
 
73
- @property # protected
74
- @abstractmethod
75
- def origin(self) -> Optional[Dict]:
76
- raise NotImplemented
77
-
78
73
  @property
79
74
  @abstractmethod
80
75
  def original_envelope(self) -> Optional[Envelope]:
@@ -90,10 +85,6 @@ class ReceiptCommand(Command):
90
85
  def original_signature(self) -> Optional[str]:
91
86
  raise NotImplemented
92
87
 
93
- @abstractmethod
94
- def match_message(self, msg: InstantMessage) -> bool:
95
- raise NotImplemented
96
-
97
88
  #
98
89
  # Factory method
99
90
  #
@@ -137,48 +128,3 @@ class ReceiptCommand(Command):
137
128
  info.pop('meta', None)
138
129
  info.pop('visa', None)
139
130
  return info
140
-
141
-
142
- # noinspection PyAbstractClass
143
- class ReceiptCommandMixIn(ReceiptCommand):
144
-
145
- def match_message(self, msg: InstantMessage) -> bool:
146
- if self.origin is None:
147
- # receipt without original message info
148
- return False
149
- # check signature
150
- sig1 = self.original_signature
151
- if sig1 is not None:
152
- # if contains signature, check it
153
- sig2 = msg.get_str(key='signature', default=None)
154
- if sig2 is not None:
155
- return match_signatures(sig1, sig2)
156
- # check envelope
157
- env1 = self.original_envelope
158
- if env1 is not None:
159
- # if contains envelope, check it
160
- if not match_envelopes(env1, msg.envelope):
161
- return False
162
- # check serial number
163
- # (only the original message's receiver can know this number)
164
- return self.original_sn == msg.content.sn
165
-
166
-
167
- def match_signatures(sig1: str, sig2: str) -> bool:
168
- if len(sig1) > 8:
169
- sig1 = sig1[-8:]
170
- if len(sig2) > 8:
171
- sig2 = sig2[-8:]
172
- return sig1 == sig2
173
-
174
-
175
- def match_envelopes(env1: Envelope, env2: Envelope) -> bool:
176
- if env1.sender != env2.sender:
177
- return False
178
- to1 = env1.group
179
- if to1 is None:
180
- to1 = env1.receiver
181
- to2 = env2.group
182
- if to2 is None:
183
- to2 = env2.receiver
184
- return to1 == to2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimp
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: Decentralized Instant Messaging Protocol
5
5
  Home-page: https://github.com/dimchat/core-py
6
6
  Author: Albert Moky
@@ -0,0 +1,2 @@
1
+ dkd>=2.1.0
2
+ mkm>=2.1.0
@@ -14,7 +14,7 @@ import io
14
14
 
15
15
  from setuptools import setup, find_packages
16
16
 
17
- __version__ = '2.0.0'
17
+ __version__ = '2.1.0'
18
18
  __author__ = 'Albert Moky'
19
19
  __contact__ = 'albert.moky@gmail.com'
20
20
 
@@ -38,7 +38,7 @@ setup(
38
38
  'Operating System :: OS Independent',
39
39
  ],
40
40
  install_requires=[
41
- 'dkd>=2.0.0',
42
- 'mkm>=2.0.0',
41
+ 'dkd>=2.1.0',
42
+ 'mkm>=2.1.0',
43
43
  ]
44
44
  )
@@ -1,2 +0,0 @@
1
- dkd>=2.0.0
2
- mkm>=2.0.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes