comparison src/plugins/plugin_xep_0085.py @ 2144:1d3f73e065e1

core, jp: component handling + client handling refactoring: - SàT can now handle components - plugin have now a "modes" key in PLUGIN_INFO where they declare if they can be used with clients and or components. They default to be client only. - components are really similar to clients, but with some changes in behaviour: * component has "entry point", which is a special plugin with a componentStart method, which is called just after component is connected * trigger end with a different suffixes (e.g. profileConnected vs profileConnectedComponent), so a plugin which manage both clients and components can have different workflow * for clients, only triggers of plugins handling client mode are launched * for components, only triggers of plugins needed in dependencies are launched. They all must handle component mode. * component have a sendHistory attribute (False by default) which can be set to True to allow saving sent messages into history * for convenience, "client" is still used in method even if it can now be a component * a new "component" boolean attribute tells if we have a component or a client * components have to add themselve Message protocol * roster and presence protocols are not added for components * component default port is 5347 (which is Prosody's default port) - asyncCreateProfile has been renamed for profileCreate, both to follow new naming convention and to prepare the transition to fully asynchronous bridge - createProfile has a new "component" attribute. When used to create a component, it must be set to a component entry point - jp: added --component argument to profile/create - disconnect bridge method is now asynchronous, this way frontends can know when disconnection is finished - new PI_* constants for PLUGIN_INFO values (not used everywhere yet) - client/component connection workflow has been moved to their classes instead of being a host methods - host.messageSend is now client.sendMessage, and former client.sendMessage is now client.sendMessageData. - identities are now handled in client.identities list, so it can be updated dynamically by plugins (in the future, frontends should be able to update them too through bridge) - profileConnecting* profileConnected* profileDisconnected* and getHandler now all use client instead of profile
author Goffi <goffi@goffi.org>
date Sun, 12 Feb 2017 17:55:43 +0100
parents 6a66c8c5a567
children 33c8c4973743
comparison
equal deleted inserted replaced
2143:c3cac21157d4 2144:1d3f73e065e1
101 # parameter value is retrieved before each use 101 # parameter value is retrieved before each use
102 host.memory.updateParams(self.params) 102 host.memory.updateParams(self.params)
103 103
104 # triggers from core 104 # triggers from core
105 host.trigger.add("MessageReceived", self.messageReceivedTrigger) 105 host.trigger.add("MessageReceived", self.messageReceivedTrigger)
106 host.trigger.add("messageSend", self.messageSendTrigger) 106 host.trigger.add("sendMessage", self.sendMessageTrigger)
107 host.trigger.add("paramUpdateTrigger", self.paramUpdateTrigger) 107 host.trigger.add("paramUpdateTrigger", self.paramUpdateTrigger)
108 108
109 # args: to_s (jid as string), profile 109 # args: to_s (jid as string), profile
110 host.bridge.addMethod("chatStateComposing", ".plugin", in_sign='ss', 110 host.bridge.addMethod("chatStateComposing", ".plugin", in_sign='ss',
111 out_sign='', method=self.chatStateComposing) 111 out_sign='', method=self.chatStateComposing)
112 112
113 # args: from (jid as string), state in CHAT_STATES, profile 113 # args: from (jid as string), state in CHAT_STATES, profile
114 host.bridge.addSignal("chatStateReceived", ".plugin", signature='sss') 114 host.bridge.addSignal("chatStateReceived", ".plugin", signature='sss')
115 115
116 def getHandler(self, profile): 116 def getHandler(self, client):
117 return XEP_0085_handler(self, profile) 117 return XEP_0085_handler(self, client.profile)
118 118
119 def profileDisconnected(self, profile): 119 def profileDisconnected(self, client):
120 """Eventually send a 'gone' state to all one2one contacts.""" 120 """Eventually send a 'gone' state to all one2one contacts."""
121 profile = client.profile
121 if profile not in self.map: 122 if profile not in self.map:
122 return 123 return
123 for to_jid in self.map[profile]: 124 for to_jid in self.map[profile]:
124 # FIXME: the "unavailable" presence stanza is received by to_jid 125 # FIXME: the "unavailable" presence stanza is received by to_jid
125 # before the chat state, so it will be ignored... find a way to 126 # before the chat state, so it will be ignored... find a way to
196 if state != 'gone' or message.getAttribute('type') != 'groupchat': 197 if state != 'gone' or message.getAttribute('type') != 'groupchat':
197 self.host.bridge.chatStateReceived(message.getAttribute("from"), state, profile) 198 self.host.bridge.chatStateReceived(message.getAttribute("from"), state, profile)
198 break 199 break
199 return True 200 return True
200 201
201 def messageSendTrigger(self, client, mess_data, pre_xml_treatments, post_xml_treatments): 202 def sendMessageTrigger(self, client, mess_data, pre_xml_treatments, post_xml_treatments):
202 """ 203 """
203 Eventually add the chat state to the message and initiate 204 Eventually add the chat state to the message and initiate
204 the state machine when sending an "active" state. 205 the state machine when sending an "active" state.
205 """ 206 """
206 profile = client.profile 207 profile = client.profile
369 'message': {}, 370 'message': {},
370 'type': self.mess_type, 371 'type': self.mess_type,
371 'subject': {}, 372 'subject': {},
372 'extra': {}, 373 'extra': {},
373 } 374 }
374 self.host.generateMessageXML(mess_data) 375 client.generateMessageXML(mess_data)
375 mess_data['xml'].addElement(state, NS_CHAT_STATES) 376 mess_data['xml'].addElement(state, NS_CHAT_STATES)
376 client.send(mess_data['xml']) 377 client.send(mess_data['xml'])
377 378
378 self.state = state 379 self.state = state
379 try: 380 try: