annotate sat/plugins/plugin_misc_forums.py @ 2891:6a0f42e9410a

core (xmpp): implemented roster versioning
author Goffi <goffi@goffi.org>
date Sun, 07 Apr 2019 18:47:17 +0200
parents 003b8b4b56a7
children 989b622faff6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python2
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # SAT plugin for Pubsub Schemas
2771
003b8b4b56a7 date update
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from sat.core.i18n import _
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from sat.core.constants import Const as C
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 from sat.core import exceptions
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 from sat.core.log import getLogger
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 from sat.tools.common import uri
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from twisted.words.protocols.jabber import jid
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from twisted.words.xish import domish
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from twisted.internet import defer
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 import shortuuid
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 import json
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 log = getLogger(__name__)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
31
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 NS_FORUMS = u'org.salut-a-toi.forums:0'
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 NS_FORUMS_TOPICS = NS_FORUMS + u'#topics'
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
34
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 PLUGIN_INFO = {
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 C.PI_NAME: _("forums management"),
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 C.PI_IMPORT_NAME: "forums",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 C.PI_TYPE: "EXP",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 C.PI_PROTOCOLS: [],
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 C.PI_DEPENDENCIES: ["XEP-0060", "XEP-0277"],
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 C.PI_MAIN: "forums",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 C.PI_HANDLER: "no",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 C.PI_DESCRIPTION: _("""forums management plugin""")
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 }
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 FORUM_ATTR = {u'title', u'name', u'main-language', u'uri'}
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 FORUM_SUB_ELTS = (u'short-desc', u'desc')
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 FORUM_TOPICS_NODE_TPL = u'{node}#topics_{uuid}'
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 FORUM_TOPIC_NODE_TPL = u'{node}_{uuid}'
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
49
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
50
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 class forums(object):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
52
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
53 def __init__(self, host):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 log.info(_(u"forums plugin initialization"))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 self.host = host
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 self._m = self.host.plugins['XEP-0277']
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 self._p = self.host.plugins['XEP-0060']
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 self._node_options = {
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 self._p.OPT_PERSIST_ITEMS: 1,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 self._p.OPT_MAX_ITEMS: -1,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 self._p.OPT_DELIVER_PAYLOADS: 1,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
63 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 }
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 host.registerNamespace('forums', NS_FORUMS)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 host.bridge.addMethod("forumsGet", ".plugin",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 in_sign='ssss', out_sign='s',
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 method=self._get,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 async=True)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
71 host.bridge.addMethod("forumsSet", ".plugin",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
72 in_sign='sssss', out_sign='',
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
73 method=self._set,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 async=True)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 host.bridge.addMethod("forumTopicsGet", ".plugin",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
76 in_sign='ssa{ss}s', out_sign='(aa{ss}a{ss})',
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 method=self._getTopics,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 async=True)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 host.bridge.addMethod("forumTopicCreate", ".plugin",
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 in_sign='ssa{ss}s', out_sign='',
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 method=self._createTopic,
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 async=True)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
83
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 @defer.inlineCallbacks
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 def _createForums(self, client, forums, service, node, forums_elt=None, names=None):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 """recursively create <forums> element(s)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
87
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 @param forums(list): forums which may have subforums
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 @param service(jid.JID): service where the new nodes will be created
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
90 @param node(unicode): node of the forums
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 will be used as basis for the newly created nodes
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 @param parent_elt(domish.Element, None): element where the forum must be added
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 if None, the root <forums> element will be created
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 @return (domish.Element): created forums
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 """
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 if not isinstance(forums, list):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 raise ValueError(_(u"forums arguments must be a list of forums"))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 if forums_elt is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 forums_elt = domish.Element((NS_FORUMS, u'forums'))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 assert names is None
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 names = set()
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 if names is None or forums_elt.name != u'forums':
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 raise exceptions.InternalError(u'invalid forums or names')
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 assert names is not None
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
106
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 for forum in forums:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 if not isinstance(forum, dict):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 raise ValueError(_(u"A forum item must be a dictionary"))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 forum_elt = forums_elt.addElement('forum')
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
111
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 for key, value in forum.iteritems():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 if key == u'name' and key in names:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 raise exceptions.ConflictError(_(u"following forum name is not unique: {name}").format(name=key))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 if key == u'uri' and not value.strip():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 log.info(_(u"creating missing forum node"))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 forum_node = FORUM_TOPICS_NODE_TPL.format(node=node, uuid=shortuuid.uuid())
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 yield self._p.createNode(client, service, forum_node, self._node_options)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 value = uri.buildXMPPUri(u'pubsub',
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
120 path=service.full(),
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 node=forum_node)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
122 if key in FORUM_ATTR:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
123 forum_elt[key] = value.strip()
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
124 elif key in FORUM_SUB_ELTS:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
125 forum_elt.addElement(key, content=value)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
126 elif key == u'sub-forums':
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 sub_forums_elt = forum_elt.addElement(u'forums')
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 yield self._createForums(client, value, service, node, sub_forums_elt, names=names)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 log.warning(_(u"Unknown forum attribute: {key}").format(key=key))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 if not forum_elt.getAttribute(u'title'):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 name = forum_elt.getAttribute(u'name')
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 if name:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 forum_elt[u'title'] = name
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 raise ValueError(_(u"forum need a title or a name"))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 if not forum_elt.getAttribute(u'uri') and not forum_elt.children:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 raise ValueError(_(u"forum need uri or sub-forums"))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 defer.returnValue(forums_elt)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
140
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 def _parseForums(self, parent_elt=None, forums=None):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 """recursivly parse a <forums> elements and return corresponding forums data
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
143
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 @param item(domish.Element): item with <forums> element
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 @param parent_elt(domish.Element, None): element to parse
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 @return (list): parsed data
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 @raise ValueError: item is invalid
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 """
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 if parent_elt.name == u'item':
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 forums = []
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 try:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 forums_elt = next(parent_elt.elements(NS_FORUMS, u'forums'))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 except StopIteration:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 raise ValueError(_(u"missing <forums> element"))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 forums_elt = parent_elt
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 if forums is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 raise exceptions.InternalError(u'expected forums')
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 if forums_elt.name != 'forums':
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 raise ValueError(_(u'Unexpected element: {xml}').format(xml=forums_elt.toXml()))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 for forum_elt in forums_elt.elements():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 if forum_elt.name == 'forum':
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 data = {}
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 for attrib in FORUM_ATTR.intersection(forum_elt.attributes):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 data[attrib] = forum_elt[attrib]
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 unknown = set(forum_elt.attributes).difference(FORUM_ATTR)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 if unknown:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
168 log.warning(_(u"Following attributes are unknown: {unknown}").format(unknown=unknown))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 for elt in forum_elt.elements():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 if elt.name in FORUM_SUB_ELTS:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 data[elt.name] = unicode(elt)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
172 elif elt.name == u'forums':
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 sub_forums = data[u'sub-forums'] = []
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 self._parseForums(elt, sub_forums)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
175 if not u'title' in data or not {u'uri', u'sub-forums'}.intersection(data):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
176 log.warning(_(u"invalid forum, ignoring: {xml}").format(xml=forum_elt.toXml()))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 forums.append(data)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 log.warning(_(u"unkown forums sub element: {xml}").format(xml=forum_elt))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
181
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 return forums
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
183
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 def _get(self, service=None, node=None, forums_key=None, profile_key=C.PROF_KEY_NONE):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 client = self.host.getClient(profile_key)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
186 if service.strip():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 service = jid.JID(service)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 service = None
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 if not node.strip():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 node = None
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 d=self.get(client, service, node, forums_key or None)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 d.addCallback(lambda data: json.dumps(data))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 return d
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
195
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 @defer.inlineCallbacks
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 def get(self, client, service=None, node=None, forums_key=None):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 if service is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 service = client.pubsub_service
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 if node is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 node = NS_FORUMS
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 if forums_key is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 forums_key = u'default'
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 items_data = yield self._p.getItems(client, service, node, item_ids=[forums_key])
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 item = items_data[0][0]
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 # we have the item and need to convert it to json
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 forums = self._parseForums(item)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 defer.returnValue(forums)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
209
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 def _set(self, forums, service=None, node=None, forums_key=None, profile_key=C.PROF_KEY_NONE):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
211 client = self.host.getClient(profile_key)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 forums = json.loads(forums)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 if service.strip():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 service = jid.JID(service)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 else:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 service = None
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 if not node.strip():
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 node = None
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 return self.set(client, forums, service, node, forums_key or None)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
220
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 @defer.inlineCallbacks
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 def set(self, client, forums, service=None, node=None, forums_key=None):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 """create or replace forums structure
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
224
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 @param forums(list): list of dictionary as follow:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 a dictionary represent a forum metadata, with the following keys:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 - title: title of the forum
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
228 - name: short name (unique in those forums) for the forum
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 - main-language: main language to be use in the forums
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 - uri: XMPP uri to the microblog node hosting the forum
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 - short-desc: short description of the forum (in main-language)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 - desc: long description of the forum (in main-language)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 - sub-forums: a list of sub-forums with the same structure
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 title or name is needed, and uri or sub-forums
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 @param forums_key(unicode, None): key (i.e. item id) of the forums
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 may be used to store different forums structures for different languages
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 None to use "default"
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 """
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 if service is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 service = client.pubsub_service
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 if node is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 node = NS_FORUMS
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 if forums_key is None:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 forums_key = u'default'
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 forums_elt = yield self._createForums(client, forums, service, node)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 yield self._p.sendItem(client, service, node, forums_elt, item_id=forums_key)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
247
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 def _getTopics(self, service, node, extra=None, profile_key=C.PROF_KEY_NONE):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 client = self.host.getClient(profile_key)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 extra = self._p.parseExtra(extra)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 d = self.getTopics(client, jid.JID(service), node, rsm_request=extra.rsm_request, extra=extra.extra)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 d.addCallback(lambda(topics, metadata): (topics, {k: unicode(v) for k,v in metadata.iteritems()}))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 return d
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
254
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
255 @defer.inlineCallbacks
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 def getTopics(self, client, service, node, rsm_request=None, extra=None):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 """retrieve topics data
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
258
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
259 Topics are simple microblog URIs with some metadata duplicated from first post
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 """
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 topics_data = yield self._p.getItems(client, service, node, rsm_request=rsm_request, extra=extra)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
262 topics = []
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
263 item_elts, metadata = topics_data
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
264 for item_elt in item_elts:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 topic_elt = next(item_elt.elements(NS_FORUMS, u'topic'))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 title_elt = next(topic_elt.elements(NS_FORUMS, u'title'))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 topic = {u'uri': topic_elt[u'uri'],
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 u'author': topic_elt[u'author'],
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 u'title': unicode(title_elt)}
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 topics.append(topic)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 defer.returnValue((topics, metadata))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
272
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 def _createTopic(self, service, node, mb_data, profile_key):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 client = self.host.getClient(profile_key)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 return self.createTopic(client, jid.JID(service), node, mb_data)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
276
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
277 @defer.inlineCallbacks
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
278 def createTopic(self, client, service, node, mb_data):
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
279 try:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
280 title = mb_data[u'title']
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
281 if not u'content' in mb_data:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
282 raise KeyError(u'content')
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
283 except KeyError as e:
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
284 raise exceptions.DataError(u"missing mandatory data: {key}".format(key=e.args[0]))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
285
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 topic_node = FORUM_TOPIC_NODE_TPL.format(node=node, uuid=shortuuid.uuid())
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 yield self._p.createNode(client, service, topic_node, self._node_options)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
288 self._m.send(client, mb_data, service, topic_node)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
289 topic_uri = uri.buildXMPPUri(u'pubsub',
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
290 subtype=u'microblog',
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
291 path=service.full(),
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
292 node=topic_node)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 topic_elt = domish.Element((NS_FORUMS, 'topic'))
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 topic_elt[u'uri'] = topic_uri
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
295 topic_elt[u'author'] = client.jid.userhost()
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
296 topic_elt.addElement(u'title', content = title)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
297 yield self._p.sendItem(client, service, node, topic_elt)