diff --git a/README.md b/README.md index 695ff4c..fafaecd 100644 --- a/README.md +++ b/README.md @@ -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 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. @@ -25,6 +35,7 @@ Copy the posting script to e.g. `/usr/local/bin/wordpress-post` so that you can * Done! ### 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`. * `--publish` — shortcut for `STATUS=publish`, posts live immediately. * `--edit POST_ID` — update an existing post instead of creating a new one. diff --git a/config.sh.template b/config.sh.template index 1909f3f..d0e5e54 100755 --- a/config.sh.template +++ b/config.sh.template @@ -1,4 +1,8 @@ #!/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 TRANSFORM=('title' 'markdown') # empty or a subset of: 'title' 'markdown' USER="" # WP user to create the post diff --git a/post.sh b/post.sh index e7009b8..b6b7744 100755 --- a/post.sh +++ b/post.sh @@ -11,21 +11,28 @@ 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}" -source ~/.config/wordpress-rest-curl/config.sh - -# CLI options (override config): +# 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) - STATUS="publish"; shift ;; + PUBLISH=1; shift ;; --file) SOURCE_FILE="$2"; shift 2 ;; *) @@ -34,6 +41,20 @@ while [[ $# -gt 0 ]]; do 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 diff --git a/site.sh.template b/site.sh.template new file mode 100644 index 0000000..6bd11f8 --- /dev/null +++ b/site.sh.template @@ -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 diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 152aa52..824b52e 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -34,6 +34,13 @@ SERVER="http://127.0.0.1:$PORT" CATEGORIES="3,7" TAGS="10" 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" < "$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: 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 --- 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"