dimples 0.2.0__tar.gz → 0.2.2__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 (119) hide show
  1. {dimples-0.2.0 → dimples-0.2.2}/PKG-INFO +1 -1
  2. {dimples-0.2.0 → dimples-0.2.2}/dimples/__init__.py +0 -1
  3. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/__init__.py +0 -1
  4. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/__init__.py +2 -2
  5. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/grp_expel.py +24 -12
  6. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/grp_invite.py +14 -9
  7. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/grp_query.py +12 -6
  8. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/grp_quit.py +22 -11
  9. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/grp_reset.py +26 -13
  10. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/history.py +12 -9
  11. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/messenger.py +1 -1
  12. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/processor.py +8 -13
  13. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/__init__.py +0 -1
  14. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/ans.py +2 -0
  15. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/protocol/__init__.py +0 -4
  16. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/account.py +3 -1
  17. {dimples-0.2.0 → dimples-0.2.2}/dimples/edge/shared.py +11 -1
  18. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/__init__.py +1 -1
  19. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/cpu/__init__.py +1 -3
  20. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/cpu/ans.py +2 -3
  21. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/cpu/handshake.py +6 -2
  22. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/cpu/login.py +6 -1
  23. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/cpu/report.py +14 -6
  24. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/dispatcher.py +7 -7
  25. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/processor.py +4 -7
  26. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/session.py +2 -1
  27. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/trace.py +3 -2
  28. {dimples-0.2.0 → dimples-0.2.2}/dimples/station/shared.py +11 -1
  29. {dimples-0.2.0 → dimples-0.2.2}/dimples.egg-info/PKG-INFO +1 -1
  30. {dimples-0.2.0 → dimples-0.2.2}/dimples.egg-info/SOURCES.txt +0 -3
  31. {dimples-0.2.0 → dimples-0.2.2}/dimples.egg-info/requires.txt +2 -2
  32. {dimples-0.2.0 → dimples-0.2.2}/setup.py +3 -3
  33. dimples-0.2.0/dimples/client/cpu/receipt.py +0 -48
  34. dimples-0.2.0/dimples/common/protocol/receipt.py +0 -179
  35. dimples-0.2.0/dimples/server/cpu/receipt.py +0 -48
  36. {dimples-0.2.0 → dimples-0.2.2}/README.md +0 -0
  37. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/handshake.py +0 -0
  38. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/login.py +0 -0
  39. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/cpu/text.py +0 -0
  40. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/group.py +0 -0
  41. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/network/__init__.py +0 -0
  42. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/network/session.py +0 -0
  43. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/network/state.py +0 -0
  44. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/network/transition.py +0 -0
  45. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/packer.py +0 -0
  46. {dimples-0.2.0 → dimples-0.2.2}/dimples/client/terminal.py +0 -0
  47. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/dbi/__init__.py +0 -0
  48. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/dbi/account.py +0 -0
  49. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/dbi/message.py +0 -0
  50. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/dbi/session.py +0 -0
  51. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/facebook.py +0 -0
  52. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/messenger.py +0 -0
  53. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/packer.py +0 -0
  54. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/protocol/ans.py +0 -0
  55. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/protocol/handshake.py +0 -0
  56. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/protocol/login.py +0 -0
  57. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/protocol/report.py +0 -0
  58. {dimples-0.2.0 → dimples-0.2.2}/dimples/common/session.py +0 -0
  59. {dimples-0.2.0 → dimples-0.2.2}/dimples/config.py +0 -0
  60. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/__init__.py +0 -0
  61. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/gate.py +0 -0
  62. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/gatekeeper.py +0 -0
  63. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/mars.py +0 -0
  64. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/mtp.py +0 -0
  65. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/protocol/__init__.py +0 -0
  66. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/protocol/mars.py +0 -0
  67. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/protocol/ws.py +0 -0
  68. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/queue.py +0 -0
  69. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/seeker.py +0 -0
  70. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/session.py +0 -0
  71. {dimples-0.2.0 → dimples-0.2.2}/dimples/conn/ws.py +0 -0
  72. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/__init__.py +0 -0
  73. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/__init__.py +0 -0
  74. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/base.py +0 -0
  75. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/document.py +0 -0
  76. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/group.py +0 -0
  77. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/login.py +0 -0
  78. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/meta.py +0 -0
  79. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/private.py +0 -0
  80. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/station.py +0 -0
  81. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/dos/user.py +0 -0
  82. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/message.py +0 -0
  83. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/session.py +0 -0
  84. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_cipherkey.py +0 -0
  85. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_document.py +0 -0
  86. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_group.py +0 -0
  87. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_login.py +0 -0
  88. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_message.py +0 -0
  89. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_meta.py +0 -0
  90. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_private.py +0 -0
  91. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_station.py +0 -0
  92. {dimples-0.2.0 → dimples-0.2.2}/dimples/database/t_user.py +0 -0
  93. {dimples-0.2.0 → dimples-0.2.2}/dimples/edge/__init__.py +0 -0
  94. {dimples-0.2.0 → dimples-0.2.2}/dimples/edge/octopus.py +0 -0
  95. {dimples-0.2.0 → dimples-0.2.2}/dimples/edge/start.py +0 -0
  96. {dimples-0.2.0 → dimples-0.2.2}/dimples/register/__init__.py +0 -0
  97. {dimples-0.2.0 → dimples-0.2.2}/dimples/register/generate.py +0 -0
  98. {dimples-0.2.0 → dimples-0.2.2}/dimples/register/modify.py +0 -0
  99. {dimples-0.2.0 → dimples-0.2.2}/dimples/register/run.py +0 -0
  100. {dimples-0.2.0 → dimples-0.2.2}/dimples/register/shared.py +0 -0
  101. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/broadcast.py +0 -0
  102. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/cpu/document.py +0 -0
  103. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/messenger.py +0 -0
  104. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/packer.py +0 -0
  105. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/push.py +0 -0
  106. {dimples-0.2.0 → dimples-0.2.2}/dimples/server/session_center.py +0 -0
  107. {dimples-0.2.0 → dimples-0.2.2}/dimples/station/__init__.py +0 -0
  108. {dimples-0.2.0 → dimples-0.2.2}/dimples/station/handler.py +0 -0
  109. {dimples-0.2.0 → dimples-0.2.2}/dimples/station/start.py +0 -0
  110. {dimples-0.2.0 → dimples-0.2.2}/dimples/utils/__init__.py +0 -0
  111. {dimples-0.2.0 → dimples-0.2.2}/dimples/utils/cache.py +0 -0
  112. {dimples-0.2.0 → dimples-0.2.2}/dimples/utils/checker.py +0 -0
  113. {dimples-0.2.0 → dimples-0.2.2}/dimples/utils/dos.py +0 -0
  114. {dimples-0.2.0 → dimples-0.2.2}/dimples/utils/log.py +0 -0
  115. {dimples-0.2.0 → dimples-0.2.2}/dimples/utils/singleton.py +0 -0
  116. {dimples-0.2.0 → dimples-0.2.2}/dimples.egg-info/dependency_links.txt +0 -0
  117. {dimples-0.2.0 → dimples-0.2.2}/dimples.egg-info/entry_points.txt +0 -0
  118. {dimples-0.2.0 → dimples-0.2.2}/dimples.egg-info/top_level.txt +0 -0
  119. {dimples-0.2.0 → dimples-0.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimples
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: DIMP Library for Edges and Stations
5
5
  Home-page: https://github.com/dimchat/demo-py
6
6
  Author: Albert Moky
@@ -32,7 +32,6 @@ from mkm.protocol import *
32
32
  from dimp.mkm import *
33
33
  from dimp.dkd import *
34
34
  from dimsdk import *
35
- from dimsdk.cpu import *
36
35
  from dimplugins import *
37
36
  from dimplugins.network import NetworkType
38
37
  from dimplugins.entity import EntityID, EntityIDFactory
@@ -48,7 +48,6 @@ __all__ = [
48
48
  #
49
49
  'HandshakeCommandProcessor',
50
50
  'LoginCommandProcessor',
51
- 'ReceiptCommandProcessor',
52
51
 
53
52
  #
54
53
  # Client
@@ -34,7 +34,6 @@ from .text import TextContentProcessor
34
34
 
35
35
  from .handshake import HandshakeCommandProcessor
36
36
  from .login import LoginCommandProcessor
37
- from .receipt import ReceiptCommandProcessor
38
37
 
39
38
  from .history import HistoryCommandProcessor, GroupCommandProcessor
40
39
  from .grp_invite import InviteCommandProcessor
@@ -44,14 +43,15 @@ from .grp_reset import ResetCommandProcessor
44
43
  from .grp_query import QueryCommandProcessor
45
44
 
46
45
  __all__ = [
46
+
47
47
  'TextContentProcessor',
48
48
 
49
49
  'HandshakeCommandProcessor',
50
50
  'LoginCommandProcessor',
51
- 'ReceiptCommandProcessor',
52
51
 
53
52
  'HistoryCommandProcessor',
54
53
  'GroupCommandProcessor',
55
54
  'InviteCommandProcessor', 'ExpelCommandProcessor', 'QuitCommandProcessor',
56
55
  'ResetCommandProcessor', 'QueryCommandProcessor',
56
+
57
57
  ]
@@ -48,10 +48,6 @@ from .history import GroupCommandProcessor
48
48
 
49
49
  class ExpelCommandProcessor(GroupCommandProcessor):
50
50
 
51
- STR_EXPEL_CMD_ERROR = 'Expel command error.'
52
- STR_EXPEL_NOT_ALLOWED = 'Sorry, you are not allowed to expel member from this group.'
53
- STR_CANNOT_EXPEL_OWNER = 'Group owner cannot be expelled.'
54
-
55
51
  # Override
56
52
  def process(self, content: Content, msg: ReliableMessage) -> List[Content]:
57
53
  assert isinstance(content, ExpelCommand), 'expel command error: %s' % content
@@ -61,25 +57,41 @@ class ExpelCommandProcessor(GroupCommandProcessor):
61
57
  members = facebook.members(identifier=group)
62
58
  # 0. check group
63
59
  if owner is None or members is None or len(members) == 0:
64
- text = self.STR_GROUP_EMPTY
65
- return self._respond_text(text=text, group=group)
60
+ return self._respond_receipt(text='Group empty.', msg=msg, group=group, extra={
61
+ 'template': 'Group empty: ${ID}',
62
+ 'replacements': {
63
+ 'ID': str(group),
64
+ }
65
+ })
66
66
  # 1. check permission
67
67
  sender = msg.sender
68
68
  if sender != owner:
69
69
  # not the owner? check assistants
70
70
  assistants = facebook.assistants(identifier=group)
71
71
  if assistants is None or sender not in assistants:
72
- text = self.STR_EXPEL_NOT_ALLOWED
73
- return self._respond_text(text=text, group=group)
72
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
73
+ 'template': 'Not allowed to expel member from group: ${ID}',
74
+ 'replacements': {
75
+ 'ID': str(group),
76
+ }
77
+ })
74
78
  # 2. expelling members
75
79
  expel_list = self.members(content=content)
76
80
  if expel_list is None or len(expel_list) == 0:
77
- text = self.STR_EXPEL_CMD_ERROR
78
- return self._respond_text(text=text, group=group)
81
+ return self._respond_receipt(text='Command error.', msg=msg, group=group, extra={
82
+ 'template': 'Expel list is empty: ${ID}',
83
+ 'replacements': {
84
+ 'ID': str(group),
85
+ }
86
+ })
79
87
  # 2.1. check owner
80
88
  if owner in expel_list:
81
- text = self.STR_CANNOT_EXPEL_OWNER
82
- return self._respond_text(text=text, group=group)
89
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
90
+ 'template': 'Not allowed to expel owner of group: ${ID}',
91
+ 'replacements': {
92
+ 'ID': str(group),
93
+ }
94
+ })
83
95
  # 2.2. build removed-list
84
96
  remove_list = []
85
97
  for item in expel_list:
@@ -48,9 +48,6 @@ from .grp_reset import ResetCommandProcessor
48
48
 
49
49
  class InviteCommandProcessor(ResetCommandProcessor):
50
50
 
51
- STR_INVITE_CMD_ERROR = 'Invite command error.'
52
- STR_INVITE_NOT_ALLOWED = 'Sorry, you are not allowed to invite new members into this group.'
53
-
54
51
  # Override
55
52
  def process(self, content: Content, msg: ReliableMessage) -> List[Content]:
56
53
  assert isinstance(content, InviteCommand), 'invite command error: %s' % content
@@ -62,25 +59,33 @@ class InviteCommandProcessor(ResetCommandProcessor):
62
59
  if owner is None or members is None or len(members) == 0:
63
60
  # NOTICE: group membership lost?
64
61
  # reset group members
65
- return self._temporary_save(content=content, sender=msg.sender)
62
+ return self._temporary_save(content=content, sender=msg.sender, msg=msg)
66
63
  # 1. check permission
67
64
  sender = msg.sender
68
65
  if sender not in members:
69
66
  # not a member? check assistants
70
67
  assistants = facebook.assistants(identifier=group)
71
68
  if assistants is None or sender not in assistants:
72
- text = self.STR_INVITE_NOT_ALLOWED
73
- return self._respond_text(text=text, group=group)
69
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
70
+ 'template': 'Not allowed to invite member into group: ${ID}',
71
+ 'replacements': {
72
+ 'ID': str(group),
73
+ }
74
+ })
74
75
  # 2. inviting members
75
76
  invite_list = self.members(content=content)
76
77
  if invite_list is None or len(invite_list) == 0:
77
- text = self.STR_INVITE_CMD_ERROR
78
- return self._respond_text(text=text, group=group)
78
+ return self._respond_receipt(text='Command error.', msg=msg, group=group, extra={
79
+ 'template': 'Invite list is empty: ${ID}',
80
+ 'replacements': {
81
+ 'ID': str(group),
82
+ }
83
+ })
79
84
  # 2.1. check for reset
80
85
  if sender == owner and owner in invite_list:
81
86
  # NOTICE: owner invites owner?
82
87
  # it means this should be a 'reset' command
83
- return self._temporary_save(content=content, sender=sender)
88
+ return self._temporary_save(content=content, sender=sender, msg=msg)
84
89
  # 2.2. build invited-list
85
90
  add_list = []
86
91
  for item in invite_list:
@@ -50,8 +50,6 @@ from .history import GroupCommandProcessor
50
50
 
51
51
  class QueryCommandProcessor(GroupCommandProcessor):
52
52
 
53
- STR_QUERY_NOT_ALLOWED = 'Sorry, you are not allowed to query this group.'
54
-
55
53
  def _respond_group_members(self, owner: ID, group: ID, members: List[ID]) -> Content:
56
54
  facebook = self.facebook
57
55
  assert isinstance(facebook, CommonFacebook), 'facebook error: %s' % facebook
@@ -71,16 +69,24 @@ class QueryCommandProcessor(GroupCommandProcessor):
71
69
  members = facebook.members(identifier=group)
72
70
  # 0. check group
73
71
  if owner is None or members is None or len(members) == 0:
74
- text = self.STR_GROUP_EMPTY
75
- return self._respond_text(text=text, group=group)
72
+ return self._respond_receipt(text='Group empty.', msg=msg, group=group, extra={
73
+ 'template': 'Group empty: ${ID}',
74
+ 'replacements': {
75
+ 'ID': str(group),
76
+ }
77
+ })
76
78
  # 1. check permission
77
79
  sender = msg.sender
78
80
  if sender not in members:
79
81
  # not a member? check assistants
80
82
  assistants = facebook.assistants(identifier=group)
81
83
  if assistants is None or sender not in assistants:
82
- text = self.STR_QUERY_NOT_ALLOWED
83
- return self._respond_text(text=text, group=group)
84
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
85
+ 'template': 'Not allowed to query members of group: ${ID}',
86
+ 'replacements': {
87
+ 'ID': str(group),
88
+ }
89
+ })
84
90
  # 2. respond
85
91
  res = self._respond_group_members(owner=owner, group=group, members=members)
86
92
  return [] if res is None else [res]
@@ -39,6 +39,7 @@
39
39
 
40
40
  from typing import List
41
41
 
42
+ from dimp import ID
42
43
  from dimp import ReliableMessage
43
44
  from dimp import Content
44
45
  from dimp import QuitCommand
@@ -48,14 +49,16 @@ from .history import GroupCommandProcessor
48
49
 
49
50
  class QuitCommandProcessor(GroupCommandProcessor):
50
51
 
51
- STR_OWNER_CANNOT_QUIT = 'Sorry, owner cannot quit.'
52
- STR_ASSISTANT_CANNOT_QUIT = 'Sorry, assistant cannot quit.'
53
-
54
52
  # noinspection PyUnusedLocal
55
- def _remove_assistant(self, content: QuitCommand, msg: ReliableMessage) -> List[Content]:
53
+ def _remove_assistant(self, content: QuitCommand, sender: ID, msg: ReliableMessage) -> List[Content]:
56
54
  # NOTICE: group assistant should be retired by the owner
57
- text = self.STR_ASSISTANT_CANNOT_QUIT
58
- return self._respond_text(text=text, group=content.group)
55
+ group = content.group
56
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
57
+ 'template': 'Assistant cannot quit from group: ${ID}',
58
+ 'replacements': {
59
+ 'ID': str(group),
60
+ }
61
+ })
59
62
 
60
63
  # Override
61
64
  def process(self, content: Content, msg: ReliableMessage) -> List[Content]:
@@ -66,16 +69,24 @@ class QuitCommandProcessor(GroupCommandProcessor):
66
69
  members = facebook.members(identifier=group)
67
70
  # 0. check group
68
71
  if owner is None or members is None or len(members) == 0:
69
- text = self.STR_GROUP_EMPTY
70
- return self._respond_text(text=text, group=group)
72
+ return self._respond_receipt(text='Group empty.', msg=msg, group=group, extra={
73
+ 'template': 'Group empty: ${ID}',
74
+ 'replacements': {
75
+ 'ID': str(group),
76
+ }
77
+ })
71
78
  # 1. check permission
72
79
  sender = msg.sender
73
80
  if sender == owner:
74
- text = self.STR_OWNER_CANNOT_QUIT
75
- return self._respond_text(text=text, group=group)
81
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
82
+ 'template': 'Owner cannot quit from group: ${ID}',
83
+ 'replacements': {
84
+ 'ID': str(group),
85
+ }
86
+ })
76
87
  assistants = facebook.assistants(identifier=group)
77
88
  if assistants is not None and sender in assistants:
78
- return self._remove_assistant(content=content, msg=msg)
89
+ return self._remove_assistant(content=content, sender=sender, msg=msg)
79
90
  # 2. remove sender from group members
80
91
  if sender in members:
81
92
  members.remove(sender)
@@ -55,23 +55,24 @@ from .history import GroupCommandProcessor
55
55
 
56
56
  class ResetCommandProcessor(GroupCommandProcessor):
57
57
 
58
- STR_RESET_CMD_ERROR = 'Reset command error.'
59
- STR_RESET_NOT_ALLOWED = 'Sorry, you are not allowed to reset this group.'
60
-
61
58
  def _query_owner(self, owner: ID, group: ID):
62
59
  command = GroupCommand.query(group=group)
63
60
  messenger = self.messenger
64
61
  assert isinstance(messenger, CommonMessenger), 'messenger error: %s' % messenger
65
62
  messenger.send_content(sender=None, receiver=owner, content=command, priority=1)
66
63
 
67
- def _temporary_save(self, content: GroupCommand, sender: ID) -> List[Content]:
64
+ def _temporary_save(self, content: GroupCommand, sender: ID, msg: ReliableMessage) -> List[Content]:
68
65
  facebook = self.facebook
69
66
  group = content.group
70
67
  # check whether the owner contained in the new members
71
68
  new_members = self.members(content=content)
72
69
  if new_members is None or len(new_members) == 0:
73
- text = self.STR_RESET_CMD_ERROR
74
- return self._respond_text(text=text, group=group)
70
+ return self._respond_receipt(text='Command error.', msg=msg, group=group, extra={
71
+ 'template': 'New member list is empty: ${ID}',
72
+ 'replacements': {
73
+ 'ID': str(group),
74
+ }
75
+ })
75
76
  man = group_manager()
76
77
  for item in new_members:
77
78
  if facebook.meta(identifier=item) is None:
@@ -106,24 +107,36 @@ class ResetCommandProcessor(GroupCommandProcessor):
106
107
  if owner is None or members is None or len(members) == 0:
107
108
  # FIXME: group profile lost?
108
109
  # FIXME: how to avoid strangers impersonating group members?
109
- return self._temporary_save(content=content, sender=msg.sender)
110
+ return self._temporary_save(content=content, sender=msg.sender, msg=msg)
110
111
  # 1. check permission
111
112
  sender = msg.sender
112
113
  if sender != owner:
113
114
  # not the owner? check assistants
114
115
  assistants = facebook.assistants(identifier=group)
115
116
  if assistants is None or sender not in assistants:
116
- text = self.STR_RESET_NOT_ALLOWED
117
- return self._respond_text(text=text, group=group)
117
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
118
+ 'template': 'Not allowed to reset members of group: ${ID}',
119
+ 'replacements': {
120
+ 'ID': str(group),
121
+ }
122
+ })
118
123
  # 2. resetting members
119
124
  new_members = self.members(content=content)
120
125
  if new_members is None or len(new_members) == 0:
121
- text = self.STR_RESET_CMD_ERROR
122
- return self._respond_text(text=text, group=group)
126
+ return self._respond_receipt(text='Command error.', msg=msg, group=group, extra={
127
+ 'template': 'New member list is empty: ${ID}',
128
+ 'replacements': {
129
+ 'ID': str(group),
130
+ }
131
+ })
123
132
  # 2.1. check owner
124
133
  if owner not in new_members:
125
- text = self.STR_RESET_CMD_ERROR
126
- return self._respond_text(text=text, group=group)
134
+ return self._respond_receipt(text='Permission denied.', msg=msg, group=group, extra={
135
+ 'template': 'Owner not in the new member list of group: ${ID}',
136
+ 'replacements': {
137
+ 'ID': str(group),
138
+ }
139
+ })
127
140
  # 2.2. build expelled-list
128
141
  remove_list = []
129
142
  for item in members:
@@ -45,20 +45,19 @@ from dimsdk.cpu import BaseCommandProcessor
45
45
 
46
46
  class HistoryCommandProcessor(BaseCommandProcessor):
47
47
 
48
- FMT_HIS_CMD_NOT_SUPPORT = 'History command (name: %s) not support yet!'
49
-
50
48
  # Override
51
49
  def process(self, content: Content, msg: ReliableMessage) -> List[Content]:
52
50
  assert isinstance(content, Command), 'history command error: %s' % content
53
- text = self.FMT_HIS_CMD_NOT_SUPPORT % content.cmd
54
- return self._respond_text(text=text, group=content.group)
51
+ return self._respond_receipt(text='Command not support.', msg=msg, group=content.group, extra={
52
+ 'template': 'History command (name: ${command}) not support yet!',
53
+ 'replacements': {
54
+ 'command': content.cmd,
55
+ }
56
+ })
55
57
 
56
58
 
57
59
  class GroupCommandProcessor(HistoryCommandProcessor):
58
60
 
59
- FMT_GRP_CMD_NOT_SUPPORT = 'Group command (name: %s) not support yet!'
60
- STR_GROUP_EMPTY = 'Group empty.'
61
-
62
61
  @staticmethod
63
62
  def members(content: GroupCommand) -> List[ID]:
64
63
  # get from 'members'
@@ -75,5 +74,9 @@ class GroupCommandProcessor(HistoryCommandProcessor):
75
74
  # Override
76
75
  def process(self, content: Content, msg: ReliableMessage) -> List[Content]:
77
76
  assert isinstance(content, GroupCommand), 'group command error: %s' % content
78
- text = self.FMT_GRP_CMD_NOT_SUPPORT % content.cmd
79
- return self._respond_text(text=text, group=content.group)
77
+ return self._respond_receipt(text='Command not support.', msg=msg, group=content.group, extra={
78
+ 'template': 'Group command (name: ${command}) not support yet!',
79
+ 'replacements': {
80
+ 'command': content.cmd,
81
+ }
82
+ })
@@ -190,7 +190,7 @@ class ClientMessenger(CommonMessenger):
190
190
  responses = super().process_reliable_message(msg=msg)
191
191
  if len(responses) == 0 and self._needs_receipt(msg=msg):
192
192
  current_user = self.facebook.current_user
193
- res = ReceiptCommand.create(text='Message received', msg=msg)
193
+ res = ReceiptCommand.create(text='Message received.', msg=msg)
194
194
  env = Envelope.create(sender=current_user.identifier, receiver=msg.sender)
195
195
  i_msg = InstantMessage.create(head=env, body=res)
196
196
  s_msg = self.encrypt_message(msg=i_msg)
@@ -31,24 +31,22 @@
31
31
  import time
32
32
  from typing import List, Optional, Union
33
33
 
34
- from dimp import EntityType
35
- from dimp import SecureMessage, ReliableMessage
36
- from dimp import ContentType, Content, TextContent
37
- from dimp import GroupCommand
38
-
34
+ from dimsdk import EntityType
35
+ from dimsdk import SecureMessage, ReliableMessage
36
+ from dimsdk import ContentType, Content, TextContent
37
+ from dimsdk import GroupCommand
38
+ from dimsdk import ReceiptCommand
39
39
  from dimsdk import ContentProcessor, ContentProcessorCreator
40
40
  from dimsdk import MessageProcessor
41
-
42
- from dimsdk.cpu import BaseContentProcessor, BaseContentProcessorCreator
41
+ from dimsdk import BaseContentProcessor, BaseContentProcessorCreator
43
42
 
44
43
  from ..utils import Logging
45
- from ..common import HandshakeCommand, ReceiptCommand, LoginCommand
44
+ from ..common import HandshakeCommand, LoginCommand
46
45
  from ..common import CommonMessenger
47
46
 
48
47
  from .cpu import TextContentProcessor
49
48
  from .cpu import HandshakeCommandProcessor
50
49
  from .cpu import LoginCommandProcessor
51
- from .cpu import ReceiptCommandProcessor
52
50
  from .cpu import HistoryCommandProcessor, GroupCommandProcessor
53
51
  from .cpu import InviteCommandProcessor, ExpelCommandProcessor, QuitCommandProcessor
54
52
  from .cpu import ResetCommandProcessor, QueryCommandProcessor
@@ -121,7 +119,7 @@ class ClientContentProcessorCreator(BaseContentProcessorCreator):
121
119
  # Override
122
120
  def create_content_processor(self, msg_type: Union[int, ContentType]) -> Optional[ContentProcessor]:
123
121
  # text
124
- if msg_type == ContentType.TEXT:
122
+ if msg_type == ContentType.TEXT.value:
125
123
  return TextContentProcessor(facebook=self.facebook, messenger=self.messenger)
126
124
  # history
127
125
  if msg_type == ContentType.HISTORY.value:
@@ -140,9 +138,6 @@ class ClientContentProcessorCreator(BaseContentProcessorCreator):
140
138
  # login
141
139
  if cmd == LoginCommand.LOGIN:
142
140
  return LoginCommandProcessor(facebook=self.facebook, messenger=self.messenger)
143
- # receipt
144
- if cmd == ReceiptCommand.RECEIPT:
145
- return ReceiptCommandProcessor(facebook=self.facebook, messenger=self.messenger)
146
141
  # group commands
147
142
  if cmd == 'group':
148
143
  return GroupCommandProcessor(facebook=self.facebook, messenger=self.messenger)
@@ -44,7 +44,6 @@ __all__ = [
44
44
  # protocol
45
45
  #
46
46
  'HandshakeCommand', 'HandshakeState',
47
- 'ReceiptCommand',
48
47
  'LoginCommand',
49
48
  'ReportCommand',
50
49
  'AnsCommand',
@@ -111,6 +111,7 @@ class AddressNameServer(AddressNameService):
111
111
  count = 0
112
112
  self.__reserved['apns'] = False
113
113
  self.__reserved['master'] = False
114
+ self.__reserved['monitor'] = False
114
115
  self.__reserved['archivist'] = False
115
116
  self.__reserved['assistant'] = False
116
117
  # self.__reserved['station'] = False
@@ -125,6 +126,7 @@ class AddressNameServer(AddressNameService):
125
126
  # self.__reserved['station'] = True
126
127
  self.__reserved['assistant'] = True
127
128
  self.__reserved['archivist'] = True
129
+ self.__reserved['monitor'] = True
128
130
  self.__reserved['master'] = True
129
131
  self.__reserved['apns'] = True
130
132
  return count
@@ -29,7 +29,6 @@ from dimsdk import register_all_factories as register_core_factories
29
29
  from dimplugins import register_plugins
30
30
 
31
31
  from .handshake import HandshakeCommand, HandshakeState
32
- from .receipt import ReceiptCommand
33
32
  from .login import LoginCommand
34
33
  from .report import ReportCommand
35
34
  from .ans import AnsCommand
@@ -41,8 +40,6 @@ def register_all_factories():
41
40
 
42
41
  # Handshake
43
42
  Command.register(cmd=HandshakeCommand.HANDSHAKE, factory=CommandFactoryBuilder(command_class=HandshakeCommand))
44
- # Receipt
45
- Command.register(cmd=ReceiptCommand.RECEIPT, factory=CommandFactoryBuilder(command_class=ReceiptCommand))
46
43
  # Login
47
44
  Command.register(cmd=LoginCommand.LOGIN, factory=CommandFactoryBuilder(command_class=LoginCommand))
48
45
  # Report
@@ -58,7 +55,6 @@ register_plugins()
58
55
  __all__ = [
59
56
 
60
57
  'HandshakeCommand', 'HandshakeState',
61
- 'ReceiptCommand',
62
58
  'LoginCommand',
63
59
  'ReportCommand',
64
60
  'AnsCommand',
@@ -99,12 +99,14 @@ class AccountDatabase(AccountDBI):
99
99
 
100
100
  # Override
101
101
  def save_document(self, document: Document) -> bool:
102
- # check with exists
102
+ # check meta first
103
103
  meta = self.__meta_table.meta(identifier=document.identifier)
104
104
  if meta is None:
105
105
  raise LookupError('meta not exists: %s' % document.identifier)
106
+ # check document valid before saving it
106
107
  if not (document.valid or document.verify(public_key=meta.key)):
107
108
  raise ValueError('document error: %s' % document.identifier)
109
+ # document ok, try to save it
108
110
  return self.__doc_table.save_document(document=document)
109
111
 
110
112
  # Override
@@ -25,6 +25,7 @@
25
25
 
26
26
  import getopt
27
27
  import sys
28
+ import time
28
29
  from typing import Optional, Tuple
29
30
 
30
31
  from dimsdk import ID, Station
@@ -131,7 +132,16 @@ def create_facebook(database: AccountDBI, current_user: ID) -> CommonFacebook:
131
132
  assert sign_key is not None, 'failed to get sign key for current user: %s' % current_user
132
133
  assert msg_keys is not None and len(msg_keys) > 0, 'failed to get msg keys: %s' % current_user
133
134
  print('set current user: %s' % current_user)
134
- facebook.current_user = facebook.user(identifier=current_user)
135
+ user = facebook.user(identifier=current_user)
136
+ assert user is not None, 'failed to get current user: %s' % current_user
137
+ visa = user.visa
138
+ if visa is not None:
139
+ # refresh visa
140
+ now = time.time()
141
+ visa.set_property(key='time', value=now)
142
+ visa.sign(private_key=sign_key)
143
+ facebook.save_document(document=visa)
144
+ facebook.current_user = user
135
145
  return facebook
136
146
 
137
147
 
@@ -58,7 +58,7 @@ __all__ = [
58
58
  # CPU
59
59
  #
60
60
  'HandshakeCommandProcessor', 'LoginCommandProcessor', 'ReportCommandProcessor',
61
- 'AnsCommandProcessor', 'DocumentCommandProcessor', 'ReceiptCommandProcessor',
61
+ 'AnsCommandProcessor', 'DocumentCommandProcessor',
62
62
 
63
63
  # Session
64
64
  'ServerSession', 'SessionCenter', # 'SessionPool',
@@ -37,10 +37,9 @@ from .ans import AnsCommandProcessor
37
37
 
38
38
  from .document import DocumentCommandProcessor
39
39
 
40
- from .receipt import ReceiptCommandProcessor
41
-
42
40
 
43
41
  __all__ = [
42
+
44
43
  'HandshakeCommandProcessor',
45
44
  'LoginCommandProcessor',
46
45
  'ReportCommandProcessor',
@@ -48,5 +47,4 @@ __all__ = [
48
47
 
49
48
  'DocumentCommandProcessor',
50
49
 
51
- 'ReceiptCommandProcessor',
52
50
  ]
@@ -48,9 +48,8 @@ class AnsCommandProcessor(BaseCommandProcessor):
48
48
  def process(self, content: Content, msg: ReliableMessage) -> List[Content]:
49
49
  assert isinstance(content, AnsCommand), 'report command error: %s' % content
50
50
  names = content.names
51
- if names is None or len(names) == 0:
52
- text = 'ANS command error'
53
- return self._respond_text(text=text)
51
+ if len(names) == 0:
52
+ return self._respond_receipt(text='ANS command error.', msg=msg)
54
53
  records = {}
55
54
  missed = []
56
55
  for item in names:
@@ -54,8 +54,12 @@ class HandshakeCommandProcessor(BaseCommandProcessor):
54
54
  title = content.title
55
55
  if title in ['DIM?', 'DIM!']:
56
56
  # S -> C
57
- text = 'Handshake command error: %s' % title
58
- return self._respond_text(text=text)
57
+ return self._respond_receipt(text='Command not support.', msg=msg, extra={
58
+ 'template': 'Handshake command error: title="${title}".',
59
+ 'replacements': {
60
+ 'title': title,
61
+ }
62
+ })
59
63
  # C -> S: Hello world!
60
64
  assert 'Hello world!' == title, 'Handshake command error: %s' % content
61
65
  # set/update session in session server with new session key
@@ -86,7 +86,12 @@ class LoginCommandProcessor(BaseCommandProcessor, Logging):
86
86
  session.set_active(active=True)
87
87
  # only respond the user login to this station
88
88
  self.info(msg='user login: %s -> %s' % (sender, roaming))
89
- return self._respond_text(text='Login received.')
89
+ return self._respond_receipt(text='Login received.', msg=msg, extra={
90
+ 'template': 'Login command received: ${ID}.',
91
+ 'replacements': {
92
+ 'ID': str(sender),
93
+ }
94
+ })
90
95
 
91
96
 
92
97
  def add_roaming(user: ID, station: ID):
@@ -65,13 +65,21 @@ class ReportCommandProcessor(BaseCommandProcessor, Logging):
65
65
  if title == ReportCommand.ONLINE:
66
66
  # online
67
67
  session.set_active(active=True, when=content.time)
68
- text = 'Online command received.'
69
- return self._respond_text(text=text)
68
+ return self._respond_receipt(text='Online received.', msg=msg, extra={
69
+ 'template': 'Online command received: ${ID}.',
70
+ 'replacements': {
71
+ 'ID': str(sender),
72
+ }
73
+ })
70
74
  elif title == ReportCommand.OFFLINE:
71
75
  # offline
72
76
  session.set_active(active=False, when=content.time)
73
- text = 'Offline command received.'
74
- return self._respond_text(text=text)
77
+ # respond nothing when user offline
78
+ return []
75
79
  else:
76
- text = 'Report command (title: %s) not support yet!' % title
77
- return self._respond_text(text=text)
80
+ return self._respond_receipt(text='Command not support.', msg=msg, extra={
81
+ 'template': 'Report command (title: ${title}) not support yet!',
82
+ 'replacements': {
83
+ 'title': title,
84
+ }
85
+ })