153 lines
4.7 KiB
Bash
Executable File
153 lines
4.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# WordPress posting script
|
|
|
|
# config:
|
|
EDITOR=vim
|
|
TRANSFORM=() # empty or a subset of: 'title' 'markdown'
|
|
USER="" # WP user to create the post
|
|
PASSWORD="" # application password generated for your WP user
|
|
SERVER="" # server hostname, optionally with subdirectories
|
|
STATUS="draft" # one of publish,future,draft,pending,private
|
|
CATEGORIES="" # comma separated integer IDs of categories
|
|
TAGS="" # comma separated integer IDs of tags
|
|
TMPFILE=/tmp/wordpress-post.txt # location of a temporary file with the post text
|
|
CONFIG_DIR="${WORDPRESS_REST_CURL_CONFIG_DIR:-$HOME/.config/wordpress-rest-curl}"
|
|
|
|
# CLI options:
|
|
# --site NAME after config.sh, also source $CONFIG_DIR/NAME.sh, whose
|
|
# values override config.sh's (lets you keep just the
|
|
# per-instance bits — USER/PASSWORD/SERVER — in each site
|
|
# file, and shared defaults in config.sh)
|
|
# --edit POST_ID update an existing post instead of creating a new one
|
|
# --publish shortcut for STATUS=publish
|
|
# --file PATH use PATH as the post source instead of opening $EDITOR
|
|
SITE=""
|
|
POST_ID=""
|
|
SOURCE_FILE=""
|
|
PUBLISH=0
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--site)
|
|
SITE="$2"; shift 2 ;;
|
|
--edit)
|
|
POST_ID="$2"; shift 2 ;;
|
|
--publish)
|
|
PUBLISH=1; shift ;;
|
|
--file)
|
|
SOURCE_FILE="$2"; shift 2 ;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2
|
|
exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
DEFAULT_CONFIG_FILE="$CONFIG_DIR/config.sh"
|
|
[[ -e "$DEFAULT_CONFIG_FILE" ]] && source "$DEFAULT_CONFIG_FILE"
|
|
|
|
if [[ -n "$SITE" ]]; then
|
|
SITE_CONFIG_FILE="$CONFIG_DIR/$SITE.sh"
|
|
[[ -e "$SITE_CONFIG_FILE" ]] || { echo "Config file not found: $SITE_CONFIG_FILE" >&2; exit 1; }
|
|
source "$SITE_CONFIG_FILE"
|
|
elif [[ ! -e "$DEFAULT_CONFIG_FILE" ]]; then
|
|
echo "No site specified and no default config found. Pass --site NAME or create $DEFAULT_CONFIG_FILE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
[[ "$PUBLISH" -eq 1 ]] && STATUS="publish"
|
|
|
|
# let the user provide the post content
|
|
if [[ -n "$SOURCE_FILE" ]]; then
|
|
cp "$SOURCE_FILE" "$TMPFILE" || exit 1
|
|
else
|
|
$EDITOR $TMPFILE || exit 1
|
|
fi
|
|
[[ -e $TMPFILE ]] || exit 1
|
|
|
|
# transformations
|
|
cp $TMPFILE $TMPFILE.trans
|
|
for T in "${TRANSFORM[@]}"; do
|
|
if [[ "$T" == "title" ]]; then
|
|
python3 >$TMPFILE.trans2 <<EOF
|
|
import re
|
|
with open('$TMPFILE.trans', 'r') as file:
|
|
title = ''
|
|
content = file.read()
|
|
matches = re.match('^#+ (.+)', content, flags=0)
|
|
if matches:
|
|
title = matches.group(1)
|
|
content = content[len(matches.group(0)) + 1:]
|
|
with open('$TMPFILE.title', 'w') as titlefile:
|
|
titlefile.write(title)
|
|
print(content)
|
|
EOF
|
|
TITLE=`cat $TMPFILE.title`
|
|
rm $TMPFILE.title
|
|
mv $TMPFILE.trans2 $TMPFILE.trans
|
|
elif [[ "$T" == "markdown" ]]; then
|
|
python3 >$TMPFILE.trans2 <<EOF
|
|
import markdown2
|
|
print(markdown2.markdown_path('$TMPFILE.trans'))
|
|
EOF
|
|
mv $TMPFILE.trans2 $TMPFILE.trans
|
|
fi
|
|
done
|
|
CONTENT=`cat $TMPFILE.trans`
|
|
rm $TMPFILE.trans
|
|
|
|
echo "--- START POST ---"
|
|
echo "$CONTENT"
|
|
echo "--- END POST ---"
|
|
echo "Title: $TITLE"
|
|
echo "User: $USER"
|
|
echo "Server: $SERVER"
|
|
echo "Status: $STATUS"
|
|
echo "Categories: $CATEGORIES"
|
|
echo "Tags: $TAGS"
|
|
if [[ -n "$POST_ID" ]]; then
|
|
echo "Editing post: $POST_ID"
|
|
fi
|
|
echo
|
|
read -p "Press enter to confirm..."
|
|
|
|
# build the JSON payload (categories/tags as real arrays, not comma strings)
|
|
CATEGORIES_JSON="[]"
|
|
if [[ -n "$CATEGORIES" ]]; then
|
|
CATEGORIES_JSON=$(echo "$CATEGORIES" | tr ',' '\n' | jq -R 'select(length > 0) | tonumber' | jq -s '.')
|
|
fi
|
|
TAGS_JSON="[]"
|
|
if [[ -n "$TAGS" ]]; then
|
|
TAGS_JSON=$(echo "$TAGS" | tr ',' '\n' | jq -R 'select(length > 0) | tonumber' | jq -s '.')
|
|
fi
|
|
|
|
PAYLOAD=$(jq -n \
|
|
--arg title "$TITLE" \
|
|
--arg content "$CONTENT" \
|
|
--arg status "$STATUS" \
|
|
--argjson categories "$CATEGORIES_JSON" \
|
|
--argjson tags "$TAGS_JSON" \
|
|
'{title: $title, content: $content, status: $status, categories: $categories, tags: $tags}')
|
|
|
|
BASE_URL="$SERVER"
|
|
[[ "$BASE_URL" != http://* && "$BASE_URL" != https://* ]] && BASE_URL="https://$BASE_URL"
|
|
URL="$BASE_URL/wp-json/wp/v2/posts/"
|
|
[[ -n "$POST_ID" ]] && URL="$BASE_URL/wp-json/wp/v2/posts/$POST_ID"
|
|
|
|
# push the post!
|
|
RESPONSE=$(curl --silent --show-error --user "$USER:$PASSWORD" -X POST \
|
|
-H "Content-Type: application/json" \
|
|
--data "$PAYLOAD" \
|
|
-w '\n%{http_code}' \
|
|
"$URL")
|
|
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
|
|
if [[ "$HTTP_CODE" -lt 200 || "$HTTP_CODE" -ge 300 ]]; then
|
|
echo "Error: WordPress API returned HTTP $HTTP_CODE" >&2
|
|
echo "$BODY" >&2
|
|
exit 1
|
|
fi
|
|
echo "$BODY"
|
|
|
|
# backup the posted data (temporarily until it is auto-removed)
|
|
mv $TMPFILE $TMPFILE.posted
|