diff --git a/doc/libervia-cli/forums.rst b/doc/libervia-cli/forums.rst
index d44dcbd5..577b6c51 100644
--- a/doc/libervia-cli/forums.rst
+++ b/doc/libervia-cli/forums.rst
@@ -28,6 +28,22 @@ Get structure of French forums in JSON::
$ li forums get -k fr -O json
+set
+===
+
+Set forums from JSON, the JSON must be given as input.
+
+Check :ref:`libervia-cli_blog_edit` for the data format.
+
+example
+-------
+
+Set the forums structure from a ``forums.json`` file::
+
+ $ li forums set < forums.json
+
+
+.. _libervia-cli_forums_edit:
edit
====
@@ -51,6 +67,8 @@ metadata are set. You can use the following metadata:
``uri``
URI to the PubSub node containing the messages of the topic (it's actually a blog node
with suitable permissions). URI must only be set for topic, not for categories.
+ If ``uri`` is empty, a node will be created automatically and the ``uri`` will be filled
+ accordingly.
``sub-forums``
list of object with the same metadata (i.e. other topics or categories)
diff --git a/libervia/backend/plugins/plugin_misc_forums.py b/libervia/backend/plugins/plugin_misc_forums.py
index 252f4bd6..52be4cdf 100644
--- a/libervia/backend/plugins/plugin_misc_forums.py
+++ b/libervia/backend/plugins/plugin_misc_forums.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+from typing import Iterable
+from libervia.backend.core.core_types import SatXMPPEntity
from libervia.backend.core.i18n import _
from libervia.backend.core.constants import Const as C
from libervia.backend.core import exceptions
@@ -80,8 +82,15 @@ class forums(object):
method=self._create_topic,
async_=True)
- @defer.inlineCallbacks
- def _create_forums(self, client, forums, service, node, forums_elt=None, names=None):
+ async def _create_forums(
+ self,
+ client: SatXMPPEntity,
+ forums: list[dict],
+ service: jid.JID,
+ node: str,
+ forums_elt: domish.Element|None = None,
+ names: Iterable = None
+ ) -> domish.Element:
"""Recursively create element(s)
@param forums(list): forums which may have subforums
@@ -111,10 +120,10 @@ class forums(object):
for key, value in forum.items():
if key == 'name' and key in names:
raise exceptions.ConflictError(_("following forum name is not unique: {name}").format(name=key))
- if key == 'uri' and not value.strip():
+ if key == 'uri' and value is None or not value.strip():
log.info(_("creating missing forum node"))
forum_node = FORUM_TOPICS_NODE_TPL.format(node=node, uuid=shortuuid.uuid())
- yield self._p.createNode(client, service, forum_node, self._node_options)
+ await self._p.createNode(client, service, forum_node, self._node_options)
value = uri.build_xmpp_uri('pubsub',
path=service.full(),
node=forum_node)
@@ -123,8 +132,9 @@ class forums(object):
elif key in FORUM_SUB_ELTS:
forum_elt.addElement(key, content=value)
elif key == 'sub-forums':
+ assert isinstance(value, list)
sub_forums_elt = forum_elt.addElement('forums')
- yield self._create_forums(client, value, service, node, sub_forums_elt, names=names)
+ await self._create_forums(client, value, service, node, sub_forums_elt, names=names)
else:
log.warning(_("Unknown forum attribute: {key}").format(key=key))
if not forum_elt.getAttribute('title'):
@@ -135,7 +145,7 @@ class forums(object):
raise ValueError(_("forum need a title or a name"))
if not forum_elt.getAttribute('uri') and not forum_elt.children:
raise ValueError(_("forum need uri or sub-forums"))
- defer.returnValue(forums_elt)
+ return forums_elt
def _parse_forums(self, parent_elt=None, forums=None):
"""Recursivly parse a elements and return corresponding forums data
diff --git a/libervia/cli/cmd_forums.py b/libervia/cli/cmd_forums.py
index 83b8e90c..a3176a73 100644
--- a/libervia/cli/cmd_forums.py
+++ b/libervia/cli/cmd_forums.py
@@ -18,11 +18,13 @@
# along with this program. If not, see .
+import sys
from . import base
from libervia.backend.core.i18n import _
from libervia.cli.constants import Const as C
from libervia.cli import common
from libervia.backend.tools.common.ansi import ANSI as A
+from libervia.frontends.bridge.bridge_frontend import BridgeException
import codecs
import json
@@ -82,7 +84,7 @@ class Edit(base.CommandBase, common.BaseEdit):
self.args.key,
self.profile,
)
- except Exception as e:
+ except BridgeException as e:
if e.classname == "NotFound":
forums_json = ""
else:
@@ -169,11 +171,51 @@ class Get(base.CommandBase):
self.host.quit(1)
forums = json.loads(forums_raw)
await self.output(forums)
+
+
+class Set(base.CommandBase):
+
+ def __init__(self, host):
+ base.CommandBase.__init__(
+ self,
+ host,
+ "set",
+ use_pubsub=True,
+ help=_("set forums"),
+ )
+
+ def add_parser_options(self):
+ self.parser.add_argument(
+ "-k",
+ "--key",
+ default="",
+ help=_("forum key (DEFAULT: default forums)"),
+ )
+
+ async def start(self):
+ forums_raw = sys.stdin.read()
+ try:
+ json.loads(forums_raw)
+ except Exception as e:
+ self.parser.error(f"Invalid JSON, a valid JSON must be used as input: {e}")
+ try:
+ await self.host.bridge.forums_set(
+ forums_raw,
+ self.args.service,
+ self.args.node,
+ self.args.key,
+ self.profile,
+ )
+ except Exception as e:
+ self.disp(f"can't set forums: {e}", error=True)
+ self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+ else:
+ self.disp(_("forums have been set"))
self.host.quit()
class Forums(base.CommandBase):
- subcommands = (Get, Edit)
+ subcommands = (Get, Set, Edit)
def __init__(self, host):
super(Forums, self).__init__(