From fee46273ee845c8b04f9647d63c57c3f1c4df51d Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Tue, 26 May 2026 01:21:02 -0700 Subject: add grabar dl tool --- README.md | 5 ++ grab.sh | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100755 grab.sh diff --git a/README.md b/README.md index 7c63adf..5b98cb4 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ These are a generic set of tools/helpers for running some sort of media service accessible over WebDAV. Its reccomended you run them from Google Colab to take advantage of fast download/upload speeds. Instructions provided in each notebook. + +For Jupyter Notebooks, please refer to the information within each one for more info + +# grab.sh +Grabar is a bridge bash script that allows you to download some file via aria2c and then upload it after via rclone to any source you've configured. Optionally uses ntfy for notifications diff --git a/grab.sh b/grab.sh new file mode 100755 index 0000000..8e2cd00 --- /dev/null +++ b/grab.sh @@ -0,0 +1,186 @@ +#!/usr/bin/env bash +set -eEuo pipefail + +usage() { + cat <<'EOF' +Usage: + grab.sh -l -r -u -n [options] + +Required args: + -l, --link Direct download link for aria2c + -r, --remote Rclone remote name (example: gdrive) + -u, --upload-dir Destination directory on the remote (example: Movies/2026) + -n, --ntfy-topic ntfy topic to publish notifications to + +Optional args: + -s, --ntfy-server ntfy server base URL (default: https://ntfy.sh) + --ntfy-token Bearer token for ntfy auth (or set NTFY_TOKEN env var) + -i, --item-name Name to include in notification titles/messages + -d, --delete-after Delete downloaded files after a successful upload + -h, --help Show this help message + +Examples: + grab.sh -l "https://example.com/file.mkv" -r gdrive -u "Incoming" -n "my-topic" -i "Movie Night" + grab.sh --link "https://example.com/file.zip" --remote myremote --upload-dir "Backups/zips" --ntfy-topic "alerts" --delete-after --item-name "Backup Zip" +EOF +} + +DOWNLOAD_LINK="" +RCLONE_REMOTE="" +UPLOAD_DIR="" +NTFY_TOPIC="" +NTFY_SERVER="https://ntfy.sh" +NTFY_TOKEN="${NTFY_TOKEN:-}" +ITEM_NAME="" +DELETE_AFTER="false" +CURRENT_STEP="initializing" +TMP_DIR="" + +send_ntfy() { + local title="$1" + local message="$2" + local priority="${3:-default}" + local tags="${4:-}" + + local url="${NTFY_SERVER%/}/${NTFY_TOPIC}" + local final_title="$title" + local final_message="$message" + + if [[ -n "$ITEM_NAME" ]]; then + final_title="${ITEM_NAME} - ${title}" + final_message="Item: ${ITEM_NAME}\n${message}" + fi + + local -a headers + headers=( + -H "Title: ${final_title}" + -H "Priority: ${priority}" + ) + + if [[ -n "$tags" ]]; then + headers+=( -H "Tags: ${tags}" ) + fi + + if [[ -n "$NTFY_TOKEN" ]]; then + headers+=( -H "Authorization: Bearer ${NTFY_TOKEN}" ) + fi + + if ! curl -fsS -m 15 -X POST "${headers[@]}" -d "$final_message" "$url" >/dev/null; then + echo "Warning: failed to publish ntfy notification (${title})." >&2 + fi +} + +on_error() { + local exit_code="$1" + local line_no="$2" + + send_ntfy \ + "grab.sh failed" \ + "Step: ${CURRENT_STEP}\nExit code: ${exit_code}\nLine: ${line_no}" \ + "high" \ + "x,warning" + + if [[ "$DELETE_AFTER" == "true" && -n "$TMP_DIR" && -d "$TMP_DIR" ]]; then + rm -rf "$TMP_DIR" + fi +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -l|--link) + DOWNLOAD_LINK="${2:-}" + shift 2 + ;; + -r|--remote) + RCLONE_REMOTE="${2:-}" + shift 2 + ;; + -u|--upload-dir) + UPLOAD_DIR="${2:-}" + shift 2 + ;; + -n|--ntfy-topic) + NTFY_TOPIC="${2:-}" + shift 2 + ;; + -s|--ntfy-server) + NTFY_SERVER="${2:-}" + shift 2 + ;; + --ntfy-token) + NTFY_TOKEN="${2:-}" + shift 2 + ;; + -i|--item-name) + ITEM_NAME="${2:-}" + shift 2 + ;; + -d|--delete-after) + DELETE_AFTER="true" + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage + exit 1 + ;; + esac +done + +if [[ -z "$DOWNLOAD_LINK" || -z "$RCLONE_REMOTE" || -z "$UPLOAD_DIR" || -z "$NTFY_TOPIC" ]]; then + echo "Error: missing required arguments." >&2 + usage + exit 1 +fi + +for cmd in aria2c rclone mktemp find curl; do + if ! command -v "$cmd" >/dev/null 2>&1; then + echo "Error: required command '$cmd' is not installed or not in PATH." >&2 + exit 1 + fi +done + +trap 'on_error $? $LINENO' ERR + +TMP_DIR="$(mktemp -d -p "$PWD" "grab.XXXXXX")" +DESTINATION="${RCLONE_REMOTE}:${UPLOAD_DIR%/}" + +CURRENT_STEP="job-start" + +CURRENT_STEP="download" +echo "Downloading with aria2c..." +send_ntfy "Download started" "Starting aria2c download." "default" "arrow_down" +aria2c \ + --dir "$TMP_DIR" \ + --auto-file-renaming=false \ + --allow-overwrite=true \ + "$DOWNLOAD_LINK" + +CURRENT_STEP="verify-download" +if ! find "$TMP_DIR" -mindepth 1 -print -quit >/dev/null 2>&1; then + send_ntfy "Download empty" "Download directory is empty; upload aborted." "high" "warning" + echo "Error: download appears empty; nothing to upload." >&2 + exit 1 +fi + +CURRENT_STEP="upload" +echo "Uploading to ${DESTINATION}..." +send_ntfy "Upload started" "Starting rclone copy to ${DESTINATION}." "default" "arrow_up" +rclone copy "$TMP_DIR" "$DESTINATION" --progress +send_ntfy "Upload complete" "rclone upload finished successfully." "default" "white_check_mark" + +if [[ "$DELETE_AFTER" == "true" ]]; then + CURRENT_STEP="cleanup" + rm -rf "$TMP_DIR" + echo "Downloaded files deleted from: $TMP_DIR" +else + echo "Downloaded files kept at: $TMP_DIR" +fi + +CURRENT_STEP="done" +echo "Done. Downloaded from '$DOWNLOAD_LINK' and uploaded to '$DESTINATION'." +send_ntfy "grabar done" "All steps completed successfully." "default" "tada" -- cgit v1.2.3