From 6554586a5ff126b4589dd5f164a719ad79487441 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 15 Oct 2020 21:54:17 +0200 Subject: [PATCH] created redaktion --- archetypes/default.md | 6 + archetypes/post.md | 75 ++++ redaktion/.gitignore | 6 + redaktion/assets/logo-inkscape.svg | 163 ++++++++ redaktion/assets/logo.jpg | Bin 0 -> 11547 bytes redaktion/assets/logo.png | Bin 0 -> 3136 bytes redaktion/assets/logo40-dark.png | Bin 0 -> 1450 bytes redaktion/assets/logo40-t.png | Bin 0 -> 1610 bytes redaktion/assets/logo40.png | Bin 0 -> 1676 bytes redaktion/assets/stravainkscape.svg | 114 ++++++ redaktion/backup.sh | 3 + redaktion/load.sh | 77 ++++ redaktion/publish.sh | 5 + redaktion/red.py | 597 ++++++++++++++++++++++++++++ redaktion/requirements.txt | 2 + 15 files changed, 1048 insertions(+) create mode 100644 archetypes/default.md create mode 100644 archetypes/post.md create mode 100644 redaktion/.gitignore create mode 100644 redaktion/assets/logo-inkscape.svg create mode 100644 redaktion/assets/logo.jpg create mode 100644 redaktion/assets/logo.png create mode 100644 redaktion/assets/logo40-dark.png create mode 100644 redaktion/assets/logo40-t.png create mode 100644 redaktion/assets/logo40.png create mode 100644 redaktion/assets/stravainkscape.svg create mode 100755 redaktion/backup.sh create mode 100755 redaktion/load.sh create mode 100755 redaktion/publish.sh create mode 100644 redaktion/red.py create mode 100644 redaktion/requirements.txt diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/archetypes/post.md b/archetypes/post.md new file mode 100644 index 0000000..32c599e --- /dev/null +++ b/archetypes/post.md @@ -0,0 +1,75 @@ +--- + +# Set the correct title here +title: "2003-11-02" + +# Date of the event, will be set via script. Format like "2003-12-31" +date: 2003-11-02 + +# Set the correct sports kind here (single value) +# It's taxonomy term: look at existing posts, to find the valid values +sports: "MTB" + +# Set the correct event type here (single value) +# It's taxonomy term: look at existing posts, to find the valid values +eventtypes: "single" + +# Set the correct participants here (list values) +# It's taxonomy term: lLook at existing posts, to find the valid values. +# For new participants set "FirstName LastName" +# Unknown names have to be set as "Gast" +members: [ + "Peter", + "Gregor", + "Edmund", + "Gerald", + "Christian" + ] + +# City name of start point +# It's taxonomy term: look at existing posts, to find the valid values +# If it's a new location: Take a simple city name +locations: "Somewhere" + +# false to hide it in production +draft: false + +# If one of the following values are not given, delete the default value +# Set the correct value here, Example 78.3 +distance_km: 0.0 +# Set the correct value here, Example 3:58:59 +duration_h: 0:00:00 +# Set the correct value here, Example 23.2 +average_speed_kmh: 0 +# Set the correct value here, Example 1234 +ascent_m: 0 +# Set the correct value here, Example 24.2 +temperature_c: + +# All image paths are relative paths and have to start with "images/" + +# Image for the post's header e.g. header_image: images/img123.jpg. Can be empty. +header_image: + +# Image for the summary list e.g. featured_image: images/img123.jpg. Can be empty. +featured_image: + +# Set captions for specific images (optional) +# A caption item has two entries: -name: "images/IMAGE_NAME" and -text: "YOUR DESCRIPTION" +# Caption names will be generated by the script, add text or let it empty. +captions: + +# Should not be changed +# Be careful: src value must be unique +resources: + - src: images/** + +# Links to activity on social platforms +# Example velohero_activity: https://app.velohero.com/activity/364363 +# velohero_activity: +# strava_activity: + +--- + + + diff --git a/redaktion/.gitignore b/redaktion/.gitignore new file mode 100644 index 0000000..2c66778 --- /dev/null +++ b/redaktion/.gitignore @@ -0,0 +1,6 @@ +in/ +.idea/ +.settings +.venv/lib/python3.8/site-packages/ +.venv/lib64/python3.8/site-packages/ +.venv diff --git a/redaktion/assets/logo-inkscape.svg b/redaktion/assets/logo-inkscape.svg new file mode 100644 index 0000000..459d784 --- /dev/null +++ b/redaktion/assets/logo-inkscape.svg @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/redaktion/assets/logo.jpg b/redaktion/assets/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fc43bb2ea2b2fd9b2bcef6f0a8a3552b4cd58803 GIT binary patch literal 11547 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 literal 0 HcmV?d00001 diff --git a/redaktion/assets/logo.png b/redaktion/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1039096642b9d95504c82e65b123d79808d34818 GIT binary patch literal 3136 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 Ef?QdTDF6Tf literal 0 HcmV?d00001 diff --git a/redaktion/assets/logo40-t.png b/redaktion/assets/logo40-t.png new file mode 100644 index 0000000000000000000000000000000000000000..db9dcbdf3d45af013827d4de68e634b84c714809 GIT binary patch literal 1610 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 + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/redaktion/backup.sh b/redaktion/backup.sh new file mode 100755 index 0000000..b42cb1a --- /dev/null +++ b/redaktion/backup.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +rsync -avz --delete --exclude kollegenrunde/.git --exclude kollegenrunde/public/ --exclude *swp /home/chris/hugo /media/diskstation/externalAccess/rsyncs diff --git a/redaktion/load.sh b/redaktion/load.sh new file mode 100755 index 0000000..38c6e5f --- /dev/null +++ b/redaktion/load.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +ROOT_DST="/home/chris/hugo/kollegenrunde/redaktion/in/posts" + +# case in-sensitive matching +shopt -s nocaseglob +shopt -s nullglob + +if [ "$1" == '-h' ] + then + echo "Copy all images " + echo " from DIR" + echo " to $ROOT_DST/" + echo "DIR must be a path to a DATE base directory like 2006010213_STAUFEN" + echo "Destination directory will be deleted an recreated" + echo "Usage:" + echo " load DIR" + echo "" + echo " DATE must be an existing directory" + echo " Images will be copied into $ROOT_DST/" + echo " For instance: load /mnt/pict/20200912_STAUFEN" + exit 0 +fi + +if [ -z "$1" ] + then echo "Missing source directory, e. g. call 'load /mnt/pict/20200912_STAUFEN'" + exit 1 +fi + +DIR=$(basename "$1") +#echo dir=$DIR + +DATE=${DIR:0:8} +#echo date=$DATE + +if [ ! -e "$1" ] + then echo "Directory '$1' not found !" + exit 1 +fi + +if [ ! -e $ROOT_DST ] + then echo "Destination root directory '$ROOT_DST' not found !" + exit 1 +fi + +DST="$ROOT_DST/$DATE" + +if [ ! -e $DST ] + then echo "Create $DST" + mkdir "$DST" +fi + +echo "Processing $DATE..." + +if [ -e "$DST" ] + then + echo "Delete $DST" + rm -r "$DST" +fi + +echo "Create $DST" +mkdir "$DST" + +# It's tricky to copy dirs with whitespaces +shopt -s extglob # turn on extended globbing +SAVEIFS=$IFS +IFS=$(echo -en "\n\b") +for f in $1?(*.jpg|*.jpeg|*.png) +do + echo "$f" + cp -v "$f" "$DST"/ +done +IFS=$SAVEIFS + + + + diff --git a/redaktion/publish.sh b/redaktion/publish.sh new file mode 100755 index 0000000..1c4068f --- /dev/null +++ b/redaktion/publish.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +echo Publish to Uberspace... + +rsync -avv --delete /home/chris/hugo/kollegenrunde/public/ kollegen@despina.uberspace.de:html/kollegenrunde diff --git a/redaktion/red.py b/redaktion/red.py new file mode 100644 index 0000000..2e25e8e --- /dev/null +++ b/redaktion/red.py @@ -0,0 +1,597 @@ +import argparse +import re +import json +import sys +from os import path, mkdir, remove, listdir +from shutil import copyfile, rmtree +from PIL import Image + +import yaml + +try: + from yaml import CLoader as Loader, CDumper as Dumper +except ImportError: + from yaml import Loader, Dumper + +args = None +log_switch = False + +post_file_name = "index.md" +post_file_backup_name = "~index.md" +post_file_archetype = path.join("..", "archetypes", "post.md") +settings_path = ".settings" + + +def execute_info(): + + if not path.exists(settings_path): + print("No actual post.") + return + + print(f"Actual post is: '{settings_get_date()}'") + + exit_invalid_initialization() + + +def execute_update(): + exit_invalid_initialization() + + yml = yaml.load(get_frontmatters(), Loader=Loader) + + previous_images = settings_get_images() + + convert(get_image_path(yml)) + + remove_previous_images(previous_images, yml) + + yml = cleanup_zombies(yml) + + yml = merge_images(yml) + + update_frontmatters(yml) + + print("Done.") + + +def remove_previous_images(previous_images, yml): + converted_images = settings_get_images() + + for image in [i for i in previous_images if i not in converted_images]: + image_path = path.join(get_image_path(yml), image) + log(f"Removing previous image '{image}'") + remove(image_path) + + +def init_date(): + + yml = yaml.load(get_frontmatters(), Loader=Loader) + + yml = set_date(yml) + + lines = get_frontmatters() + + lines = update_date(yml, lines) + + content = get_content() + with open(get_post_file_path(), "w") as f: + f.write("---\n") + f.write(lines) + f.write("---\n") + f.write(content) + + +def init_title(): + + yml = yaml.load(get_frontmatters(), Loader=Loader) + + yml = set_title(yml) + + lines = get_frontmatters() + + lines = update_title(yml, lines) + + content = get_content() + with open(get_post_file_path(), "w") as f: + f.write("---\n") + f.write(lines) + f.write("---\n") + f.write(content) + + +def update_frontmatters(yml): + copyfile(get_post_file_path(), get_post_backup_file_path()) + + lines = get_frontmatters() + + lines = update_title(yml, lines) + lines = update_date(yml, lines) + lines = update_header_image(yml, lines) + lines = update_featured_image(yml, lines) + lines = update_captions(yml, lines) + + content = get_content() + with open(get_post_file_path(), "w") as f: + f.write("---\n") + f.write(lines) + f.write("---\n") + f.write(content) + + +def set_title(yml): + yml['title'] = "Tour " + settings_get_date()[0:4] + "-" + settings_get_date()[4:6] + "-" + settings_get_date()[6:8] + + return yml + + +def set_date(yml): + yml['date'] = settings_get_date()[0:4] + "-" + settings_get_date()[4:6] + "-" + settings_get_date()[6:8] + + return yml + + +def get_image_path(yml): + return path.join(get_out_path(), get_image_resource_path(yml)) + + +def get_image_resource_path(yml): + items = [i for i in yml['resources'] if 'src' in i] + + ret = "" + + if len(items) > 0: + path = items[0]['src'] + # Should never happens + else: + path = '' + + + reg = re.match("(.*)/\*\*", path) + if reg is not None and len(reg.groups()) >= 1: + ret = reg.group(1) + + # log(f"get_image_path={ret}") + + return ret + + +def merge_images(yml): + files = get_image_resources(yml) + + if len(files) == 0: + return yml + + key = 'header_image' + if key in yml and yml[key] is None: + yml[key] = files[0] + + key = 'featured_image' + if key in yml and yml[key] is None: + yml[key] = files[0] + + # log(f"merge_images {yml}") + + key = 'captions' + key2 = 'name' + if key in yml: + if yml[key] is None: + yml[key] = [] + for file in files: + hit = False + for item in yml[key]: + if key2 in item and item[key2] == file: + hit = True + break + if not hit: + # log(f"merge_images added {file}") + yml[key].append(dict(name=file, text="")) + + yml[key] = sorted(yml[key], key=lambda k: k['name']) + + # log(f"merge_images {yml}") + return yml + + +def cleanup_zombies(yml): + files = get_image_resources(yml) + + key = 'header_image' + if key in yml: + if yml[key] is not None and not yml[key] in files: + yml[key] = "" + else: + yml[key] = "" + + key = 'featured_image' + if key in yml: + if yml[key] is not None and not yml[key] in files: + yml[key] = "" + else: + yml[key] = "" + + # log(f"cleanup_zombies={yml}") + + key = 'captions' + if key in yml: + if yml[key] is not None: + key2 = 'name' + # log(f"cleanup_zombies={yml[key]}") + items = yml[key].copy() + for item in items: + if not item[key2] in files: + # log(f"cleanup_zombies remove item {item[key2]} ") + yml[key].remove(item) + else: + yml[key] = [] + + # log(f"cleanup_zombies ret = {yml}") + return yml + + +def get_image_resources(yml): + files = get_images(get_image_path(yml)) + sub = get_image_resource_path(yml) + + ret = [] + for name in files: + ret.append(path.join(sub, name)) + + return ret + + +def get_images(dir): + ret = [f for f in listdir(dir) if f.lower().endswith(".jpg") + or f.lower().endswith(".jpeg") or f.lower().endswith(".png")] + + ret.sort() + + return ret + + +def convert(image_path): + names = [] + for f in get_images(get_in_path()): + + in_path = path.join(get_in_path(), f) + out_path = path.join(image_path, f) + + log(f"Converting '{in_path}' to '{out_path}'") + + im = Image.open(in_path) + + if im.width <= 1200 and im.height <= 1200: + copyfile(in_path, out_path) + continue + + if im.width > im.height: + new_image = im.resize((1200, round(1200*im.height/im.width))) + else: + new_image = im.resize((round(1200*im.width/im.height), 1200)) + + if 'exif' in im.info: + new_image.save(out_path, exif=im.info['exif'], quality=80) + else: + new_image.save(out_path, quality=80) + + + names.append(f) + + settings_save_images(names) + + +def update_date(yml, lines): + return re.sub("\ndate:.*\n", f"\ndate: {yml['date']}\n",lines) + + +def update_featured_image(yml, lines): + return re.sub("\nfeatured_image:.*\n", f"\nfeatured_image: {yml['featured_image']}\n",lines) + + +def update_header_image(yml, lines): + return re.sub("\nheader_image:.*\n", f"\nheader_image: {yml['header_image']}\n",lines) + + +def update_captions(yml, lines): + data = yml['captions'] + + lines = clear_captions(lines) + # log(f"update_captions lines={lines}") + + if data is None: + output = "" + else: + output = yaml.dump(data, Dumper=Dumper) + + # log(f"update_captions output={output}") + lines = re.sub("\ncaptions:.*\n", f"\ncaptions:\n{output}", lines) + + # log(f"update_captions {lines}") + return lines + + +def clear_captions(lines): + arr = lines.split('\n') + captions = False + arr2 = [] + + for item in arr: + if item.startswith("captions:"): + captions = True + arr2.append(item) + continue + + if captions: + if len(item.strip()) == 0: + captions = False + arr2.append(item) + + else: + arr2.append(item) + + ret = "" + for item in arr2: + if len(ret) == 0: + ret = item + else: + ret = ret + '\n' + item + + return ret + + +def update_title(yml, lines): + return re.sub("\ntitle:.*\n", f"\ntitle: \"{yml['title']}\"\n",lines) + + +def get_content(): + lines = "" + + # log(f"get_content get_post_file_path={get_post_file_path()}") + pattern = re.compile("^---$") + cnt = 0 + + with open(get_post_file_path(), "r") as f: + # log(f"get_content with f={f}") + + for line in f: + # log(f"get_content {line}") + + if pattern.match(line): + cnt += 1 + continue + + if cnt < 2: + continue + + lines = lines + line + + # log(f"get_content return={lines}") + return lines + + +def get_frontmatters(): + lines = "" + with open(get_post_file_path(), "r") as f: + # log("open") + pattern = re.compile("^---$") + cnt = 0 + + for line in f: + # log(line) + if pattern.match(line): + cnt += 1 + # log(f"a: {cnt}") + continue + + if cnt == 0: + # log(f"b: {cnt}") + continue + + if cnt == 2: + # log(f"c: {cnt}") + break + + # log(line) + lines = lines + line + + return lines + + +def execute_cleanup(): + + if path.exists(settings_path): + date = settings_get_date() + else: + print("Not initialized: nothing to do.") + return + + if path.exists(get_in_path()): + rmtree(get_in_path()) + print(f"Removed '{get_in_path()}'") + + remove(settings_path) + + print(f"{date} closed.") + + +def settings_get_date(): + with open(settings_path) as f: + settings = json.load(f) + return settings['date'] + + +def settings_get_images(): + with open(settings_path) as f: + settings = json.load(f) + return settings['images'] + + +def settings_init(date): + with open(settings_path, 'w') as f: + json.dump(dict(date=date, images=[]), f) + + +def settings_save_images(images): + + date = settings_get_date() + + with open(settings_path, 'w') as f: + json.dump(dict(date=date, images=images), f) + + +def execute_init(): + + # date must match YYYYMMDD pattern + pattern = re.compile("^\d{8}$") + + if not pattern.match(args.date): + exit_on_error("Wrong date format, must be ") + + settings_init(args.date) + + # ### in #### + if path.exists(get_in_path()): + print(f"Existing in path found. Put your original images here: '{get_in_path()}'") + else: + mkdir(get_in_path()) + print(f"Post directory created. Put your original images here: '{get_in_path()}'") + + # ### post dir #### + if path.exists(get_out_path()): + if args.clean: + rmtree(get_out_path()) + mkdir(get_out_path()) + print(f"Existing post directory cleaned: '{get_out_path()}'") + else: + print(f"Existing post directory found: '{get_out_path()}'") + else: + mkdir(get_out_path()) + print(f"Post' directory created: '{get_out_path()}' ") + + # ### post file #### + if path.exists(get_post_file_path()): + print(f"Existing post file found: '{get_post_file_path()}'") + else: + copyfile(post_file_archetype, get_post_file_path()) + init_title() + print(f"New post file created: '{get_post_file_path()}'") + + yml = yaml.load(get_frontmatters(), Loader=Loader) + image_path = get_image_path(yml) + if not path.exists(image_path): + mkdir(image_path) + print(f"Image directory created: '{get_image_resource_path(yml)}' ") + + init_date() + + print(f"The next step would be to add your images into the '{get_in_path()}' directory. " + f"After that you can update the post directory '{get_out_path()}' and the post file '{post_file_name}': " + f"call 'update'.") + + +def get_post_file_path(): + return path.join(get_out_path(), post_file_name) + + +def get_post_backup_file_path(): + return path.join(get_out_path(), post_file_backup_name) + + +def get_in_path(): + with open('.settings') as f: + settings = json.load(f) + return path.join("in", "posts", settings['date']) + + +def log(message): + """ + Only switched on for development + """ + if log_switch: + print(message) + + +def exit_invalid_initialization(): + if not path.exists(settings_path): + exit_on_error("Editorial seems not to be initialized.") + + if not path.exists(get_in_path()): + exit_on_error(f"Invalid in path: '{get_in_path()}'.") + + if not path.exists(get_out_path()): + exit_on_error(f"Invalid post path: '{get_out_path()}'.") + + if not path.exists(get_post_file_path()): + exit_on_error(f"No post file found: '{get_post_file_path()}'.") + + +def get_out_path(): + with open(settings_path) as f: + settings = json.load(f) + return path.join("..", "content", "posts", settings['date']) + + +def parse_args(): + + global args + + parser = argparse.ArgumentParser(description='Bring your content into the Hugo blog') + + parser.add_argument("-v", "--verbose", + action='store_true', + help="Print more info") + + sub_parsers = parser.add_subparsers() + + # ######### init ######### + init_parser = sub_parsers.add_parser('init', + help="Setup a new post or edit an existing one", + description="" + ) + init_parser.add_argument('date', metavar='DATE', type=str, + help="Date of the post as , example: 'init 20201231'") + + init_parser.add_argument('--clean', action="store_true", + help="Removes existing post content, if exists." + "Be careful with this option! Particularly, if there are multiple editors working " + "on this blog." + ) + + init_parser.set_defaults(func=execute_init) + + # ######### update ######### + update_parser = sub_parsers.add_parser('update', + help="Converts images into a proper size and update the post file", + description="Images must be in in/post/" + ) + + update_parser.set_defaults(func=execute_update) + + # ######### cleanup ######### + cleanup_parser = sub_parsers.add_parser('cleanup', + help=f"cleanup editorial by clean up the in directory", + description=f"Removes in directory (with your original images). " + ) + + cleanup_parser.set_defaults(func=execute_cleanup) + + args = parser.parse_args() + + if args.verbose: + set_log_switch(True) + + if len(sys.argv) > 1: + args.func() + else: + execute_info() + +def set_log_switch(value): + global log_switch + log_switch = value + + +def exit_on_error(message): + print(message) + exit(1) + + +if __name__ == '__main__': + parse_args() \ No newline at end of file diff --git a/redaktion/requirements.txt b/redaktion/requirements.txt new file mode 100644 index 0000000..e3af201 --- /dev/null +++ b/redaktion/requirements.txt @@ -0,0 +1,2 @@ +Pillow==7.2.0 +PyYAML==5.3.1