jp (blog): new --attachment argument to attach files or external data to a blog post
This commit is contained in:
parent
c3f97ec712
commit
d52af77c44
1 changed files with 80 additions and 19 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue