Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0277.py @ 1421:16b1ba7ccaaa
plugins xep-0277: some methods reordering to make the plugin more readable
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 23 Apr 2015 10:25:47 +0200 |
parents | be2df1ddea8e |
children | e8c8e467964b |
comparison
equal
deleted
inserted
replaced
1420:7c0acb966fd6 | 1421:16b1ba7ccaaa |
---|---|
73 host.bridge.addMethod("setMicroblogAccess", ".plugin", in_sign='ss', out_sign='', | 73 host.bridge.addMethod("setMicroblogAccess", ".plugin", in_sign='ss', out_sign='', |
74 method=self.setMicroblogAccess, | 74 method=self.setMicroblogAccess, |
75 async=True, | 75 async=True, |
76 doc={}) | 76 doc={}) |
77 | 77 |
78 def parseCommentUrl(self, node_url): | 78 ## plugin management methods ## |
79 """Determine the fields comments_service and comments_node of a microblog data | 79 |
80 from the href attribute of an entry's link element. For example this input: | 80 def microblogCB(self, itemsEvent, profile): |
81 xmpp:sat-pubsub.libervia.org?node=urn%3Axmpp%3Acomments%3A_c5c4a142-2279-4b2a-ba4c-1bc33aa87634__urn%3Axmpp%3Agroupblog%3Asouliane%40libervia.org | 81 """Callback to "MICROBLOG" PEP event.""" |
82 will return (JID(u'sat-pubsub.libervia.org'), 'urn:xmpp:comments:_c5c4a142-2279-4b2a-ba4c-1bc33aa87634__urn:xmpp:groupblog:souliane@libervia.org') | 82 def manageItem(microblog_data): |
83 @return: a tuple (JID, str) | 83 self.host.bridge.personalEvent(itemsEvent.sender.full(), "MICROBLOG", microblog_data, profile) |
84 """ | 84 |
85 parsed_url = urlparse.urlparse(node_url, 'xmpp') | 85 for item in itemsEvent.items: |
86 service = jid.JID(parsed_url.path) | 86 self.item2mbdata(item).addCallbacks(manageItem, lambda failure: None) |
87 queries = parsed_url.query.split(';') | 87 |
88 parsed_queries = dict() | 88 ## data/item transformation ## |
89 for query in queries: | 89 |
90 parsed_queries.update(urlparse.parse_qs(query)) | 90 def _getDomishInnerContent(self, elt): |
91 node = parsed_queries.get('node', [''])[0] | 91 """Return the inner content of a domish.Element.""" |
92 | 92 result = '' |
93 if not node: | 93 for child in elt.children: |
94 raise exceptions.DataError('Invalid comments link') | 94 try: |
95 | 95 result += child.toXml() # child id a domish.Element |
96 return (service, node) | 96 except AttributeError: |
97 result += child # child is unicode | |
98 return result | |
97 | 99 |
98 def _removeXHTMLMarkups(self, xhtml): | 100 def _removeXHTMLMarkups(self, xhtml): |
99 """Remove XHTML markups from the given string. | 101 """Remove XHTML markups from the given string. |
100 | 102 |
101 @param xhtml: the XHTML string to be cleaned | 103 @param xhtml: the XHTML string to be cleaned |
107 False) | 109 False) |
108 | 110 |
109 @defer.inlineCallbacks | 111 @defer.inlineCallbacks |
110 def item2mbdata(self, item): | 112 def item2mbdata(self, item): |
111 """Convert an XML Item to microblog data used in bridge API | 113 """Convert an XML Item to microblog data used in bridge API |
114 | |
112 @param item: domish.Element of microblog item | 115 @param item: domish.Element of microblog item |
113 @return: microblog data (dictionary)""" | 116 @return: microblog data (dictionary) |
117 """ | |
114 | 118 |
115 def xpath(elt, path): | 119 def xpath(elt, path): |
116 """Return the XPATH result of an entry element or its descendance.""" | 120 """Return the XPATH result of an entry element or its descendance.""" |
117 # XXX: use a wildcard to work with all and even undefined namespaces | 121 # XXX: use a wildcard to work with all and even undefined namespaces |
118 return elt.xpath('/'.join(["*[local-name() = '%s']" % tag for tag in path.split('/')])) | 122 return elt.xpath('/'.join(["*[local-name() = '%s']" % tag for tag in path.split('/')])) |
140 | 144 |
141 microblog_data = {} | 145 microblog_data = {} |
142 | 146 |
143 for key in ['title', 'content']: # process the textual elements | 147 for key in ['title', 'content']: # process the textual elements |
144 for attr_elt in xpath(entry_elt, key): | 148 for attr_elt in xpath(entry_elt, key): |
145 attr_content = self._getLXMLInnerContent(attr_elt) | 149 # Return the inner content of a lxml.etree.Element. It is not |
150 # trivial because the lxml tostring method would return the full | |
151 # content including elt's tag and attributes, and elt.getchildren() | |
152 # would skip a text value which is not within an element... | |
153 attr_content = self._getDomishInnerContent(ElementParser()(etree.tostring(attr_elt))) | |
146 if not attr_content.strip(): | 154 if not attr_content.strip(): |
147 continue # element with empty value | 155 continue # element with empty value |
148 content_type = attr_elt.get('type', 'text').lower() | 156 content_type = attr_elt.get('type', 'text').lower() |
149 if content_type == 'xhtml': | 157 if content_type == 'xhtml': |
150 text = self._decapsulateExtraNS(attr_content) | 158 # Check for XHTML namespace and decapsulate the content so the user |
159 # who wants to modify an entry will see the text that he entered. Also | |
160 # this avoids successive encapsulation with a new <div>...</div> at | |
161 # each modification (encapsulation is done in self.data2entry) | |
162 elt = ElementParser()(attr_content) | |
163 if elt.uri != NS_XHTML: | |
164 raise exceptions.DataError(_('Content of type XHTML must declare its namespace!')) | |
165 text = self._getDomishInnerContent(elt) | |
151 microblog_data['%s_xhtml' % key] = yield self.host.plugins["TEXT-SYNTAXES"].clean_xhtml(text) | 166 microblog_data['%s_xhtml' % key] = yield self.host.plugins["TEXT-SYNTAXES"].clean_xhtml(text) |
152 else: | 167 else: |
153 microblog_data[key] = attr_content | 168 microblog_data[key] = attr_content |
154 if key not in microblog_data and ('%s_xhtml' % key) in microblog_data: | 169 if key not in microblog_data and ('%s_xhtml' % key) in microblog_data: |
155 microblog_data[key] = yield self._removeXHTMLMarkups(microblog_data['%s_xhtml' % key]) | 170 microblog_data[key] = yield self._removeXHTMLMarkups(microblog_data['%s_xhtml' % key]) |
195 microblog_data['author'] = xpath(entry_elt, 'author/nick')[0].text | 210 microblog_data['author'] = xpath(entry_elt, 'author/nick')[0].text |
196 except IndexError: | 211 except IndexError: |
197 log.warning(_(u"Can't find author element in atom entry %s") % microblog_data['id']) | 212 log.warning(_(u"Can't find author element in atom entry %s") % microblog_data['id']) |
198 | 213 |
199 defer.returnValue(microblog_data) | 214 defer.returnValue(microblog_data) |
200 | |
201 def _getLXMLInnerContent(self, elt): | |
202 """Return the inner content of a lxml.etree.Element. It is not | |
203 trivial because the lxml tostring method would return the full | |
204 content including elt's tag and attributes, and elt.getchildren() | |
205 would skip a text value which is not within an element...""" | |
206 return self._getDomishInnerContent(ElementParser()(etree.tostring(elt))) | |
207 | |
208 def _getDomishInnerContent(self, elt): | |
209 """Return the inner content of a domish.Element.""" | |
210 result = '' | |
211 for child in elt.children: | |
212 try: | |
213 result += child.toXml() # child id a domish.Element | |
214 except AttributeError: | |
215 result += child # child is unicode | |
216 return result | |
217 | |
218 def _decapsulateExtraNS(self, text): | |
219 """Check for XHTML namespace and decapsulate the content so the user | |
220 who wants to modify an entry will see the text that he entered. Also | |
221 this avoids successive encapsulation with a new <div>...</div> at | |
222 each modification (encapsulation is done in self.data2entry)""" | |
223 elt = ElementParser()(text) | |
224 if elt.uri != NS_XHTML: | |
225 raise exceptions.DataError(_('Content of type XHTML must declare its namespace!')) | |
226 return self._getDomishInnerContent(elt) | |
227 | |
228 def microblogCB(self, itemsEvent, profile): | |
229 """Callback to "MICROBLOG" PEP event.""" | |
230 def manageItem(microblog_data): | |
231 self.host.bridge.personalEvent(itemsEvent.sender.full(), "MICROBLOG", microblog_data, profile) | |
232 | |
233 for item in itemsEvent.items: | |
234 self.item2mbdata(item).addCallbacks(manageItem, lambda failure: None) | |
235 | 215 |
236 @defer.inlineCallbacks | 216 @defer.inlineCallbacks |
237 def data2entry(self, data, profile): | 217 def data2entry(self, data, profile): |
238 """Convert a data dict to en entry usable to create an item | 218 """Convert a data dict to en entry usable to create an item |
239 | 219 |
295 _entry.links.append(link) | 275 _entry.links.append(link) |
296 _entry_elt = ElementParser()(str(_entry).decode('utf-8')) | 276 _entry_elt = ElementParser()(str(_entry).decode('utf-8')) |
297 item = pubsub.Item(id=entry_id, payload=_entry_elt) | 277 item = pubsub.Item(id=entry_id, payload=_entry_elt) |
298 defer.returnValue(item) | 278 defer.returnValue(item) |
299 | 279 |
280 ## publish ## | |
281 | |
300 @defer.inlineCallbacks | 282 @defer.inlineCallbacks |
301 def sendMicroblog(self, data, profile): | 283 def sendMicroblog(self, data, profile): |
302 """Send XEP-0277's microblog data | 284 """Send XEP-0277's microblog data |
303 | 285 |
304 @param data: must include content | 286 @param data: must include content |
312 raise exceptions.DataError('empty content') | 294 raise exceptions.DataError('empty content') |
313 item = yield self.data2entry(data, profile) | 295 item = yield self.data2entry(data, profile) |
314 ret = yield self.host.plugins["XEP-0060"].publish(None, NS_MICROBLOG, [item], profile_key=profile) | 296 ret = yield self.host.plugins["XEP-0060"].publish(None, NS_MICROBLOG, [item], profile_key=profile) |
315 defer.returnValue(ret) | 297 defer.returnValue(ret) |
316 | 298 |
299 ## get ## | |
300 | |
317 def getLastMicroblogs(self, pub_jid, max_items=10, profile_key=C.PROF_KEY_NONE): | 301 def getLastMicroblogs(self, pub_jid, max_items=10, profile_key=C.PROF_KEY_NONE): |
318 """Get the last published microblogs | 302 """Get the last published microblogs |
319 | 303 |
320 @param pub_jid: jid of the publisher | 304 @param pub_jid: jid of the publisher |
321 @param max_items: how many microblogs we want to get | 305 @param max_items: how many microblogs we want to get |
325 """ | 309 """ |
326 d = self.host.plugins["XEP-0060"].getItems(jid.JID(pub_jid), NS_MICROBLOG, max_items=max_items, profile_key=profile_key) | 310 d = self.host.plugins["XEP-0060"].getItems(jid.JID(pub_jid), NS_MICROBLOG, max_items=max_items, profile_key=profile_key) |
327 d.addCallback(lambda res: (defer.DeferredList(map(self.item2mbdata, res[0]), consumeErrors=True), res[1])) | 311 d.addCallback(lambda res: (defer.DeferredList(map(self.item2mbdata, res[0]), consumeErrors=True), res[1])) |
328 d.addCallback(lambda res: ([value for (success, value) in res[0] if success], res[1])) | 312 d.addCallback(lambda res: ([value for (success, value) in res[0] if success], res[1])) |
329 return d | 313 return d |
314 | |
315 def parseCommentUrl(self, node_url): | |
316 """Determine the fields comments_service and comments_node of a microblog data | |
317 from the href attribute of an entry's link element. For example this input: | |
318 xmpp:sat-pubsub.libervia.org?node=urn%3Axmpp%3Acomments%3A_c5c4a142-2279-4b2a-ba4c-1bc33aa87634__urn%3Axmpp%3Agroupblog%3Asouliane%40libervia.org | |
319 will return (JID(u'sat-pubsub.libervia.org'), 'urn:xmpp:comments:_c5c4a142-2279-4b2a-ba4c-1bc33aa87634__urn:xmpp:groupblog:souliane@libervia.org') | |
320 @return: a tuple (JID, str) | |
321 """ | |
322 parsed_url = urlparse.urlparse(node_url, 'xmpp') | |
323 service = jid.JID(parsed_url.path) | |
324 queries = parsed_url.query.split(';') | |
325 parsed_queries = dict() | |
326 for query in queries: | |
327 parsed_queries.update(urlparse.parse_qs(query)) | |
328 node = parsed_queries.get('node', [''])[0] | |
329 | |
330 if not node: | |
331 raise exceptions.DataError('Invalid comments link') | |
332 | |
333 return (service, node) | |
334 | |
335 ## configure ## | |
330 | 336 |
331 def setMicroblogAccess(self, access="presence", profile_key=C.PROF_KEY_NONE): | 337 def setMicroblogAccess(self, access="presence", profile_key=C.PROF_KEY_NONE): |
332 """Create a microblog node on PEP with given access | 338 """Create a microblog node on PEP with given access |
333 | 339 |
334 If the node already exists, it change options | 340 If the node already exists, it change options |