annotate sat/plugins/plugin_misc_forums.py @ 3528:849374e59178

component file sharing: quotas implementation: quotas can now be specified using the `quotas_json` option of `component file_sharing` section in settings. This must be a dict where: - `users` key contains default quotas for all users - `admins` key contains quotas for administrators (not implemented yet) - `jids` contain bare JID to quota mapping, to have user-specific quota The value can be either a int for quota in bytes, or a case insensitive string with an optional multiplier symbol (e.g. "500 Mio"). `None` can be used for explicit unlimited quota (which is the default is `users` is not set). When a file size is too big for quota, upload is refused with an error message indicating allowed quota, used space, and the size of the file that user wants to upload.
author Goffi <goffi@goffi.org>
date Wed, 05 May 2021 15:37:33 +0200
parents 2dce411c2647
children 3fd60beb9b92
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
1 #!/usr/bin/env python3
3137
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
2
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
2959
989b622faff6 plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
4 # SAT plugin for pubsub forums
3479
be6d91572633 date update
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
5 # Copyright (C) 2009-2021 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
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
32 NS_FORUMS = 'org.salut-a-toi.forums:0'
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
33 NS_FORUMS_TOPICS = NS_FORUMS + '#topics'
2484
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 }
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
45 FORUM_ATTR = {'title', 'name', 'main-language', 'uri'}
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
46 FORUM_SUB_ELTS = ('short-desc', 'desc')
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
47 FORUM_TOPICS_NODE_TPL = '{node}#topics_{uuid}'
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
48 FORUM_TOPIC_NODE_TPL = '{node}_{uuid}'
2484
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):
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
54 log.info(_("forums plugin initialization"))
2484
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,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
70 async_=True)
2484
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,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
74 async_=True)
2484
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,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
78 async_=True)
2484
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,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
82 async_=True)
2484
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):
2959
989b622faff6 plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
86 """Recursively create <forums> element(s)
2484
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):
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
97 raise ValueError(_("forums arguments must be a list of forums"))
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 if forums_elt is None:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
99 forums_elt = domish.Element((NS_FORUMS, 'forums'))
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
103 if names is None or forums_elt.name != 'forums':
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
104 raise exceptions.InternalError('invalid forums or names')
2484
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):
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
109 raise ValueError(_("A forum item must be a dictionary"))
2484
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
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
112 for key, value in forum.items():
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
113 if key == 'name' and key in names:
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
114 raise exceptions.ConflictError(_("following forum name is not unique: {name}").format(name=key))
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
115 if key == 'uri' and not value.strip():
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
116 log.info(_("creating missing forum node"))
2484
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)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
119 value = uri.buildXMPPUri('pubsub',
2484
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)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
126 elif key == 'sub-forums':
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
127 sub_forums_elt = forum_elt.addElement('forums')
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
130 log.warning(_("Unknown forum attribute: {key}").format(key=key))
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
131 if not forum_elt.getAttribute('title'):
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
132 name = forum_elt.getAttribute('name')
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 if name:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
134 forum_elt['title'] = name
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 else:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
136 raise ValueError(_("forum need a title or a name"))
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
137 if not forum_elt.getAttribute('uri') and not forum_elt.children:
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
138 raise ValueError(_("forum need uri or sub-forums"))
2484
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):
2959
989b622faff6 plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
142 """Recursivly parse a <forums> elements and return corresponding forums data
2484
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 """
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
149 if parent_elt.name == 'item':
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
152 forums_elt = next(parent_elt.elements(NS_FORUMS, 'forums'))
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 except StopIteration:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
154 raise ValueError(_("missing <forums> element"))
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
158 raise exceptions.InternalError('expected forums')
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 if forums_elt.name != 'forums':
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
160 raise ValueError(_('Unexpected element: {xml}').format(xml=forums_elt.toXml()))
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
168 log.warning(_("Following attributes are unknown: {unknown}").format(unknown=unknown))
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
171 data[elt.name] = str(elt)
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
172 elif elt.name == 'forums':
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
173 sub_forums = data['sub-forums'] = []
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 self._parseForums(elt, sub_forums)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
175 if not 'title' in data or not {'uri', 'sub-forums'}.intersection(data):
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
176 log.warning(_("invalid forum, ignoring: {xml}").format(xml=forum_elt.toXml()))
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
180 log.warning(_("unkown forums sub element: {xml}").format(xml=forum_elt))
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
203 forums_key = 'default'
2484
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):
2959
989b622faff6 plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
223 """Create or replace forums structure
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
244 forums_key = 'default'
2484
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)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
252 d.addCallback(lambda topics_metadata: (topics_metadata[0], {k: str(v) for k,v in topics_metadata[1].items()}))
2484
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):
2959
989b622faff6 plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
257 """Retrieve topics data
2484
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:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
265 topic_elt = next(item_elt.elements(NS_FORUMS, 'topic'))
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
266 title_elt = next(topic_elt.elements(NS_FORUMS, 'title'))
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
267 topic = {'uri': topic_elt['uri'],
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
268 'author': topic_elt['author'],
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
269 'title': str(title_elt)}
2484
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)
3515
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
275 return defer.ensureDeferred(
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
276 self.createTopic(client, jid.JID(service), node, mb_data)
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
277 )
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
278
3515
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
279 async def createTopic(self, client, service, node, mb_data):
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
280 try:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
281 title = mb_data['title']
3515
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
282 content = mb_data.pop('content')
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
283 except KeyError as e:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
284 raise exceptions.DataError("missing mandatory data: {key}".format(key=e.args[0]))
3515
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
285 else:
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
286 mb_data["content_rich"] = content
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 topic_node = FORUM_TOPIC_NODE_TPL.format(node=node, uuid=shortuuid.uuid())
3515
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
288 await self._p.createNode(client, service, topic_node, self._node_options)
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
289 await self._m.send(client, mb_data, service, topic_node)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
290 topic_uri = uri.buildXMPPUri('pubsub',
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
291 subtype='microblog',
2484
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
292 path=service.full(),
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 node=topic_node)
785b6a1cef0a plugin forums: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 topic_elt = domish.Element((NS_FORUMS, 'topic'))
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
295 topic_elt['uri'] = topic_uri
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
296 topic_elt['author'] = client.jid.userhost()
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2959
diff changeset
297 topic_elt.addElement('title', content = title)
3515
2dce411c2647 plugin misc forums: use rich content in createTopic
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
298 await self._p.sendItem(client, service, node, topic_elt)