Add site selection and config override

This commit is contained in:
Dejvino 2026-07-30 17:55:58 +02:00
parent 160388194a
commit 8d1488f354
5 changed files with 78 additions and 5 deletions

View File

@ -14,7 +14,17 @@ Make sure you have `curl` and `jq` installed. If you want to enter text in
markdown format, install `python-markdown2` (`pip install markdown2` or your markdown format, install `python-markdown2` (`pip install markdown2` or your
distro's `python3-markdown2` package). distro's `python3-markdown2` package).
Create a config file `~/.config/wordpress-rest-curl/config.sh` from the `config.sh.template` file. Copy `config.sh.template` to `~/.config/wordpress-rest-curl/config.sh` and
fill in whatever's shared across sites (`TRANSFORM`, `EDITOR`, `STATUS`, ...).
`config.sh` is always loaded first if it exists — it doesn't need `USER`,
`PASSWORD`, or `SERVER` filled in.
If you post to more than one WordPress instance, copy `site.sh.template` to
`~/.config/wordpress-rest-curl/NAME.sh` once per site, e.g.
`blog-example-com.sh` and `news-example-com.sh`, containing just the per-instance bits
(`USER`, `PASSWORD`, `SERVER`, and any `CATEGORIES`/`TAGS` that differ). Pick
one at run time with `--site NAME` (see Options below) — its values are
layered on top of `config.sh`, overriding only what it sets.
Copy the posting script to e.g. `/usr/local/bin/wordpress-post` so that you can run it from anywhere. Copy the posting script to e.g. `/usr/local/bin/wordpress-post` so that you can run it from anywhere.
@ -25,6 +35,7 @@ Copy the posting script to e.g. `/usr/local/bin/wordpress-post` so that you can
* Done! * Done!
### Options ### Options
* `--site NAME` — use `~/.config/wordpress-rest-curl/NAME.sh` instead of the default `config.sh`. Useful when posting to multiple WordPress instances with different credentials.
* `--file PATH` — use PATH as the post content instead of opening `$EDITOR`. * `--file PATH` — use PATH as the post content instead of opening `$EDITOR`.
* `--publish` — shortcut for `STATUS=publish`, posts live immediately. * `--publish` — shortcut for `STATUS=publish`, posts live immediately.
* `--edit POST_ID` — update an existing post instead of creating a new one. * `--edit POST_ID` — update an existing post instead of creating a new one.

View File

@ -1,4 +1,8 @@
#!/bin/bash #!/bin/bash
# Shared defaults, loaded before any --site NAME file. If you only ever post
# to one WordPress instance, fill in USER/PASSWORD/SERVER here too and skip
# --site entirely. If you post to more than one, leave those three blank
# here and put them in per-site files instead (see README).
EDITOR=vim EDITOR=vim
TRANSFORM=('title' 'markdown') # empty or a subset of: 'title' 'markdown' TRANSFORM=('title' 'markdown') # empty or a subset of: 'title' 'markdown'
USER="" # WP user to create the post USER="" # WP user to create the post

29
post.sh
View File

@ -11,21 +11,28 @@ STATUS="draft" # one of publish,future,draft,pending,private
CATEGORIES="" # comma separated integer IDs of categories CATEGORIES="" # comma separated integer IDs of categories
TAGS="" # comma separated integer IDs of tags TAGS="" # comma separated integer IDs of tags
TMPFILE=/tmp/wordpress-post.txt # location of a temporary file with the post text 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}"
source ~/.config/wordpress-rest-curl/config.sh # CLI options:
# --site NAME after config.sh, also source $CONFIG_DIR/NAME.sh, whose
# CLI options (override config): # 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 # --edit POST_ID update an existing post instead of creating a new one
# --publish shortcut for STATUS=publish # --publish shortcut for STATUS=publish
# --file PATH use PATH as the post source instead of opening $EDITOR # --file PATH use PATH as the post source instead of opening $EDITOR
SITE=""
POST_ID="" POST_ID=""
SOURCE_FILE="" SOURCE_FILE=""
PUBLISH=0
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--site)
SITE="$2"; shift 2 ;;
--edit) --edit)
POST_ID="$2"; shift 2 ;; POST_ID="$2"; shift 2 ;;
--publish) --publish)
STATUS="publish"; shift ;; PUBLISH=1; shift ;;
--file) --file)
SOURCE_FILE="$2"; shift 2 ;; SOURCE_FILE="$2"; shift 2 ;;
*) *)
@ -34,6 +41,20 @@ while [[ $# -gt 0 ]]; do
esac esac
done 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 # let the user provide the post content
if [[ -n "$SOURCE_FILE" ]]; then if [[ -n "$SOURCE_FILE" ]]; then
cp "$SOURCE_FILE" "$TMPFILE" || exit 1 cp "$SOURCE_FILE" "$TMPFILE" || exit 1

9
site.sh.template Normal file
View File

@ -0,0 +1,9 @@
#!/bin/bash
# Per-site overrides, loaded after config.sh when running with --site NAME.
# Copy to ~/.config/wordpress-rest-curl/NAME.sh and fill in. Only set what
# differs from config.sh -- anything left out here falls back to config.sh.
USER="" # WP user to create the post
PASSWORD="" # application password generated for your WP user
SERVER="" # server hostname, optionally with subdirectories
CATEGORIES="" # comma separated integer IDs of categories
TAGS="" # comma separated integer IDs of tags

View File

@ -34,6 +34,13 @@ SERVER="http://127.0.0.1:$PORT"
CATEGORIES="3,7" CATEGORIES="3,7"
TAGS="10" TAGS="10"
EOF EOF
# Deliberately sparse: only the fields that differ from config.sh, to prove
# --site layers on top of the default config rather than replacing it.
cat > "$HOME/.config/wordpress-rest-curl/othersite.sh" <<EOF
USER="other-tester"
PASSWORD="other-pass"
CATEGORIES="1"
EOF
POST_FILE="$WORKDIR/post.md" POST_FILE="$WORKDIR/post.md"
cat > "$POST_FILE" <<'EOF2' cat > "$POST_FILE" <<'EOF2'
@ -77,6 +84,27 @@ REQ=$(cat "$MOCK_WP_REQUEST_FILE")
assert_eq "edit: path includes post ID" "/wp-json/wp/v2/posts/99" "$(jq -r '.path' <<<"$REQ")" assert_eq "edit: path includes post ID" "/wp-json/wp/v2/posts/99" "$(jq -r '.path' <<<"$REQ")"
assert_eq "edit: status defaults to draft" "draft" "$(jq -r '.payload.status' <<<"$REQ")" assert_eq "edit: status defaults to draft" "draft" "$(jq -r '.payload.status' <<<"$REQ")"
# --- --site layers on top of config.sh: overrides what it sets, inherits the rest ---
rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE"
run_post_sh --site othersite --file "$POST_FILE" >/dev/null
assert_eq "site: exit code" "0" "$?"
REQ=$(cat "$MOCK_WP_REQUEST_FILE")
assert_eq "site: categories overridden by site config" "[1]" "$(jq -c '.payload.categories' <<<"$REQ")"
assert_eq "site: tags inherited from default config" "[10]" "$(jq -c '.payload.tags' <<<"$REQ")"
assert_eq "site: title transform inherited from default config" "My Test Title" "$(jq -r '.payload.title' <<<"$REQ")"
rm -f "$MOCK_WP_REQUEST_FILE" "$MOCK_WP_CONTROL_FILE"
OUT=$(run_post_sh --site does-not-exist --file "$POST_FILE" 2>&1)
assert_eq "site: unknown site exits non-zero" "1" "$?"
assert_eq "site: unknown site error message" "true" "$(grep -q "Config file not found" <<<"$OUT" && echo true || echo false)"
# --- no --site and no default config.sh: clean error, not a crash ---
mv "$HOME/.config/wordpress-rest-curl/config.sh" "$WORKDIR/config.sh.bak"
OUT=$(run_post_sh --file "$POST_FILE" 2>&1)
assert_eq "no config: exits non-zero" "1" "$?"
assert_eq "no config: error message" "true" "$(grep -q "No site specified and no default config found" <<<"$OUT" && echo true || echo false)"
mv "$WORKDIR/config.sh.bak" "$HOME/.config/wordpress-rest-curl/config.sh"
# --- non-2xx response is surfaced and script exits non-zero --- # --- non-2xx response is surfaced and script exits non-zero ---
rm -f "$MOCK_WP_REQUEST_FILE" rm -f "$MOCK_WP_REQUEST_FILE"
echo '{"status": 401, "body": {"code": "rest_forbidden", "message": "Sorry, you are not allowed to do that."}}' > "$MOCK_WP_CONTROL_FILE" echo '{"status": 401, "body": {"code": "rest_forbidden", "message": "Sorry, you are not allowed to do that."}}' > "$MOCK_WP_CONTROL_FILE"