Files
Server-scripts/torrent/generate_torrent.sh
T

457 lines
11 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#set -euo pipefail
TRACKER="https://leo-test.store/announce.php?passkey=6535616464613165323432306163343561333531"
PIECE_SIZE=22
usage() {
cat <<EOF
Usage:
$0 -i <input> -s <search-name> -t <movie|tv> [-l <language>] [--skip]
Options:
-i, --input Input directory
-s, --search Search name for TMDB lookup
-t, --type Content type: movie or tv
-l, --lang Language (default: de)
--skip Skip torrent creation
-h, --help Show this help
EOF
}
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
-i|--input)
INPUT="$2"
shift 2
;;
-s|--search)
SEARCH_NAME="$2"
shift 2
;;
-t|--type)
TYPE="${2,,}"
shift 2
;;
-l|--lang)
LANGUAGE="${2,,}"
shift 2
;;
--skip)
SKIP_TORRENT_CREATION="true"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Error: Unknown argument '$1'"
usage
exit 1
;;
esac
done
}
validate_args() {
local errors=0
[[ -z "$INPUT" ]] && {
echo "Error: Input directory is required."
((errors++))
}
[[ -n "$INPUT" && ! -d "$INPUT" ]] && {
echo "Error: Input directory does not exist: $INPUT"
((errors++))
}
[[ -z "$SEARCH_NAME" ]] && {
echo "Error: Search name is required."
((errors++))
}
[[ "$TYPE" != "movie" && "$TYPE" != "tv" ]] && {
echo "Error: Type must be 'movie' or 'tv'."
((errors++))
}
# Optional: only allow supported TMDB languages
[[ ! "$LANGUAGE" =~ ^(de|en|fr|es|it)$ ]] && {
echo "Error: Language must be one of: de, en, fr, es, it"
((errors++))
}
(( errors > 0 )) && {
echo
usage
exit 1
}
}
normalize_language() {
case "${LANGUAGE,,}" in
de) LANGUAGE="de-DE" ;;
en) LANGUAGE="en-US" ;;
fr) LANGUAGE="fr-FR" ;;
es) LANGUAGE="es-ES" ;;
it) LANGUAGE="it-IT" ;;
*)
echo "Error: Languag* must be one of: de, en, fr, es, i*"
exit 1
;*
esac
}
# Defaults
INPUT=""
SEARCH_NAME=""
TYPE=""
LANGUAGE="de"
SKIP_TORRENT_CREATION="false"
parse_args "$@"
validate_args
normalize_language
if [ -d "$INPUT" ]; then
NAME=$(basename "$INPUT")
else
echo "Input does not exist: $INPUT"
exit 1
fi
TMDB_BEARER_TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJlOTIwMzJlMDk1NmEzMWEyZjQ4MDA4NGI0MTg4OTIyZCIsIm5iZiI6MTc5MDQzMjc5NS42NjcsInN1YiI6IjZhYjdkNjFiZDY5NmI1ZGFjNGM5NDRkMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.IjddKtQ5X62A63kYslH24Pxg_TFCzu-QpGak_Pemgr8"
if [[ -z "$SEARCH_NAME" ]]; then
echo "Search name required"
exit 1
fi
TMDB_API="https://api.themoviedb.org/3"
# --------------------------------------------------
# Helper
# --------------------------------------------------
get_value() {
local value="$1"
if [[ -z "$value" || "$value" == "null" ]]; then
echo "N/A"
else
echo "$value"
fi
}
tmdb_get() {
local url="$1"
curl -s \
-H "Authorization: Bearer ${TMDB_BEARER_TOKEN}" \
-H "accept: application/json" \
"$url"
}
# --------------------------------------------------
# Search
# --------------------------------------------------
echo "Collect $TYPE Release Info"
SEARCH_JSON=$(curl -s --get \
-H "Authorization: Bearer ${TMDB_BEARER_TOKEN}" \
-H "accept: application/json" \
--data-urlencode "query=${SEARCH_NAME}" \
--data-urlencode "language=${LANGUAGE}" \
"${TMDB_API}/search/${TYPE}")
TOTAL_RESULTS=$(echo "$SEARCH_JSON" | jq -r '.total_results // 0')
if [[ "$TOTAL_RESULTS" -eq 0 ]]; then
echo "No results found for: $SEARCH_NAME"
exit 1
fi
TMDB_ID=$(echo "$SEARCH_JSON" | jq -r '.results[0].id')
# --------------------------------------------------
# Details
# --------------------------------------------------
echo "Collect $TYPE Release Details"
DETAILS=$(tmdb_get \
"${TMDB_API}/${TYPE}/${TMDB_ID}?language=de-DE")
EXTERNAL=$(tmdb_get \
"${TMDB_API}/${TYPE}/${TMDB_ID}/external_ids")
# --------------------------------------------------
# Shared fields
# --------------------------------------------------
TITLE=$(get_value "$(echo "$DETAILS" | jq -r '.title // .name')")
ORIGINAL_TITLE=$(get_value "$(echo "$DETAILS" | jq -r '.original_title // .original_name')")
OVERVIEW=$(get_value "$(echo "$DETAILS" | jq -r '.overview')
")
IMDB_ID=$(get_value "$(echo "$EXTERNAL" | jq -r '.imdb_id')")
FIRST_RELEASE=$(get_value "$(echo "$DETAILS" | jq -r '.release_date // .first_air_date')")
STATUS=$(get_value "$(echo "$DETAILS" | jq -r '.status')")
DETAIL_LANGUAGE=$(get_value "$(echo "$DETAILS" | jq -r '.original_language')")
RATING=$(get_value "$(echo "$DETAILS" | jq -r '.vote_average')")
VOTES=$(get_value "$(echo "$DETAILS" | jq -r '.vote_count')")
GENRES=$(echo "$DETAILS" | jq -r '
if (.genres | length > 0)
then [.genres[].name] | join(", ")
else "N/A"
end
')
POSTER_PATH=$(echo "$DETAILS" | jq -r '.poster_path // empty')
BACKDROP_PATH=$(echo "$DETAILS" | jq -r '.backdrop_path // empty')
POSTER_URL="N/A"
BACKDROP_URL="N/A"
if [[ -n "$POSTER_PATH" ]]; then
POSTER_URL="https://image.tmdb.org/t/p/original${POSTER_PATH}"
fi
if [[ -n "$BACKDROP_PATH" ]]; then
BACKDROP_URL="https://image.tmdb.org/t/p/original${BACKDROP_PATH}"
fi
mkdir -p "$INPUT/Screens"
if [[ "$POSTER_URL" != "N/A" ]]; then
curl -s -L "$POSTER_URL" \
-o "$INPUT/Screens/cover.jpg"
fi
if [[ "$BACKDROP_URL" != "N/A" ]]; then
curl -s -L "$BACKDROP_URL" \
-o "$INPUT/Screens/backdrop.jpg"
fi
# --data-urlencode "api_key=AB" \
# "https://api.themoviedb.org/3/search/tv"
echo "Collecting media info..."
MEDIA_FILE=$(find "$INPUT" -type f \( \
-iname "*.mkv" -o \
-iname "*.mp4" -o \
-iname "*.avi" -o \
-iname "*.mov" -o \
-iname "*.m4v" -o \
-iname "*.ts" \
\) | head -n1)
MEDIAINFO_OUTPUT=$(mediainfo "$MEDIA_FILE")
ENCODER_SETTINGS=$(mediainfo "$MEDIA_FILE" \
| grep -iE "Encoded library settings|Writing library|encoding settings" \
|| true)
VIDEO_CODEC=$(mediainfo "$MEDIA_FILE" \
| grep "^Format" \
| head -n1 \
| cut -d':' -f2-)
SIZE=$(du -sh "$MEDIA_FILE" | awk '{print $1}')
MD5=$(md5sum "$MEDIA_FILE" | awk '{print $1}')
SHA256=$(sha256sum "$MEDIA_FILE" | awk '{print $1}')
TMDB_URL="https://www.themoviedb.org/${TYPE}/${TMDB_ID}"
if [[ "$IMDB_ID" != "N/A" ]]; then
IMDB_URL="https://www.imdb.com/title/${IMDB_ID}"
else
IMDB_URL="N/A"
fi
FILE_LIST=$(find "$INPUT" -type f -exec du -h {} \; | sort)
TOTAL_SIZE=$(du -sh "$INPUT" | cut -f1)
echo Generate nfo file
cat > "${NAME}.nfo" <<EOF
==================================================
RELEASE INFORMATION
==================================================
Title : ${TITLE:-$NAME}
Original Title : ${ORIGINAL_TITLE:-N/A}
TMDB ID : ${TMDB_ID:-N/A}
TMDB URL : ${TMDB_URL:-N/A}
IMDb ID : ${IMDB_ID:-N/A}
IMDb URL : ${IMDB_URL:-N/A}
Release Date : ${FIRST_RELEASE:-N/A}
Language : ${DETAIL_LANGUAGE:-N/A}
Status : ${STATUS:-N/A}
Genres : ${GENRES:-N/A}
Rating : ${RATING:-N/A}
Votes : ${VOTES:-N/A}
--------------------------------------------------
LINKS
--------------------------------------------------
TMDB ID : ${TMDB_ID:-N/A}
TMDB URL : ${TMDB_URL:-N/A}
IMDb ID : ${IMDB_ID:-N/A}
IMDb URL : ${IMDB_URL:-N/A}
--------------------------------------------------
OVERVIEW
--------------------------------------------------
${OVERVIEW:-N/A}
--------------------------------------------------
TV INFORMATION
--------------------------------------------------
Seasons : ${SEASONS:-N/A}
Episodes : ${EPISODES:-N/A}
Creators : ${CREATORS:-N/A}
Networks : ${NETWORKS:-N/A}
--------------------------------------------------
MOVIE INFORMATION
--------------------------------------------------
Runtime : ${RUNTIME:-N/A}
Budget : ${BUDGET:-N/A}
Director : ${DIRECTOR:-N/A}
--------------------------------------------------
CAST
--------------------------------------------------
${CAST:-N/A}
--------------------------------------------------
CONTENTS
--------------------------------------------------
 
Total Size : $TOTAL_SIZE
 
Files
-----
 
$FILE_LIST
--------------------------------------------------
FILE INFORMATION
--------------------------------------------------
Filename : $MEDIA_FILE
Size : $SIZE
Video Codec
-----------
$VIDEO_CODEC
Encoder Settings
----------------
${ENCODER_SETTINGS:-N/A}
--------------------------------------------------
MEDIAINFO
--------------------------------------------------
$MEDIAINFO_OUTPUT
--------------------------------------------------
CHECKSUMS
--------------------------------------------------
MD5
---
$MD5
SHA256
------
$SHA256
--------------------------------------------------
TORRENT
--------------------------------------------------
Private Torrent : Yes
Piece Size : ${PIECE_SIZE:-Unknown}
Created With : mktorrent
==================================================
Generated on: $(date)
==================================================
EOF
SCREEN_DIR="$INPUT/Screens"
mkdir -p "$SCREEN_DIR"
# Videolänge in Sekunden
DURATION=$(ffprobe -v error \
-show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 \
"$MEDIA_FILE")
# 5 gleichmäßig verteilte Screenshots (10%-90%)
for i in {1..5}; do
PERCENT=$((i * 100 / 6))
TIMESTAMP=$(awk "BEGIN {print $DURATION * $PERCENT / 100}")
ffmpeg -y \
-ss "$TIMESTAMP" \
-i "$MEDIA_FILE" \
-frames:v 1 \
-q:v 2 \
"$SCREEN_DIR/screen_$i.png" \
>/dev/null 2>&1
done
echo "Screenshots erstellt in: $SCREEN_DIR"
echo "Created:"
echo " ${NAME}.torrent"
echo " ${NAME}.nfo"
if [[ "$SKIP_TORRENT_CREATION" == "--skip" ]]; then
echo
echo Skip torrent cration
else
echo
echo "Creating torrent..."
mktorrent \
-p \
-l "$PIECE_SIZE" \
-a "$TRACKER" \
-o "${NAME}.torrent" \
"$INPUT"
fi
for f in "$INPUT"/Screens/*; do
[[ -e "$f" ]] && FILES+=("$f")
done
ssh lucas@vivohost "mkdir -p \"Torrents/${NAME}\"" 
scp "${NAME}.torrent" "${NAME}.nfo" lucas@vivohost:"Torrents/${NAME}/"
scp -r "$INPUT/Screens" lucas@vivohost:"Torrents/${NAME}/"