#!/bin/bash

## Copyright (C) 2025 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

set -o errexit
set -o nounset
set -o errtrace
set -o pipefail
shopt -s inherit_errexit
shopt -s shift_verbose

# shellcheck source=../share/mediawiki-shell/common
source /usr/share/mediawiki-shell/common

usage() {
  printf '%s\n' "Usage: ${0##*/} [--dry-run] WIKI INPUT PAGE_FILE [EDIT_MSG]
Options:
  --dry-run        Preview only; skip the actual upload on the server.
Defaults:
  EDIT_MSG=${default_edit_msg}
Example:
  ${0##*/} 'https://www.kicksecure.com/w' /tmp/a File:Search-engine-clipart.jpg
  ${0##*/} 'https://www.kicksecure.com/w' /tmp/a File:Search-engine-clipart.jpg 'custom message'" >&2
  exit 1
}

default_edit_msg="mediawiki-shell-bot-default-upload-message"

while true; do
  case "${1-}" in
    --dry-run)
      export DRY_RUN="true"
      shift
      ;;
    -h|--help)
      usage
      ;;
    --)
      shift
      break
      ;;
    -*)
      die 2 "Invalid option: '$1'"
      ;;
    *)
      break
      ;;
  esac
done

if [ -z "${3-}" ]; then
  usage
fi

WIKI_URL="$1"
new_file="$2"
page_file="$3"
edit_msg="${4-"${default_edit_msg}"}"

check_vars_exist new_file page_file

## Defense-in-depth: check page_file for malicious unicode before
## sending it to the wiki API as the upload filename.
printf '%s\n' "$page_file" | unicode-show

# shellcheck source=../share/mediawiki-shell/wiki-config
source /usr/share/mediawiki-shell/wiki-config

log info "WIKI_URL             : $WIKI_URL"
log info "new_file             : $new_file"
log info "page_file            : $page_file"

if [ -d "$new_file" ]; then
  die 1 "new_file '$new_file' is a folder!"
fi

if [ ! -r "$new_file" ]; then
  die 2 "Local file '$new_file' does not exist or is not readable!"
fi

if [ ! -s "$new_file" ]; then
  log info "Local file '$new_file' was empty."
  exit 0
fi

log info "Uploading file '${WIKI_URL}' '$new_file'..."

mw-login-test "$WIKI_URL"

curl_run \
  "${curl_opts[@]}" \
  --cookie "$cookie_jar" \
  --cookie-jar "$cookie_jar" \
  --header "Accept-Language: en-GB" \
  --header "Connection: keep-alive" \
  --compressed \
  --output "${TMPFOLDER}/fetch-edit-token.json" \
  --request "GET" \
  "${WIKI_API}?action=query&meta=tokens&format=json"

csrf_token=$(jq --raw-output '.query.tokens.csrftoken' -- "${TMPFOLDER}/fetch-edit-token.json")

if [ "${#csrf_token}" = 42 ]; then
  log info "Edit token for file OK."
else
  die 1 "Edit token for file not set."
fi

dry_run_skip "upload file '$page_file' to '$WIKI_URL'"

curl_run \
  "${curl_opts[@]}" \
  --cookie "$cookie_jar" \
  --cookie-jar "$cookie_jar" \
  --header "Accept-Language: en-GB" \
  --header "Connection: keep-alive" \
  --header "Expect:" \
  --form "token=$csrf_token" \
  --form "filename=$page_file" \
  --form "file=@$new_file" \
  --form "comment=$edit_msg" \
  --form "ignorewarnings=yes" \
  --output "${TMPFOLDER}/upload-result.json" \
  --request "POST" \
  "${WIKI_API}?action=upload&format=json&tags=mediawiki-shell&bot"

log info "Network for file upload ok."

test -r "${TMPFOLDER}/upload-result.json"

edit_result_output="$(stcat "${TMPFOLDER}/upload-result.json")"
if [ "$(jq -r ".error.code" <<<"$edit_result_output")" = "fileexists-no-change" ]; then
  log info "Upload file success."
  exit 0
fi

edit_result_jq="$(jq -r ".edit.result" <<<"$edit_result_output")"
if [ "$edit_result_jq" = "Success" ]; then
  log info "Upload (edit) file success."
  exit 0
fi

upload_result_jq="$(jq -r ".upload.result" <<<"$edit_result_output")"
if [ "$upload_result_jq" = "Success" ]; then
  log info "Upload (upload) file success."
  exit 0
fi

log error "Check result on the file: ${TMPFOLDER}/upload-result.json"
jq . <<<"$edit_result_output" | stcat >&2
die 1 "Upload file error."
