cli (blog): preserve existing item fields on set -i + attachments fixes:
- `set -i` was replacing all fields of any existing item, losing tags, attachments, publication date, etc. It now fetches the existing item if any, and starts from its data. `-r/--replace` can be used to force a full replacement (and avoid fetching old item). - `--attachment` uses `action="extend"` so multiple `-a` can be used. - Fix attachement data key (`url` -> `sources`).
This commit is contained in:
parent
8afde9962a
commit
fa04667152
1 changed files with 53 additions and 14 deletions
|
|
@ -39,6 +39,7 @@ from libervia.backend.tools.common import data_format
|
||||||
from libervia.backend.tools.common.ansi import ANSI as A
|
from libervia.backend.tools.common.ansi import ANSI as A
|
||||||
from libervia.cli import common
|
from libervia.cli import common
|
||||||
from libervia.cli.constants import Const as C
|
from libervia.cli.constants import Const as C
|
||||||
|
from libervia.frontends.bridge.bridge_frontend import BridgeException
|
||||||
|
|
||||||
from . import base, cmd_pubsub
|
from . import base, cmd_pubsub
|
||||||
|
|
||||||
|
|
@ -145,6 +146,23 @@ class AltLinkAction(argparse.Action):
|
||||||
class BlogPublishCommon:
|
class BlogPublishCommon:
|
||||||
"""handle common option for publising commands (Set and Edit)"""
|
"""handle common option for publising commands (Set and Edit)"""
|
||||||
|
|
||||||
|
async def get_existing_item(self, service, node, item):
|
||||||
|
"""Fetch the data of an existing item from the pubsub service.
|
||||||
|
|
||||||
|
@param service: JID of the pubsub service (None for PEP)
|
||||||
|
@param node: identifier of the pubsub node (None for the default one)
|
||||||
|
@param item: ID of the item to fetch (None for the latest item)
|
||||||
|
@return: deserialised data of the item
|
||||||
|
@raise BridgeException: if the item can't be fetched (e.g. "item-not-found")
|
||||||
|
"""
|
||||||
|
items = [item] if item else []
|
||||||
|
mb_data = data_format.deserialise(
|
||||||
|
await self.host.bridge.mb_get(
|
||||||
|
service, node, 1, items, data_format.serialise({}), self.profile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return mb_data["items"][0]
|
||||||
|
|
||||||
async def get_current_syntax(self):
|
async def get_current_syntax(self):
|
||||||
"""Retrieve current_syntax
|
"""Retrieve current_syntax
|
||||||
|
|
||||||
|
|
@ -190,6 +208,7 @@ class BlogPublishCommon:
|
||||||
"-a",
|
"-a",
|
||||||
"--attachment",
|
"--attachment",
|
||||||
dest="attachments",
|
dest="attachments",
|
||||||
|
action="extend",
|
||||||
nargs="+",
|
nargs="+",
|
||||||
help=_("attachment in the form URL [metadata_name=value]"),
|
help=_("attachment in the form URL [metadata_name=value]"),
|
||||||
)
|
)
|
||||||
|
|
@ -282,13 +301,13 @@ class BlogPublishCommon:
|
||||||
f" accepted): {arg}"
|
f" accepted): {arg}"
|
||||||
)
|
)
|
||||||
if attachment:
|
if attachment:
|
||||||
# if we hae a new URL, we have a new attachment
|
# if we have a new URL, we have a new attachment
|
||||||
attachments.append(attachment)
|
attachments.append(attachment)
|
||||||
attachment = {}
|
attachment = {}
|
||||||
attachment["url"] = arg
|
attachment["sources"] = [{"url": arg}]
|
||||||
else:
|
else:
|
||||||
# we should have a metadata
|
# we should have a metadata
|
||||||
if "url" not in attachment:
|
if "sources" not in attachment:
|
||||||
self.parser.error(
|
self.parser.error(
|
||||||
"you must to specify an URL before any metadata in "
|
"you must to specify an URL before any metadata in "
|
||||||
"--attachment"
|
"--attachment"
|
||||||
|
|
@ -351,13 +370,40 @@ class Set(base.CommandBase, BlogPublishCommon):
|
||||||
|
|
||||||
def add_parser_options(self):
|
def add_parser_options(self):
|
||||||
BlogPublishCommon.add_parser_options(self)
|
BlogPublishCommon.add_parser_options(self)
|
||||||
|
self.parser.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--replace",
|
||||||
|
action="store_true",
|
||||||
|
help=_(
|
||||||
|
"don't fetch the existing item, replace all its fields with "
|
||||||
|
"the given ones (only used with -i)"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
async def start(self):
|
async def start(self):
|
||||||
self.current_syntax = await self.get_current_syntax()
|
self.current_syntax = await self.get_current_syntax()
|
||||||
self.pubsub_item = self.args.item
|
self.pubsub_item = self.args.item
|
||||||
mb_data = {
|
if self.args.replace and not self.pubsub_item:
|
||||||
"service": self.args.service or None,
|
self.parser.error("--replace can only be used with -i")
|
||||||
}
|
mb_data = {}
|
||||||
|
if self.pubsub_item and not self.args.replace:
|
||||||
|
# start from the existing item data, so fields not given on the command line
|
||||||
|
# (tags, attachments, publication date, etc.) are kept
|
||||||
|
try:
|
||||||
|
existing = await self.get_existing_item(
|
||||||
|
self.args.service, self.args.node, self.pubsub_item
|
||||||
|
)
|
||||||
|
except BridgeException as e:
|
||||||
|
if e.condition == "item-not-found":
|
||||||
|
self.disp(f"item {self.pubsub_item!r} not found, creating a new one")
|
||||||
|
else:
|
||||||
|
self.disp(f"can't get item: {e}", error=True)
|
||||||
|
self.host.quit(C.EXIT_BRIDGE_ERRBACK)
|
||||||
|
else:
|
||||||
|
for key in KEY_TO_REMOVE_METADATA:
|
||||||
|
existing.pop(key, None)
|
||||||
|
mb_data.update(existing)
|
||||||
|
mb_data["service"] = self.args.service or None
|
||||||
if self.args.node:
|
if self.args.node:
|
||||||
mb_data["node"] = self.args.node
|
mb_data["node"] = self.args.node
|
||||||
self.set_mb_data_from_args(mb_data)
|
self.set_mb_data_from_args(mb_data)
|
||||||
|
|
@ -731,14 +777,7 @@ class Edit(base.CommandBase, BlogPublishCommon, common.BaseEdit):
|
||||||
return SYNTAX_EXT.get(self.current_syntax, SYNTAX_EXT[""])
|
return SYNTAX_EXT.get(self.current_syntax, SYNTAX_EXT[""])
|
||||||
|
|
||||||
async def get_item_data(self, service, node, item):
|
async def get_item_data(self, service, node, item):
|
||||||
items = [item] if item else []
|
item = await self.get_existing_item(service, node, item)
|
||||||
|
|
||||||
mb_data = data_format.deserialise(
|
|
||||||
await self.host.bridge.mb_get(
|
|
||||||
service, node, 1, items, data_format.serialise({}), self.profile
|
|
||||||
)
|
|
||||||
)
|
|
||||||
item = mb_data["items"][0]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
content = item["content_xhtml"]
|
content = item["content_xhtml"]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue