forked from HPR/hpr-tools
		
	
		
			
	
	
		
			291 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			291 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | #!/bin/bash - | ||
|  | #=============================================================================== | ||
|  | # | ||
|  | #         FILE: delete_ia_item | ||
|  | # | ||
|  | #        USAGE: ./delete_ia_item episode | ||
|  | # | ||
|  | #  DESCRIPTION: Deletes an uploaded item on the IA. The item (identifier) | ||
|  | #               can't be deleted entirely but it can be stripped of contents | ||
|  | #               and metadata and left in a 'Reserved' state so the slot can be | ||
|  | #               reused. | ||
|  | # | ||
|  | #      OPTIONS: --- | ||
|  | # REQUIREMENTS: --- | ||
|  | #         BUGS: --- | ||
|  | #        NOTES: --- | ||
|  | #       AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com | ||
|  | #      VERSION: 0.0.3 | ||
|  | #      CREATED: 2022-05-08 19:40:37 | ||
|  | #     REVISION: 2022-08-14 23:09:51 | ||
|  | # | ||
|  | #=============================================================================== | ||
|  | 
 | ||
|  | set -o nounset                              # Treat unset variables as an error | ||
|  | 
 | ||
|  | VERSION="0.0.3" | ||
|  | 
 | ||
|  | SCRIPT=${0##*/} | ||
|  | # DIR=${0%/*} | ||
|  | 
 | ||
|  | STDOUT="/dev/fd/2" | ||
|  | 
 | ||
|  | # | ||
|  | # Load library functions | ||
|  | # | ||
|  | LIB="$HOME/bin/function_lib.sh" | ||
|  | [ -e "$LIB" ] || { echo "Unable to source functions"; exit 1; } | ||
|  | # shellcheck source=function_lib.sh | ||
|  | source "$LIB" | ||
|  | 
 | ||
|  | # | ||
|  | # Colour codes | ||
|  | # | ||
|  | define_colours | ||
|  | 
 | ||
|  | # | ||
|  | # Make temporary files and set traps to delete them | ||
|  | # | ||
|  | TMP1=$(mktemp) || { echo "$SCRIPT: creation of temporary file failed!"; exit 1; } | ||
|  | trap 'cleanup_temp $TMP1' SIGHUP SIGINT SIGPIPE SIGTERM EXIT | ||
|  | 
 | ||
|  | #===  FUNCTION  ================================================================ | ||
|  | #         NAME: _DEBUG | ||
|  | #  DESCRIPTION: Writes messages if in DEBUG mode | ||
|  | #   PARAMETERS: List of messages | ||
|  | #      RETURNS: Nothing | ||
|  | #=============================================================================== | ||
|  | _DEBUG () { | ||
|  |     [ "$DEBUG" == 0 ] && return | ||
|  |     for msg in "$@"; do | ||
|  |         printf 'D> %s\n' "$msg" | ||
|  |     done | ||
|  | } | ||
|  | 
 | ||
|  | #===  FUNCTION  ================================================================ | ||
|  | #         NAME: _usage | ||
|  | #  DESCRIPTION: Report usage | ||
|  | #   PARAMETERS: 1       [optional] exit value | ||
|  | #      RETURNS: Nothing | ||
|  | #=============================================================================== | ||
|  | _usage () { | ||
|  |     local -i res="${1:-0}" | ||
|  | 
 | ||
|  |     cat >$STDOUT <<-endusage | ||
|  | ${SCRIPT} - version: ${VERSION} | ||
|  | 
 | ||
|  | Usage: ./${SCRIPT} [-h] [-d {0|1}] episode | ||
|  | 
 | ||
|  | Deletes an uploaded item on the IA. The item (identifier) can't be deleted | ||
|  | entirely but it can be stripped of contents and metadata and left in | ||
|  | a 'Reserved' state so the slot can be reused. | ||
|  | 
 | ||
|  | Options: | ||
|  |   -h                    Print this help | ||
|  |   -d 0|1                Dry run: -d 1 (the default) runs the script in dry-run | ||
|  |                         mode where nothing is moved but the actions that | ||
|  |                         will be taken are reported; -d 0 turns off dry-run | ||
|  |                         mode and the actions will be carried out. | ||
|  | 
 | ||
|  | Arguments: | ||
|  |    episode              Defines the episode (IA identifier) to be deleted from | ||
|  |                         archive.org. These identifiers are in the format | ||
|  |                         'hprNNNN' where 'NNNN' is a number with leading | ||
|  |                         zeroes, and 'hpr' is mandatory. | ||
|  | 
 | ||
|  |                         The script attempts to reformat incorrect identifiers | ||
|  |                         before giving up. The missing 'hpr' is added, and | ||
|  |                         missing leading zeroes are inserted. Thus '42' and | ||
|  |                         'hpr42' become 'hpr0042'. | ||
|  | 
 | ||
|  | Environment variables: | ||
|  |   delete_ia_item_DEBUG  If set to a non-zero value then the debugging | ||
|  |                         statements in the script are executed. Otherwise if | ||
|  |                         set to zero, or if the variable is absent no debug | ||
|  |                         information is produced.  The variable can be set | ||
|  |                         using the 'export' command or on the same line as the | ||
|  |                         command calling the script.  See the example below. | ||
|  | 
 | ||
|  | Examples | ||
|  |     ./delete_ia_item 3594        # Run in (default) dry-run mode | ||
|  |     ./delete_ia_item -d1 3594    # Run in (explicit) dry-run mode | ||
|  |     ./delete_ia_item -d0 3594    # Live mode | ||
|  | 
 | ||
|  |     delete_ia_item_DEBUG=1 ./delete_ia_item 3594 | ||
|  |                                  # Run in dry-run mode with debugging enabled | ||
|  | 
 | ||
|  | endusage | ||
|  |     exit "$res" | ||
|  | } | ||
|  | 
 | ||
|  | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|  | 
 | ||
|  | # | ||
|  | # Configure depending whether local or on borg | ||
|  | # | ||
|  | case $HOSTNAME in | ||
|  |     hprvps|marvin|borg) | ||
|  |         BASEDIR="$HOME/IA" ;; | ||
|  |     i7-desktop) | ||
|  |         BASEDIR="$HOME/HPR/IA" ;; | ||
|  |     *) | ||
|  |         echo "Wrong host!"; exit 1 ;; | ||
|  | esac | ||
|  | 
 | ||
|  | cd "$BASEDIR" || { echo "Can't cd to $BASEDIR"; exit 1; } | ||
|  | 
 | ||
|  | # | ||
|  | # Directories and files | ||
|  | # | ||
|  | LOGS="$BASEDIR/logs" | ||
|  | LOGFILE="$LOGS/$SCRIPT.log" | ||
|  | 
 | ||
|  | # | ||
|  | # Debug mode. Invoke it with: 'delete_ia_item_DEBUG=1 ./tidy_uploaded' | ||
|  | # | ||
|  | DEBUGVAR="${SCRIPT}_DEBUG" | ||
|  | DEBUG="${!DEBUGVAR:-0}" | ||
|  | [[ $DEBUG -eq 1 ]] && echo "Debug mode" | ||
|  | 
 | ||
|  | # | ||
|  | # File of processed shows | ||
|  | # | ||
|  | PROCFILE="$BASEDIR/.${SCRIPT}.dat" | ||
|  | [ -e "$PROCFILE" ] || touch "$PROCFILE" | ||
|  | 
 | ||
|  | # | ||
|  | # Prerequisites | ||
|  | # | ||
|  | jq=$(command -v jq) | ||
|  | [ -z "$jq" ] && { echo "Needs the 'jq' JSON filter"; exit 1; } | ||
|  | ia=$(command -v ia) | ||
|  | [ -z "$ia" ] && { echo "Needs the 'ia' Internet Archive script"; exit 1; } | ||
|  | 
 | ||
|  | # | ||
|  | # Process options | ||
|  | # | ||
|  | while getopts :d:h opt | ||
|  | do | ||
|  |     case "${opt}" in | ||
|  |         d) DRYRUN=$OPTARG;; | ||
|  |         h) _usage 0;; | ||
|  |         *) echo "** Unknown option" | ||
|  |            _usage 1;; | ||
|  |     esac | ||
|  | done | ||
|  | shift $((OPTIND - 1)) | ||
|  | 
 | ||
|  | DRYRUN=${DRYRUN:-1} | ||
|  | if [[ $DRYRUN -ne 0 && $DRYRUN -ne 1 ]]; then | ||
|  |     echo "** Use '-d 0' or '-d 1'" | ||
|  |     _usage 1 | ||
|  | fi | ||
|  | [[ $DRYRUN -eq 1 ]] && echo "Dry run mode" | ||
|  | 
 | ||
|  | # | ||
|  | # Should have only one argument | ||
|  | # | ||
|  | if [[ $# != 1 ]]; then | ||
|  |     echo "${red}${SCRIPT} takes one argument${reset}" | ||
|  |     _usage 1 | ||
|  | fi | ||
|  | 
 | ||
|  | # | ||
|  | # Collect the argument and clean and validate it, forcing leading zeroes if | ||
|  | # needed | ||
|  | # | ||
|  | item="${1:-}" | ||
|  | item="${item,,}" | ||
|  | item="${item## }" | ||
|  | item="${item%% }" | ||
|  | if [[ $item =~ ^(hpr)?([0-9]{1,4})$ ]]; then | ||
|  |     printf -v item 'hpr%04i' "${BASH_REMATCH[2]}" | ||
|  | else | ||
|  |     echo "${red}Invalid episode specification: '$item'${reset}" | ||
|  |     echo "${yellow}Use hprNNNN format with leading zeroes${reset}" | ||
|  |     _usage 1 | ||
|  | fi | ||
|  | 
 | ||
|  | _DEBUG "Dry run:     $DRYRUN" | ||
|  | _DEBUG "Item chosen: $item" | ||
|  | 
 | ||
|  | # | ||
|  | # Check the item exists on the IA and if it does collect metadata and parse | ||
|  | # out the items we need. | ||
|  | # | ||
|  | _DEBUG "Testing IA for existence of $item" | ||
|  | if ia list "$item" > /dev/null 2>&1; then | ||
|  |     ia metadata "$item" > "$TMP1" | ||
|  | 
 | ||
|  |     # This one's an array but we want a CSV list. | ||
|  |     # TODO: Not sure this works with tags containing spaces | ||
|  |     # shellcheck disable=SC2046 | ||
|  |     subject="$(jq -r '.metadata.subject | @csv' "$TMP1")" | ||
|  |     subject="${subject//\"\"\"/\"}" | ||
|  | 
 | ||
|  |     creator="$(jq -r '.metadata.creator' "$TMP1")" | ||
|  | 
 | ||
|  |     date="$(jq -r '.metadata.date' "$TMP1")" | ||
|  | 
 | ||
|  |     _DEBUG "subject:     $subject" | ||
|  |     _DEBUG "creator:     $creator" | ||
|  |     _DEBUG "date:        $date" | ||
|  | else | ||
|  |     echo "${red}The requested item '$item' is not on archive.org${reset}" | ||
|  |     exit 1 | ||
|  | fi | ||
|  | 
 | ||
|  | # | ||
|  | # Either pretend to do stuff in dry-run mode or do it for real, but with | ||
|  | # confirmation first. | ||
|  | # | ||
|  | if [[ $DRYRUN -eq 1 ]]; then | ||
|  |     echo "${yellow}Would have deleted item $item${reset}" | ||
|  |     echo "Commands:" | ||
|  |     echo "${blue}ia delete $item --all --no-backup${reset}" | ||
|  |     echo "${blue}ia metadata $item --modify=title:\"Reserved\"${reset}" | ||
|  |     echo "${blue}ia metadata $item --modify=description:\"Reserved\"${reset}" | ||
|  |     echo "${blue}ia metadata $item --remove=creator:\"$creator\"${reset}" | ||
|  |     echo "${blue}ia metadata $item --remove=date:$date${reset}" | ||
|  |     echo "${blue}ia metadata $item --remove=subject:'$subject'${reset}" | ||
|  |     echo | ||
|  |     echo "${blue}Would have removed any cache entry found${reset}" | ||
|  | else | ||
|  |     echo "${red}About to delete item $item.${reset}" | ||
|  |     if yes_no "OK to continue? %s " "N"; then | ||
|  |         # Not yet tested. Can't be until we have a need! Note that the quoted | ||
|  |         # items will not be shown as such using this form of 'echo'. | ||
|  |         # echo "Commands are being displayed, not run, until testing is complete" | ||
|  |         # | ||
|  |         # Now tested, and looking good | ||
|  |         # | ||
|  |         ia delete "$item" --all --no-backup | ||
|  |         ia metadata "$item" --modify=title:"Reserved" | ||
|  |         ia metadata "$item" --modify=description:"Reserved" | ||
|  |         ia metadata "$item" --remove=creator:"$creator" | ||
|  |         ia metadata "$item" --remove=date:"$date" | ||
|  |         ia metadata "$item" --remove=subject:"$(printf "'%s'" "$subject")" | ||
|  | 
 | ||
|  |         # | ||
|  |         # Ensure the show is not marked as "processed" in the cache. We need | ||
|  |         # 'grep' to determine if there's anything to do since 'sed' can't do | ||
|  |         # this apparently. | ||
|  |         # | ||
|  |         if grep -q -E '^'"$item"'$' "$PROCFILE"; then | ||
|  |             sed -i -e '/^'"$item"'$/d' "$PROCFILE" | ||
|  |             echo "${yellow}$item removed from cache${reset}" | ||
|  |         else | ||
|  |             echo "${yellow}$item not found in cache${reset}" | ||
|  |         fi | ||
|  | 
 | ||
|  |         # | ||
|  |         # Log this item | ||
|  |         # | ||
|  |         echo "$(date +%Y%m%d%H%M%S) deleted $item" >> "$LOGFILE" | ||
|  |     else | ||
|  |         echo "${red}Item not deleted. Aborting.${reset}" | ||
|  |     fi | ||
|  | fi | ||
|  | 
 | ||
|  | # vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21 |