Files
Server-scripts/torrent/generate_torrent.sh
T

456 lines
11 KiB
Bash
Raw Normal View History

2026-10-02 12:59:29 +02:00
#!/usr/bin/env bash
#set -euo pipefail
TRACKER="https://leo-test.store/announce.php?passkey=6535616464613165323432306163343561333531"
PIECE_SIZE=22
2026-10-03 10:41:51 +02:00
usage() {
cat <<EOF
Usage:
$0 -i <input> -s <search-name> -t <movie|tv> [-l <language>] [--skip]
2026-10-02 12:59:29 +02:00
2026-10-03 10:41:51 +02:00
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
2026-10-02 12:59:29 +02:00
if [ -d "$INPUT" ]; then
2026-10-02 12:59:29 +02:00
NAME=$(basename "$INPUT")
else
echo "Input does not exist: $INPUT"
exit 1
fi
TMDB_BEARER_TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJlOTIwMzJlMDk1NmEzMWEyZjQ4MDA4NGI0MTg4OTIyZCIsIm5iZiI6MTc5MDQzMjc5NS42NjcsInN1YiI6IjZhYjdkNjFiZDY5NmI1ZGFjNGM5NDRkMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.IjddKtQ5X62A63kYslH24Pxg_TFCzu-QpGak_Pemgr8"
2026-10-03 10:41:51 +02:00
2026-10-02 12:59:29 +02:00
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" \
2026-10-03 10:41:51 +02:00
"$url"
2026-10-02 12:59:29 +02:00
}
# --------------------------------------------------
# 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}" \
2026-10-03 10:41:51 +02:00
--data-urlencode "language=${LANGUAGE}" \
2026-10-02 12:59:29 +02:00
"${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')")
2026-10-03 10:41:51 +02:00
DETAIL_LANGUAGE=$(get_value "$(echo "$DETAILS" | jq -r '.original_language')")
2026-10-02 12:59:29 +02:00
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
2026-10-02 12:59:29 +02:00
mkdir -p "$INPUT/Screens"
if [[ "$POSTER_URL" != "N/A" ]]; then
2026-10-03 10:41:51 +02:00
curl -s -L "$POSTER_URL" \
-o "$INPUT/Screens/cover.jpg"
fi
if [[ "$BACKDROP_URL" != "N/A" ]]; then
2026-10-03 10:41:51 +02:00
curl -s -L "$BACKDROP_URL" \
-o "$INPUT/Screens/backdrop.jpg"
fi
2026-10-02 12:59:29 +02:00
# --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}')
2026-10-03 10:41:51 +02:00
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)
2026-10-02 12:59:29 +02:00
echo Generate nfo file
cat > "${NAME}.nfo" <<EOF
==================================================
RELEASE INFORMATION
==================================================
2026-10-03 10:41:51 +02:00
Title : ${TITLE:-$NAME}
Original Title : ${ORIGINAL_TITLE:-N/A}
2026-10-02 12:59:29 +02:00
2026-10-03 10:41:51 +02:00
TMDB ID : ${TMDB_ID:-N/A}
TMDB URL : ${TMDB_URL:-N/A}
2026-10-02 12:59:29 +02:00
2026-10-03 10:41:51 +02:00
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
-----------
2026-10-02 12:59:29 +02:00
$VIDEO_CODEC
2026-10-03 10:41:51 +02:00
Encoder Settings
----------------
${ENCODER_SETTINGS:-N/A}
2026-10-02 12:59:29 +02:00
--------------------------------------------------
MEDIAINFO
--------------------------------------------------
$MEDIAINFO_OUTPUT
--------------------------------------------------
CHECKSUMS
--------------------------------------------------
2026-10-03 10:41:51 +02:00
MD5
---
2026-10-02 12:59:29 +02:00
$MD5
2026-10-03 10:41:51 +02:00
SHA256
------
2026-10-02 12:59:29 +02:00
$SHA256
--------------------------------------------------
TORRENT
--------------------------------------------------
2026-10-03 10:41:51 +02:00
Private Torrent : Yes
Piece Size : ${PIECE_SIZE:-Unknown}
Created With : mktorrent
2026-10-02 12:59:29 +02:00
2026-10-03 10:41:51 +02:00
==================================================
Generated on: $(date)
2026-10-02 12:59:29 +02:00
==================================================
EOF
SCREEN_DIR="$INPUT/Screens"
mkdir -p "$SCREEN_DIR"
2026-10-03 10:41:51 +02:00
# Videolänge in Sekunden
DURATION=$(ffprobe -v error \
-show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 \
"$MEDIA_FILE")
2026-10-03 10:41:51 +02:00
# 5 gleichmäßig verteilte Screenshots (10%-90%)
for i in {1..5}; do
PERCENT=$((i * 100 / 6))
TIMESTAMP=$(awk "BEGIN {print $DURATION * $PERCENT / 100}")
2026-10-03 10:41:51 +02:00
ffmpeg -y \
-ss "$TIMESTAMP" \
-i "$MEDIA_FILE" \
-frames:v 1 \
-q:v 2 \
"$SCREEN_DIR/screen_$i.png" \
>/dev/null 2>&1
done
2026-10-03 10:41:51 +02:00
echo "Screenshots erstellt in: $SCREEN_DIR"
2026-10-02 12:59:29 +02:00
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
2026-10-02 12:59:29 +02:00
for f in "$INPUT"/Screens/*; do
[[ -e "$f" ]] && FILES+=("$f")
done
2026-10-03 10:41:51 +02:00
ssh lucas@vivohost "mkdir -p \"Torrents/${NAME}\"" 
scp "${NAME}.torrent" "${NAME}.nfo" lucas@vivohost:"Torrents/${NAME}/"
scp -r "$INPUT/Screens" lucas@vivohost:"Torrents/${NAME}/"