#!/usr/bin/env bash set -Eeuo pipefail PROFILE="/joplin-profile" CONFIG="/app/config.yaml" RESULT_JSON="/app/data/last_result.json" log() { printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"; } fail() { log "ERROR: $*"; exit 1; } : "${JOPLIN_WEBDAV_URL:?JOPLIN_WEBDAV_URL is required}" : "${JOPLIN_WEBDAV_USERNAME:?JOPLIN_WEBDAV_USERNAME is required}" : "${JOPLIN_WEBDAV_PASSWORD:?JOPLIN_WEBDAV_PASSWORD is required}" JOPLIN_NOTEBOOK="${JOPLIN_NOTEBOOK:-Radar Papers}" JOPLIN_WRITE_ENABLED="${JOPLIN_WRITE_ENABLED:-false}" JOPLIN_IGNORE_TLS_ERRORS="${JOPLIN_IGNORE_TLS_ERRORS:-false}" mkdir -p "$PROFILE" /app/data/outbox log "Configuring Joplin CLI WebDAV profile..." joplin --profile "$PROFILE" config sync.target 6 >/dev/null joplin --profile "$PROFILE" config sync.6.path "$JOPLIN_WEBDAV_URL" >/dev/null joplin --profile "$PROFILE" config sync.6.username "$JOPLIN_WEBDAV_USERNAME" >/dev/null joplin --profile "$PROFILE" config sync.6.password "$JOPLIN_WEBDAV_PASSWORD" >/dev/null joplin --profile "$PROFILE" config sync.wipeOutFailSafe true >/dev/null if [[ "${JOPLIN_IGNORE_TLS_ERRORS,,}" == "true" ]]; then joplin --profile "$PROFILE" config net.ignoreTlsErrors true >/dev/null else joplin --profile "$PROFILE" config net.ignoreTlsErrors false >/dev/null fi # Pull the current remote state first. This is important when PC/mobile also use the same WebDAV target. log "Synchronising Joplin from WebDAV before writing..." joplin --profile "$PROFILE" sync if [[ "${JOPLIN_WRITE_ENABLED,,}" != "true" ]]; then log "JOPLIN_WRITE_ENABLED=false: sync-only safety mode. No paper note will be written." log "If this first sync succeeded, set JOPLIN_WRITE_ENABLED=true and run again." exit 0 fi log "Running paper monitor..." python -m paper_monitor --config "$CONFIG" --dry-run [[ -f "$RESULT_JSON" ]] || fail "Result JSON not produced: $RESULT_JSON" readarray -t META < <(python - "$RESULT_JSON" <<'PY' import json, sys p=sys.argv[1] d=json.load(open(p,encoding='utf-8')) print(d.get('report_count',0)) print(d.get('report_title','')) print(d.get('markdown','')) PY ) REPORT_COUNT="${META[0]:-0}" REPORT_TITLE="${META[1]:-}" MARKDOWN="${META[2]:-}" if [[ "$REPORT_COUNT" == "0" ]]; then log "No papers in today's report. Nothing to write to Joplin." exit 0 fi [[ -n "$REPORT_TITLE" ]] || fail "Empty report title" [[ -f "$MARKDOWN" ]] || fail "Markdown report not found: $MARKDOWN" log "Ensuring notebook exists: $JOPLIN_NOTEBOOK" if ! joplin --profile "$PROFILE" use "$JOPLIN_NOTEBOOK" >/dev/null 2>&1; then joplin --profile "$PROFILE" mkbook "$JOPLIN_NOTEBOOK" fi # Replace only the daily report with the exact same title. Since the report is cumulative # for the local day, rerunning is idempotent and will not lose earlier papers from the same day. log "Replacing existing daily note if present: $REPORT_TITLE" joplin --profile "$PROFILE" rmnote "$REPORT_TITLE" -f >/dev/null 2>&1 || true TMP_DIR="$(mktemp -d)" trap 'rm -rf "$TMP_DIR"' EXIT TMP_MD="$TMP_DIR/$REPORT_TITLE.md" cp "$MARKDOWN" "$TMP_MD" log "Importing report into Joplin notebook: $JOPLIN_NOTEBOOK" joplin --profile "$PROFILE" import "$TMP_MD" "$JOPLIN_NOTEBOOK" --format md -f log "Synchronising Joplin changes to WebDAV..." joplin --profile "$PROFILE" sync log "Completed: $REPORT_TITLE ($REPORT_COUNT papers)"