@property def messenger(self) -> ServerMessenger: return super().messenger @messenger.setter def messenger(self, transceiver: ServerMessenger): CommandProcessor.messenger.__set__(self, transceiver) @property def session_server(self) -> SessionServer: return self.messenger.session_server def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance(cmd, Command), 'command error: %s' % cmd facebook = self.facebook users = self.session_server.random_users() results = {} for item in users: meta = facebook.meta(identifier=item) if isinstance(meta, Meta): results[str(item)] = meta.dictionary return SearchCommand(users=list(users), results=results) # register spu = SearchCommandProcessor() CommandProcessor.register(command=SearchCommand.SEARCH, cpu=SearchCommandProcessor()) CommandProcessor.register(command=SearchCommand.ONLINE_USERS, cpu=UsersCommandProcessor())
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ login protocol """ from typing import Optional from dimp import ID from dimp import InstantMessage from dimp import Content from dimp import Command from dimsdk import ReceiptCommand from dimsdk import CommandProcessor class LoginCommandProcessor(CommandProcessor): # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Optional[Content]: assert isinstance(content, Command), 'command error: %s' % content # TODO: update login status return ReceiptCommand.new(message='Login received') # register CommandProcessor.register(command='login', processor_class=LoginCommandProcessor)
def __put(self, cmd: Command, sender: ID) -> Content: # receive encrypted contacts, save it if self.database.save_contacts_command(cmd=cmd, sender=sender): self.info('contacts command saved for %s' % sender) return ReceiptCommand.new(message='Contacts of %s received!' % sender) else: self.error('failed to save contacts command: %s' % cmd) return TextContent.new(text='Contacts not stored %s!' % cmd) # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Content: if type(self) != ContactsCommandProcessor: raise AssertionError('override me!') assert isinstance(content, Command), 'command error: %s' % content if 'data' in content or 'contacts' in content: # upload contacts, save it return self.__put(cmd=content, sender=sender) else: # query contacts, load it return self.__get(sender=sender) # register CommandProcessor.register(command='contacts', processor_class=ContactsCommandProcessor)
return stored else: # return TextContent.new(text='Sorry, block-list of %s not found.' % sender) # TODO: here should response an empty HistoryCommand: 'block' res = Command.new(command='block') res['list'] = [] return res def __put(self, cmd: BlockCommand, sender: ID) -> Content: # receive block command, save it if self.database.save_block_command(cmd=cmd, sender=sender): return ReceiptCommand.new(message='Block command of %s received!' % sender) else: return TextContent.new(text='Sorry, block-list not stored: %s!' % cmd) # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Content: assert isinstance(content, BlockCommand), 'block command error: %s' % content if 'list' in content: # upload block-list, save it return self.__put(cmd=content, sender=sender) else: # query block-list, load it return self.__get(sender=sender) # register CommandProcessor.register(command='block', processor_class=BlockCommandProcessor)
assert isinstance(content, Command), 'command error: %s' % content # welcome back! self.receptionist.add_guest(identifier=sender) session = self.messenger.current_session(identifier=sender) if isinstance(session, Session): session.active = True return ReceiptCommand.new(message='Client online received') class OfflineCommandProcessor(ReportCommandProcessor): # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Optional[Content]: assert isinstance(content, Command), 'command error: %s' % content # goodbye! session = self.messenger.current_session(identifier=sender) if isinstance(session, Session): session.active = False return ReceiptCommand.new(message='Client offline received') # register CommandProcessor.register(command='report', processor_class=ReportCommandProcessor) CommandProcessor.register(command='broadcast', processor_class=ReportCommandProcessor) CommandProcessor.register(command='apns', processor_class=APNsCommandProcessor) CommandProcessor.register(command='online', processor_class=OnlineCommandProcessor) CommandProcessor.register(command='offline', processor_class=OfflineCommandProcessor)
from dimsdk import CommandProcessor, GroupCommandProcessor class QueryCommandProcessor(GroupCommandProcessor): def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance(cmd, QueryCommand), 'group command error: %s' % cmd facebook = self.facebook group: ID = cmd.group # 1. check permission if not facebook.exists_member(member=msg.sender, group=group): if not facebook.exists_assistant(member=msg.sender, group=group): raise AssertionError('only member/assistant can query: %s, %s' % (group, msg.sender)) # 2. get group members members = facebook.members(identifier=group) if members is None or len(members) == 0: text = 'Group members not found: %s' % group return TextContent(text=text) # 3. response group members for sender user = facebook.current_user assert user is not None, 'current user not set' if facebook.is_owner(member=user.identifier, group=group): return GroupCommand.reset(group=group, members=members) else: return GroupCommand.invite(group=group, members=members) # register CommandProcessor.register(command=GroupCommand.QUERY, cpu=QueryCommandProcessor())
session.active = True # post notification post_notification(session=session, sender=self) # TODO: notification for pushing offline message(s) from 'last_time' return ReceiptCommand(message='Client online received') class OfflineCommandProcessor(ReportCommandProcessor): def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance( cmd, ReportCommand), 'offline report command error: %s' % cmd # goodbye! session = self.messenger.current_session(identifier=msg.sender) if isinstance(session, Session): session.active = False # post notification post_notification(session=session, sender=self) return ReceiptCommand(message='Client offline received') # register rpu = ReportCommandProcessor() CommandProcessor.register(command=ReportCommand.REPORT, cpu=rpu) CommandProcessor.register(command='broadcast', cpu=rpu) CommandProcessor.register(command='apns', cpu=APNsCommandProcessor()) CommandProcessor.register(command=ReportCommand.ONLINE, cpu=OnlineCommandProcessor()) CommandProcessor.register(command=ReportCommand.OFFLINE, cpu=OfflineCommandProcessor())
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Handshake Protocol """ from typing import Optional from dimp import ReliableMessage from dimp import Content from dimp import Command from dimsdk import HandshakeCommand from dimsdk import CommandProcessor class HandshakeCommandProcessor(CommandProcessor): def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance(cmd, HandshakeCommand), 'command error: %s' % cmd message = cmd.message if 'DIM?' == message: # station ask client to handshake again return HandshakeCommand.restart(session=cmd.session) elif 'DIM!' == message: # handshake accepted by station server = self.messenger.server server.handshake_success() # register CommandProcessor.register(command=Command.HANDSHAKE, cpu=HandshakeCommandProcessor())
@staticmethod def __ask(session_key: str) -> Content: # station ask client to handshake again return HandshakeCommand.restart(session=session_key) def __success(self) -> Optional[Content]: # handshake accepted by station return self.delegate.handshake_success() # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Content: if type(self) != HandshakeCommandProcessor: raise AssertionError('override me!') assert isinstance(content, HandshakeCommand), 'command error: %s' % content message = content.message if 'DIM!' == message: # S -> C return self.__success() elif 'DIM?' == message: # S -> C return self.__ask(session_key=content.session) else: # C -> S: Hello world! return self.__offer(session_key=content.session, sender=sender) # register CommandProcessor.register(command=Command.HANDSHAKE, processor_class=HandshakeCommandProcessor)
if stored is not None: # response the stored mute command directly return stored else: # return TextContent.new(text='Sorry, mute-list of %s not found.' % sender) # TODO: here should response an empty HistoryCommand: 'mute' res = Command(command=MuteCommand.MUTE) res['list'] = [] return res def __put(self, cmd: MuteCommand, sender: ID) -> Content: # receive mute command, save it if self.database.save_mute_command(cmd=cmd, sender=sender): return ReceiptCommand(message='Mute command of %s received!' % sender) else: return TextContent(text='Sorry, mute-list not stored %s!' % cmd) def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance(cmd, MuteCommand), 'command error: %s' % cmd if 'list' in cmd: # upload mute-list, save it return self.__put(cmd=cmd, sender=msg.sender) else: # query mute-list, load it return self.__get(sender=msg.sender) # register CommandProcessor.register(command=MuteCommand.MUTE, cpu=MuteCommandProcessor())
assert isinstance(cmd, LoginCommand), 'command error: %s' % cmd sender = msg.sender # check roaming sid = self.__roaming(cmd=cmd, sender=sender) if sid is not None: self.info('%s is roamer to: %s' % (sender, sid)) octopus.roaming(roamer=sender, station=sid) # update login info if not self.database.save_login(cmd=cmd, msg=msg): return None # respond nothing return None # register CommandProcessor.register(command=Command.LOGIN, cpu=LoginCommandProcessor()) class InnerMessenger(ClientMessenger): """ Messenger for processing message from local station """ def __init__(self): super().__init__() self.accepted = False # Override def process_reliable_message( self, msg: ReliableMessage) -> Optional[ReliableMessage]: if self.accepted: return octopus.departure(msg=msg) else: return super().process_reliable_message(msg=msg)
from dimsdk import CommandProcessor from ..utils import Log class ReceiptCommandProcessor(CommandProcessor): def __init__(self, messenger): super().__init__(messenger=messenger) def info(self, msg: str): Log.info('%s >\t%s' % (self.__class__.__name__, msg)) def error(self, msg: str): Log.error('%s >\t%s' % (self.__class__.__name__, msg)) # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Optional[Content]: assert isinstance(content, ReceiptCommand), 'text content error: %s' % content nickname = self.facebook.nickname(identifier=sender) self.info('Received receipt message from %s: %s' % (nickname, content)) return None # register CommandProcessor.register(command=Command.RECEIPT, processor_class=ReceiptCommandProcessor)
def __process_contacts(self, cmd: StorageCommand, sender: ID) -> Content: if cmd.data is None and 'contacts' not in cmd: # query contacts, load it return self.__get_contacts(sender=sender) else: # upload contacts, save it return self.__put_contacts(cmd=cmd, sender=sender) # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Content: assert isinstance(content, StorageCommand), 'command error: %s' % content title = content.title if title == StorageCommand.CONTACTS: return self.__process_contacts(cmd=content, sender=sender) # error return TextContent.new( text='Storage command (title: %s) not support yet!' % title) # register CommandProcessor.register(command=StorageCommand.STORAGE, processor_class=StorageCommandProcessor) CommandProcessor.register(command=StorageCommand.CONTACTS, processor_class=StorageCommandProcessor) CommandProcessor.register(command=StorageCommand.PRIVATE_KEY, processor_class=StorageCommandProcessor)
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # ============================================================================== """ Receipt Command Processor ~~~~~~~~~~~~~~~~~~~~~~~~~ """ from typing import Optional from dimp import ReliableMessage from dimp import Content, Command from dimsdk import ReceiptCommand from dimsdk import CommandProcessor class ReceiptCommandProcessor(CommandProcessor): def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance(cmd, ReceiptCommand), 'receipt command error: %s' % cmd # nickname = self.facebook.name(identifier=sender) return None # register CommandProcessor.register(command=Command.RECEIPT, cpu=ReceiptCommandProcessor())
# results results = content.get('results') if results is not None: print(' results:', json.dumps(results)) return None class UsersCommandProcessor(CommandProcessor): # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Optional[Content]: assert isinstance(content, Command), 'command error: %s' % content # message message = content.get('message') print('online users response: %s' % message) # users users = content.get('users') if users is not None: print(' users:', json.dumps(users)) return None # register CommandProcessor.register(command='search', processor_class=SearchCommandProcessor) CommandProcessor.register(command='users', processor_class=UsersCommandProcessor)
# response the stored block command directly return stored else: # return TextContent.new(text='Sorry, block-list of %s not found.' % sender) # TODO: here should response an empty HistoryCommand: 'block' res = Command(command=BlockCommand.BLOCK) res['list'] = [] return res def __put(self, cmd: BlockCommand, sender: ID) -> Content: # receive block command, save it if self.database.save_block_command(cmd=cmd, sender=sender): return ReceiptCommand(message='Block command of %s received!' % sender) else: return TextContent(text='Sorry, block-list not stored: %s!' % cmd) def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance(cmd, BlockCommand), 'block command error: %s' % cmd if 'list' in cmd: # upload block-list, save it return self.__put(cmd=cmd, sender=msg.sender) else: # query block-list, load it return self.__get(sender=msg.sender) # register CommandProcessor.register(command=BlockCommand.BLOCK, cpu=BlockCommandProcessor())
def __put_contacts(self, cmd: StorageCommand, sender: ID) -> Content: # receive encrypted contacts, save it if self.database.save_contacts_command(cmd=cmd, sender=sender): return ReceiptCommand(message='Contacts of %s received!' % sender) else: return TextContent(text='Contacts not stored %s!' % cmd) def __process_contacts(self, cmd: StorageCommand, sender: ID) -> Content: if cmd.data is None and 'contacts' not in cmd: # query contacts, load it return self.__get_contacts(sender=sender) else: # upload contacts, save it return self.__put_contacts(cmd=cmd, sender=sender) def execute(self, cmd: Command, msg: ReliableMessage) -> Optional[Content]: assert isinstance(cmd, StorageCommand), 'command error: %s' % cmd title = cmd.title if title == StorageCommand.CONTACTS: return self.__process_contacts(cmd=cmd, sender=msg.sender) # error return TextContent(text='Storage command (title: %s) not support yet!' % title) # register spu = StorageCommandProcessor() CommandProcessor.register(command=StorageCommand.STORAGE, cpu=spu) CommandProcessor.register(command=StorageCommand.CONTACTS, cpu=spu) CommandProcessor.register(command=StorageCommand.PRIVATE_KEY, cpu=spu)
return res def __put(self, cmd: Command, sender: ID) -> Content: # receive mute command, save it if self.database.save_mute_command(cmd=cmd, sender=sender): self.info('mute command saved for %s' % sender) return ReceiptCommand.new(message='Mute command of %s received!' % sender) else: self.error('failed to save mute command: %s' % cmd) return TextContent.new(text='Mute-list not stored %s!' % cmd) # # main # def process(self, content: Content, sender: ID, msg: InstantMessage) -> Content: if type(self) != MuteCommandProcessor: raise AssertionError('override me!') assert isinstance(content, Command), 'command error: %s' % content if 'list' in content: # upload mute-list, save it return self.__put(cmd=content, sender=sender) else: # query mute-list, load it return self.__get(sender=sender) # register CommandProcessor.register(command='mute', processor_class=MuteCommandProcessor)