Mercurial > libervia-backend
comparison src/plugins/plugin_misc_groupblog.py @ 311:0aa6ca6cdbdd
plugin group blog: group blog now use PEP to take profit of autosubscribe
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 12 Apr 2011 20:40:47 +0200 |
parents | 53adec87d1d7 |
children | f56108eb2880 |
comparison
equal
deleted
inserted
replaced
310:53adec87d1d7 | 311:0aa6ca6cdbdd |
---|---|
30 from wokkel import disco,pubsub | 30 from wokkel import disco,pubsub |
31 from feed.atom import Entry, Author | 31 from feed.atom import Entry, Author |
32 import uuid | 32 import uuid |
33 from time import time | 33 from time import time |
34 | 34 |
35 MBLOG_COLLECTION = 'MBLOGCOLLECTION' | 35 NS_MICROBLOG = 'urn:xmpp:microblog:%02d' |
36 CONFIG_NODE = 'CONFIG' | 36 CONFIG_NODE = 'CONFIG' |
37 OPT_ACCESS_MODEL = 'pubsub#access_model' | 37 OPT_ACCESS_MODEL = 'pubsub#access_model' |
38 OPT_PERSIST_ITEMS = 'pubsub#persist_items' | 38 OPT_PERSIST_ITEMS = 'pubsub#persist_items' |
39 OPT_MAX_ITEMS = 'pubsub#max_items' | 39 OPT_MAX_ITEMS = 'pubsub#max_items' |
40 OPT_NODE_TYPE = 'pubsub#node_type' | 40 OPT_NODE_TYPE = 'pubsub#node_type' |
64 | 64 |
65 def __init__(self, host): | 65 def __init__(self, host): |
66 info(_("Group blog plugin initialization")) | 66 info(_("Group blog plugin initialization")) |
67 self.host = host | 67 self.host = host |
68 self._blog_nodes={} | 68 self._blog_nodes={} |
69 for i in range(1,21): | |
70 self.host.plugins["XEP-0163"].addPEPEvent("MICROBLOG_%02d" % i, NS_MICROBLOG % i, self.host.plugins["XEP-0277"].microblogCB, None) | |
69 | 71 |
70 host.bridge.addMethod("cleanBlogCollection", ".communication", in_sign='s', out_sign='', | 72 host.bridge.addMethod("cleanBlogCollection", ".communication", in_sign='s', out_sign='', |
71 method=self.cleanBlogCollection, | 73 method=self.cleanBlogCollection, |
72 doc = { | 74 doc = { |
73 }) | 75 }) |
95 'param_1':'%(doc_profile)s' | 97 'param_1':'%(doc_profile)s' |
96 }) | 98 }) |
97 | 99 |
98 def _getRootNode(self, entity): | 100 def _getRootNode(self, entity): |
99 return "%(entity)s_%(root_suff)s" % {'entity':entity.userhost(), 'root_suff':MBLOG_COLLECTION} | 101 return "%(entity)s_%(root_suff)s" % {'entity':entity.userhost(), 'root_suff':MBLOG_COLLECTION} |
102 | |
103 def _getNodeName(self, number): | |
104 """Return the node name | |
105 @param number: int number of the node | |
106 @param entity: jid of the owner""" | |
107 return NS_MICROBLOG % number | |
100 | 108 |
101 def _getConfigNode(self, entity): | 109 def _getConfigNode(self, entity): |
102 return "%(entity)s_%(root_suff)s" % {'entity':entity.userhost(), 'root_suff':CONFIG_NODE} | 110 return "%(entity)s_%(root_suff)s" % {'entity':entity.userhost(), 'root_suff':CONFIG_NODE} |
103 | 111 |
104 def _configNodeCb(self, result, callback, profile): | 112 def _configNodeCb(self, result, callback, profile): |
143 if not client: | 151 if not client: |
144 error(_('No client for this profile key: %s') % profile_key) | 152 error(_('No client for this profile key: %s') % profile_key) |
145 return | 153 return |
146 client.client_initialized.addCallback(after_init) | 154 client.client_initialized.addCallback(after_init) |
147 | 155 |
148 def _publishMblog(self, name, message, pubsub_ent, profile): | 156 def _publishMblog(self, name, message, client): |
149 """Actually publish the message on the group blog | 157 """Actually publish the message on the group blog |
150 @param name: name of the node where we publish | 158 @param name: name of the node where we publish |
151 @param message: message to publish | 159 @param message: message to publish |
152 @param pubsub_ent: entity of the publish-subscribe service | 160 @param client: SatXMPPClient of the published""" |
153 @param profile: profile of the owner of the group""" | 161 mblog_item = self.host.plugins["XEP-0277"].data2entry({'content':message}, client.profile) |
154 mblog_item = self.host.plugins["XEP-0277"].data2entry({'content':message}, profile) | 162 defer_blog = self.host.plugins["XEP-0060"].publish(client.jid.userhostJID(), name, items=[mblog_item], profile_key=client.profile) |
155 defer_blog = self.host.plugins["XEP-0060"].publish(pubsub_ent, name, items=[mblog_item], profile_key=profile) | |
156 defer_blog.addErrback(self._mblogPublicationFailed) | 163 defer_blog.addErrback(self._mblogPublicationFailed) |
157 | 164 |
158 def _groupNodeCreated(self, ignore, groups, name, message, user_jid, pubsub_ent, profile): | 165 def _groupNodeCreated(self, ignore, groups, name, message, client): |
159 """A group node as been created, we need to add it to the configure node, and send the message to it | 166 """A group node as been created, we need to add it to the configure node, and send the message to it |
160 @param groups: list of groups authorized to subscribe to the node | 167 @param groups: list of groups authorized to subscribe to the node |
161 @param name: unique name of the group | 168 @param name: unique name of the node |
162 @param message: message to publish to the group | 169 @param message: message to publish to the group |
163 @param user_jid: jid of the owner of the node | 170 @param client: SatXMPPClient""" |
164 @param pubsub_ent: entity of the publish-subscribe service | 171 def configNodeUpdated(result): |
165 @param profile: profile of the owner of the group""" | 172 self._blog_nodes[client.profile][name] = groups |
166 config_node = self._getConfigNode(user_jid) | 173 debug(_("Configuration node updated")) |
174 | |
175 config_node = self._getConfigNode(client.jid) | |
167 _payload = domish.Element(('','node_association')) | 176 _payload = domish.Element(('','node_association')) |
168 _payload['node'] = name | 177 _payload['node'] = name |
169 for group in groups: | 178 for group in groups: |
170 _payload.addElement('group',content=group) | 179 _payload.addElement('group',content=group) |
171 config_item = pubsub.Item(payload=_payload) | 180 config_item = pubsub.Item(payload=_payload) |
172 defer_config = self.host.plugins["XEP-0060"].publish(pubsub_ent, config_node, items=[config_item], profile_key=profile) | 181 pubsub_ent = self.host.memory.getServerServiceEntity("pubsub", "service", client.profile) |
173 defer_config.addCallback(lambda x: debug(_("Configuration node updated"))) | 182 defer_config = self.host.plugins["XEP-0060"].publish(pubsub_ent, config_node, items=[config_item], profile_key=client.profile) |
183 defer_config.addCallback(configNodeUpdated) | |
174 defer_config.addErrback(self._configUpdateFailed) | 184 defer_config.addErrback(self._configUpdateFailed) |
175 | 185 |
176 #Finally, we publish the message | 186 #Finally, we publish the message |
177 self._publishMblog(name, message, pubsub_ent, profile) | 187 self._publishMblog(name, message, client) |
178 | 188 |
179 | 189 |
180 def _mblogPublicationFailed(self, failure): | 190 def _mblogPublicationFailed(self, failure): |
181 #TODO | 191 #TODO |
182 import pdb | 192 import pdb |
185 def _configUpdateFailed(self, failure): | 195 def _configUpdateFailed(self, failure): |
186 #TODO | 196 #TODO |
187 import pdb | 197 import pdb |
188 pdb.set_trace() | 198 pdb.set_trace() |
189 | 199 |
190 def _nodeCreationFailed(self, failure, name, user_jid, groups, pubsub_ent, message, profile): | 200 def _nodeCreationFailed(self, failure, name, groups, message, client): |
191 #TODO | 201 #FIXME: temporary behaviour is to delete the node, |
192 if failure.value.condition == "item-not-found": | 202 #user input should be required in the future |
193 #The root node doesn't exists | 203 def unmanagedError(failure): |
194 def err_creating_root_node(failure): | 204 msg = _("Can't create node") |
195 msg = _("Can't create Root node") | 205 error(msg) |
196 error(msg) | 206 raise NodeCreationError(msg) |
197 raise NodeCreationError(msg) | 207 |
198 | 208 if failure.value.condition == 'conflict': |
199 _options = {OPT_NODE_TYPE:TYPE_COLLECTION} | 209 pubsub_elts = filter(lambda elt: elt.name == 'pubsub', failure.value.children) |
200 d = self.host.plugins["XEP-0060"].createNode(pubsub_ent, self._getRootNode(user_jid), _options, profile_key=profile) | 210 if pubsub_elts: |
201 d.addCallback(self._createNode, name, user_jid, groups, pubsub_ent, message, profile) | 211 create_elts = filter(lambda elt: elt.name == 'create', pubsub_elts[0].children) |
202 d.addErrback(err_creating_root_node) | 212 if create_elts: |
213 _from = jid.JID(failure.value.stanza['from']) | |
214 _node = create_elts[0]['node'] | |
215 d = self.host.plugins["XEP-0060"].deleteNode(_from, _node, client.profile) | |
216 d.addCallback(self._createNode, name, groups, message, client) | |
217 d.addErrback(unmanagedError) | |
203 else: | 218 else: |
204 import pdb | 219 unmanagedError(None) |
205 pdb.set_trace() | 220 msg = _("Can't create node") |
206 | 221 error(msg) |
207 def _createNode(self, ignore, name, user_jid, groups, pubsub_ent, message, profile): | 222 raise NodeCreationError(msg) |
223 | |
224 def _createNode(self, ignore, name, groups, message, client): | |
208 """create a group microblog node | 225 """create a group microblog node |
209 @param ignore: ignored param, necessary to be added as a deferred callback | 226 @param ignore: ignored param, necessary to be added as a deferred callback |
210 @param name: name of the node | 227 @param name: name of the node |
211 @param user_jid: jid of the user creating the node | |
212 @param groups: list of group than can subscribe to the node | 228 @param groups: list of group than can subscribe to the node |
213 @param pubsub_ent: publish/subscribe service's entity | |
214 @param message: message to publish | 229 @param message: message to publish |
215 @param profile: profile of the user creating the node""" | 230 @param client: SatXMPPClient""" |
216 _options = {OPT_ACCESS_MODEL:"roster", OPT_PERSIST_ITEMS:1, OPT_MAX_ITEMS:-1, | 231 _options = {OPT_ACCESS_MODEL:"roster", OPT_PERSIST_ITEMS:1, OPT_MAX_ITEMS:-1, |
217 'pubsub#node_type':'leaf', 'pubsub#collection':self._getRootNode(user_jid), | |
218 'pubsub#roster_groups_allowed':groups} | 232 'pubsub#roster_groups_allowed':groups} |
219 d = self.host.plugins["XEP-0060"].createNode(pubsub_ent, name, _options, profile_key=profile) | 233 d = self.host.plugins["XEP-0060"].createNode(client.jid.userhostJID(), name, _options, client.profile) |
220 d.addCallback(self._groupNodeCreated, groups, name, message, user_jid, pubsub_ent, profile) | 234 d.addCallback(self._groupNodeCreated, groups, name, message, client) |
221 d.addErrback(self._nodeCreationFailed, name, user_jid, groups, pubsub_ent, message, profile) | 235 d.addErrback(self._nodeCreationFailed, name, groups, message, client) |
222 | 236 |
223 def _getNodeForGroups(self, groups, profile): | 237 def _getNodeForGroups(self, groups, profile): |
224 """Return node associated with the given list of groups | 238 """Return node associated with the given list of groups |
225 @param groups: list of groups | 239 @param groups: list of groups |
226 @param profile: profile of publisher""" | 240 @param profile: profile of publisher""" |
228 node_groups = self._blog_nodes[profile][node] | 242 node_groups = self._blog_nodes[profile][node] |
229 if set(node_groups) == set(groups): | 243 if set(node_groups) == set(groups): |
230 return node | 244 return node |
231 return None | 245 return None |
232 | 246 |
247 def _getFreeNode(self, entity, profile): | |
248 """Return a free group number, | |
249 raise an exception if we have reach limit""" | |
250 _all = set([self._getNodeName(idx) for idx in range(1,21)]) | |
251 _used = set(self._blog_nodes[profile].keys()) | |
252 _free = _all.difference(_used) | |
253 if not _free: | |
254 msg = _("Can't create group node: no more free node available") | |
255 warning(msg) | |
256 raise NodeCreationError(msg) | |
257 else: | |
258 return _free.pop() | |
259 | |
233 def sendGroupBlog(self, groups, message, profile_key='@DEFAULT@'): | 260 def sendGroupBlog(self, groups, message, profile_key='@DEFAULT@'): |
234 """Publish a microblog to the node associated to the groups | 261 """Publish a microblog to the node associated to the groups |
235 If the node doesn't exist, it is created, then the message is posted | 262 If the node doesn't exist, it is created, then the message is posted |
236 @param groups: list of groups allowed to retrieve the microblog | 263 @param groups: list of groups allowed to retrieve the microblog |
237 @param message: microblog | 264 @param message: microblog |
244 | 271 |
245 def after_init(ignore): | 272 def after_init(ignore): |
246 _groups = list(set(groups).intersection(client.roster.getGroups())) #We only keep group which actually exist | 273 _groups = list(set(groups).intersection(client.roster.getGroups())) #We only keep group which actually exist |
247 #TODO: send an error signal if user want to post to non existant groups | 274 #TODO: send an error signal if user want to post to non existant groups |
248 _groups.sort() | 275 _groups.sort() |
249 pubsub_ent = self.host.memory.getServerServiceEntity("pubsub", "service", profile) | |
250 for group in _groups: | 276 for group in _groups: |
251 _node = self._getNodeForGroups([group], profile) | 277 _node = self._getNodeForGroups([group], profile) |
252 if not _node: | 278 if not _node: |
253 _node_name = unicode(uuid.uuid4()) | 279 _node_name = self._getFreeNode(client.jid, profile) |
254 self._createNode(None, _node_name, client.jid, [group], pubsub_ent, message, profile) | 280 self._createNode(None, _node_name, [group], message, client) |
255 else: | 281 else: |
256 self._publishMblog(_node, message, pubsub_ent, profile) | 282 self._publishMblog(_node, message, client) |
257 | 283 |
258 client = self.host.getClient(profile) | 284 client = self.host.getClient(profile) |
259 if not client: | 285 if not client: |
260 error(_('No client for this profile key: %s') % profile_key) | 286 error(_('No client for this profile key: %s') % profile_key) |
261 return | 287 return |
320 client = self.host.getClient(profile) | 346 client = self.host.getClient(profile) |
321 if not client: | 347 if not client: |
322 error(_('No client for this profile key: %s') % profile_key) | 348 error(_('No client for this profile key: %s') % profile_key) |
323 return | 349 return |
324 client.client_initialized.addCallback(after_init) | 350 client.client_initialized.addCallback(after_init) |
351 |