jp (blog): new --attachment argument to attach files or external data to a blog post

This commit is contained in:
Goffi 2023-03-23 15:43:48 +01:00
commit d52af77c44

View file

@ -18,24 +18,28 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import sys
import os.path
import os
import tempfile
import subprocess
import asyncio
from asyncio.subprocess import DEVNULL
from configparser import NoOptionError, NoSectionError
import json
import os
import os.path
from pathlib import Path
from . import base, cmd_pubsub
import re
import subprocess
import sys
import tempfile
from urllib.parse import urlparse
from sat.core.i18n import _
from sat_frontends.jp.constants import Const as C
from sat_frontends.jp import common
from sat.tools.common.ansi import ANSI as A
from sat.tools.common import uri
from sat.tools import config
from configparser import NoSectionError, NoOptionError
from sat.tools.common import uri
from sat.tools.common import data_format
from sat.tools.common.ansi import ANSI as A
from sat_frontends.jp import common
from sat_frontends.jp.constants import Const as C
from . import base, cmd_pubsub
__commands__ = ["Blog"]
@ -84,6 +88,8 @@ MB_KEYS = (
"extra"
)
OUTPUT_OPT_NO_HEADER = "no-header"
RE_ATTACHMENT_METADATA = re.compile(r"^(?P<key>[a-z_]+)=(?P<value>.*)")
ALLOWER_ATTACH_MD_KEY = ("desc", "media_type", "external")
async def guessSyntaxFromPath(host, sat_conf, path):
@ -104,7 +110,7 @@ async def guessSyntaxFromPath(host, sat_conf, path):
return await host.bridge.getParamA("Syntax", "Composition", "value", host.profile)
class BlogPublishCommon(object):
class BlogPublishCommon:
"""handle common option for publising commands (Set and Edit)"""
async def get_current_syntax(self):
@ -148,6 +154,16 @@ class BlogPublishCommon(object):
help=_("language of the item (ISO 639 code)"),
)
self.parser.add_argument(
"-a",
"--attachment",
dest="attachments",
nargs="+",
help=_(
"attachment in the form URL [metadata_name=value]"
)
)
comments_group = self.parser.add_mutually_exclusive_group()
comments_group.add_argument(
"-C",
@ -192,7 +208,7 @@ class BlogPublishCommon(object):
help=_("cryptographically sign the blog post")
)
async def setMbDataContent(self, content, mb_data):
async def set_mb_data_content(self, content, mb_data):
if self.default_syntax_used:
# default syntax has been used
mb_data["content_rich"] = content
@ -203,7 +219,51 @@ class BlogPublishCommon(object):
content, self.current_syntax, SYNTAX_XHTML, False, self.profile
)
def setMbDataFromArgs(self, mb_data):
def handle_attachments(self, mb_data: dict) -> None:
"""Check, validate and add attachments to mb_data"""
if self.args.attachments:
attachments = []
attachment = {}
for arg in self.args.attachments:
m = RE_ATTACHMENT_METADATA.match(arg)
if m is None:
# we should have an URL
url_parsed = urlparse(arg)
if url_parsed.scheme not in ("http", "https"):
self.parser.error(
"invalid URL in --attachment (only http(s) scheme is "
f" accepted): {arg}"
)
if attachment:
# if we hae a new URL, we have a new attachment
attachments.append(attachment)
attachment = {}
attachment["url"] = arg
else:
# we should have a metadata
if "url" not in attachment:
self.parser.error(
"you must to specify an URL before any metadata in "
"--attachment"
)
key = m.group("key")
if key not in ALLOWER_ATTACH_MD_KEY:
self.parser.error(
f"invalid metadata key in --attachment: {key!r}"
)
value = m.group("value").strip()
if key == "external":
if not value:
value=True
else:
value = C.bool(value)
attachment[key] = value
if attachment:
attachments.append(attachment)
if attachments:
mb_data.setdefault("extra", {})["attachments"] = attachments
def set_mb_data_from_args(self, mb_data):
"""set microblog metadata according to command line options
if metadata already exist, it will be overwritten
@ -222,6 +282,7 @@ class BlogPublishCommon(object):
mb_data["signed"] = True
if self.args.encrypt_for:
mb_data["encrypted_for"] = {"targets": self.args.encrypt_for}
self.handle_attachments(mb_data)
class Set(base.CommandBase, BlogPublishCommon):
@ -243,11 +304,11 @@ class Set(base.CommandBase, BlogPublishCommon):
self.current_syntax = await self.get_current_syntax()
self.pubsub_item = self.args.item
mb_data = {}
self.setMbDataFromArgs(mb_data)
self.set_mb_data_from_args(mb_data)
if self.pubsub_item:
mb_data["id"] = self.pubsub_item
content = sys.stdin.read()
await self.setMbDataContent(content, mb_data)
await self.set_mb_data_content(content, mb_data)
try:
item_id = await self.host.bridge.mbSend(
@ -533,7 +594,7 @@ class Edit(base.CommandBase, BlogPublishCommon, common.BaseEdit):
except KeyError:
pass
# and override metadata with command-line arguments
self.setMbDataFromArgs(mb_data)
self.set_mb_data_from_args(mb_data)
if self.args.no_publish:
mb_data["publish"] = False
@ -597,7 +658,7 @@ class Edit(base.CommandBase, BlogPublishCommon, common.BaseEdit):
await asyncio.gather(*coroutines)
async def publish(self, content, mb_data):
await self.setMbDataContent(content, mb_data)
await self.set_mb_data_content(content, mb_data)
if self.pubsub_item:
mb_data["id"] = self.pubsub_item