Last active
October 24, 2024 15:22
-
-
Save marco79cgn/b09e26beaaf466cb04f9d74122866048 to your computer and use it in GitHub Desktop.
Das Skript lädt entweder einen einzelnen Film, Staffeln einer Serie oder alle Tatort Folgen einer Stadt von ARD Plus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
FILE=ard-plus-token | |
# parse input parameter | |
ardPlusUrl=$1 | |
username=$2 | |
password=$3 | |
skip=$4 | |
movieId='' | |
token='' | |
showPath=$(echo $ardPlusUrl | rev | cut -d "/" -f1 | rev) | |
showId=$(echo $showPath | cut -d "-" -f1) | |
if [[ -z "$username" || -z "$password" ]] | |
then | |
echo "Credentials missing! Please start the script with 3 parameters: " | |
echo "./ard-plus-dl <ard-plus-url> <username> <password>" | |
exit 1 | |
fi | |
if [[ -z "$skip" ]] | |
then | |
skip=1 | |
fi | |
# login only if necessary | |
login() { | |
loginResult=$(curl -s -o /dev/null -w '%header{authorization}' 'https://auth.ardplus.de/auth/login?plainRedirect=true&redirectURL=https%3A%2F%2Fwww.ardplus.de%2Flogin%2Fcallback&errorRedirectURL=https%3A%2F%2Fwww.ardplus.de%2Fanmeldung%3Ferror%3Dtrue' \ | |
-H 'authority: auth.ardplus.de' \ | |
-H 'content-type: application/x-www-form-urlencoded' \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' \ | |
--data-raw "username=$1&password=$2" \ | |
--compressed) | |
token=$(echo $loginResult | awk -F'Bearer ' '{print $2}') | |
echo $token > $FILE | |
} | |
# cleanup after each episode and at the end | |
cleanup() { | |
deleteToken=$(curl -s 'https://token.ardplus.de/token/session/playback/delete' \ | |
-H 'authority: token.ardplus.de' \ | |
-H 'content-type: application/json' \ | |
-H "cookie: sid=$token" \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' \ | |
--data-raw "{\"contentId\":\"$movieId\",\"contentType\":\"CmsMovie\"}" \ | |
--compressed) | |
} | |
# get authorization for content | |
auth() { | |
auth=$(curl -s 'https://token.ardplus.de/token/session' \ | |
-H 'authority: token.ardplus.de' \ | |
-H 'content-type: application/json' \ | |
-H "cookie: sid=$token" \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' \ | |
--data-raw "{\"contentId\":\"$movieId\",\"contentType\":\"CmsEpisode\",\"download\":false,\"appInfo\":{\"platform\":\"web\",\"appVersion\":\"1.0.0\",\"build\":\"web\",\"bundleIdentifier\":\"web\"},\"deviceInfo\":{\"isTouchDevice\":false,\"isTablet\":false,\"isFireOS\":false,\"appPlatform\":\"web\",\"isIOS\":false,\"isCastReceiver\":false,\"isSafari\":false,\"isFirefox\":false}}" \ | |
--compressed) | |
urlParam=$(echo ${auth} | jq -r '.authorizationParams') | |
echo "$urlParam" | |
} | |
# intercept CTRL+C click to clean up before exit | |
term() { | |
echo "CTRL+C pressed. Cleanup and exit!" | |
cleanup | |
exit 0 | |
} | |
trap term SIGINT | |
# perform login | |
if [ -f "$FILE" ]; then | |
# Using cached token | |
token=$(<$FILE) | |
else | |
# Log in once | |
login $username $password | |
fi | |
# check if token is valid | |
movieId="a0S010000007GcX" | |
urlParam=$( auth ) | |
if [[ "$urlParam" == null ]]; then | |
login $username $password | |
token=$(<$FILE) | |
if [[ -z "$token" ]]; then | |
echo "Login not possible! Please check credentials and subscription for user $username." | |
exit 0 | |
fi | |
fi | |
cleanup | |
# get requested content | |
contentUrl="https://data.ardplus.de/ard/graphql?extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%2240d7cbfb79e6675c80aae2d44da2a7f74e4a4ee913b5c31b37cf9522fa64d63b%22%7D%7D&variables=%7B%22movieId%22%3A%22$showId%22%2C%22externalId%22%3A%22%22%2C%22slug%22%3A%22%22%2C%22potentialMovieId%22%3A%22%22%7D" | |
seasonsStatus=$(curl -s -o content-result.txt -w "%{http_code}" "${contentUrl}" \ | |
-H 'authority: data.ardplus.de' \ | |
-H 'content-type: application/json' \ | |
-H "cookie: sid=$token" \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36') | |
if [[ $seasonsStatus != "200" ]]; then | |
#retry once | |
echo "Couldn't get season details. Trying again!" | |
sleep 2 | |
seasonsStatus=$(curl -s -o content-result.txt -w "%{http_code}" "${contentUrl}" \ | |
-H 'authority: data.ardplus.de' \ | |
-H 'content-type: application/json' \ | |
-H "cookie: sid=$token" \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36') | |
contentResult=$(cat content-result.txt) | |
else | |
contentResult=$(cat content-result.txt) | |
fi | |
# check whether content is movie or series | |
movie=$(echo "$contentResult" | jq '.data.movie') | |
tvshow=$(echo "$contentResult" | jq '.data.series') | |
if [[ "$movie" != null ]]; then | |
movieId=$(echo "$movie" | jq -r '.id') | |
name=$(echo "$movie" | jq -r '.title') | |
videoUrl=$(echo "$movie" | jq -r '.videoSource.dashUrl') | |
year=$(echo "$movie" | jq -r '.productionYear') | |
filename="${name} (${year})" | |
urlParam=$( auth ) | |
downloadUrl=${videoUrl}?${urlParam} | |
echo "Lade Film ${filename}..." | |
yt-dlp --quiet --progress --no-warnings ${downloadUrl} -o "$filename" | |
cleanup | |
elif [[ "$tvshow" != null ]]; then | |
requestedShow=$(echo "$contentResult" | jq '.data.series.title') | |
seasonIds=$(echo "$contentResult" | jq '[.data.series.seasons.nodes[] | { season: .seasonInSeries, seasonId: .id, title: .title }]') | |
seasonOutput=$(echo "$seasonIds" | jq '[.[] | { Option: .season, Titel: .title }]' | jq -r '(.[0]|keys_unsorted|(.,map(length*"-"))),.[]|map(.)|@tsv'|column -ts $'\t') | |
echo -e "\nGewünschte Serie: $requestedShow\n" | |
echo -e "$seasonOutput\n" | |
echo -n "Welche Staffel möchtest du runterladen? " | |
read -r selectedSeason | |
selectedSeasonId=$(echo "$seasonIds" | jq -r --argjson index 1 ".[$((selectedSeason - 1))].seasonId") | |
seasonData=$(curl -s "https://data.ardplus.de/ard/graphql?extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%22134d75e1e68a9599d1cdccf790839d9d71d2e7d7dca57d96f95285fcfd02b2ae%22%7D%7D&variables=%7B%22seasonId%22%3A%22$selectedSeasonId%22%7D&operationName=EpisodesInSeasonData" \ | |
-H 'authority: data.ardplus.de' \ | |
-H 'content-type: application/json' \ | |
-H "cookie: sid=$token" \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36') | |
episodes=$(echo $seasonData | jq '[.data.episodes.nodes[] | { id: .id, episodeNo: .episodeInSeason, title: .title, videoUrl: .videoSource.dashUrl }]') | |
amount=$(echo $episodes | jq '. | length') | |
echo -e "\nStaffel $selectedSeason hat $amount Folgen." | |
selectedSeasonFormatted=$(printf '%02d\n' "$selectedSeason") | |
# loop over all episodes and download each | |
while read episode | |
do | |
movieId=$(echo "$episode" | jq -r '.id') | |
name=$(echo "$episode" | jq -r '.title') | |
videoUrl=$(echo "$episode" | jq -r '.videoUrl') | |
episode=$(echo "$episode" | jq -r '.episodeNo') | |
filename="S${selectedSeasonFormatted}E$(printf '%02d\n' $episode) - ${name}" | |
urlParam=$( auth ) | |
downloadUrl=${videoUrl}?${urlParam} | |
echo "Lade ${filename}..." | |
yt-dlp --quiet --progress --no-warnings ${downloadUrl} -o "$filename" | |
cleanup | |
done < <(echo "$episodes" | jq -c '.[]') | |
elif [[ "$ardPlusUrl" == *"tatort"* ]]; then | |
tatortCity=$(echo $showPath | cut -d "-" -f2) | |
# get all episodes per city | |
tatortCityEpisodes=$(curl -s "https://data.ardplus.de/ard/graphql?operationName=CategoryDataBySlug&variables=%7B%22slug%22%3A%22tatort-$tatortCity%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%221bf6e600fa91aa72bba35ee95a53677cf21b994a4c2afbcd01127259c7e88612%22%7D%7D" \ | |
--header 'authority: data.ardplus.de' \ | |
--header 'content-type: application/json' \ | |
--header "cookie: sid=$token" \ | |
--header 'origin: https://www.ardplus.de' \ | |
--header 'referer: https://www.ardplus.de/' \ | |
--header 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36') | |
episodeIds=$(echo "$tatortCityEpisodes" | jq '[.data.category.content.nodes[] | { id: .contentMovie.id }]') | |
amount=$(echo $episodeIds | jq '. | length') | |
cityCapitalized=$(echo ${tatortCity} | awk '{$1=toupper(substr($1,0,1))substr($1,2)}1') | |
echo "Der Tatort ${cityCapitalized} hat $amount Episoden." | |
echo -n "Wie viele Episoden möchtest du überspringen? (0=alle laden) " | |
read -r skip | |
echo "Überspringe $skip Episode(n)." | |
skip=$((skip + 1)) | |
# loop over all episodes and download each | |
while read episode | |
do | |
movieId=$(echo "$episode" | jq -r '.id') | |
episodeUrl="https://data.ardplus.de/ard/graphql?operationName=MovieDetails&variables=%7B%22movieId%22%3A%22$movieId%22%2C%22externalId%22%3A%22%22%2C%22slug%22%3A%22%22%2C%22potentialMovieId%22%3A%22%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%226a791c24fd9716b154a3d68f9b5213eb0bf25828a5e633cdbbd2e35aa5b9a984%22%7D%7D" | |
episodeDetailsStatus=$(curl -s -o current-tatort-episode.txt -w "%{http_code}" "${episodeUrl}" \ | |
-H 'authority: data.ardplus.de' \ | |
-H 'content-type: application/json' \ | |
-H "cookie: sid=$token" \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36') | |
if [[ $episodeDetailsStatus != "200" ]]; then | |
#retry once | |
echo "Couldn't get episode details. Trying again!" | |
sleep 2 | |
episodeDetailsStatus=$(curl -s -o current-tatort-episode.txt -w "%{http_code}" $episodeUrl \ | |
-H 'authority: data.ardplus.de' \ | |
-H 'content-type: application/json' \ | |
-H "cookie: sid=$token" \ | |
-H 'origin: https://www.ardplus.de' \ | |
-H 'referer: https://www.ardplus.de/' \ | |
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' \ | |
--compressed) | |
episodeDetails=$(cat current-tatort-episode.txt) | |
else | |
episodeDetails=$(cat current-tatort-episode.txt) | |
fi | |
name=$(echo "$episodeDetails" | jq -r '.data.movie.title') | |
videoUrl=$(echo "$episodeDetails" | jq -r '.data.movie.videoSource.dashUrl') | |
year=$(echo "$episodeDetails" | jq -r '.data.movie.productionYear') | |
customData=$(echo "$episodeDetails" | jq -r '.data.movie.customData') | |
episode=$(echo "$customData" | jq -r '.episodeProductionNumber') | |
team=$(echo "$customData" | jq -r '.team') | |
city=$(echo "$customData" | jq -r '.location') | |
filename="Tatort ${city}" | |
if [[ -n "$team" ]]; | |
then | |
filename="$filename (${team})" | |
fi | |
if [[ "$episode" != null ]]; | |
then | |
filename="$filename - Folge ${episode}" | |
fi | |
filename="$filename - ${name} (${year})" | |
urlParam=$( auth ) | |
downloadUrl=${videoUrl}?${urlParam} | |
echo "Lade ${filename}..." | |
yt-dlp --quiet --progress --no-warnings ${downloadUrl} -o "$filename" | |
cleanup | |
sleep 1 | |
done < <(echo "$episodeIds" | jq -c '.[]' | tail -n +$skip ) | |
else | |
echo "invalid content" | |
fi | |
cleanup |
Hallo!
Hast du eine Idee, ob sich in der ARDplus Mediathek etwas geändert hat?
Ich bekomme oft 'invalid content' für Filme und Serien werden auch nicht runtergeladen...
folgendes Beispiel - dl.sh:
~/git/ard-plus-dl/ard-plus-dl.sh https://www.ardplus.de/details/a0S01000000zF11-halleluja-amigo <user> <password>
~/git/ard-plus-dl/ard-plus-dl.sh https://www.ardplus.de/details/a0T01000000s7sX-don-matteo <user> <password>
~/git/ard-plus-dl/ard-plus-dl.sh https://www.ardplus.de/details/a0S010000015IyU-alfred-die-knallerbse <user> <password>
~/git/ard-plus-dl/ard-plus-dl.sh https://www.ardplus.de/details/a0S010000015IyY-der-zerstreute <user> <password>
~/git/ard-plus-dl/ard-plus-dl.sh https://www.ardplus.de/details/a0S010000015Iyf-der-sanfte-mit-den-schnellen-beinen <user> <password>
~/git/ard-plus-dl/ard-plus-dl.sh https://www.ardplus.de/details/a0S010000015RYQ-ein-tolpatsch-auf-abwegen <user> <password>
ergibt folgenden Output:
> ./dl.sh
invalid content
Gewünschte Serie: "Don Matteo"
Option Titel
------ -----
1 Don Matteo - Staffel 1
2 Don Matteo - Staffel 2
Welche Staffel möchtest du runterladen? 2
jq: error (at <stdin>:1): Cannot iterate over null (null)
Staffel 2 hat Folgen.
Lade Film Alfred, die Knallerbse (1972)...
invalid content
invalid content
Lade Film Ein Tolpatsch auf Abwegen (1978)...
Lade Film Eine Wolke zwischen den Zähnen (1974)...
Vielen Dank für das ansonsten tolle Script!
Update 24.10.2024: fixed API calls
@gh01mojmnet
Sorry, hatte dein Feedback komplett übersehen. Das Skript sollte jetzt wieder einwandfrei funktionieren, auch mit deinen Beispielen.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Anforderungen
Benutzung
Skript downloaden und ausführbar machen:
chmod 755 ard-plus-series-dl.sh
Anschließend das Skript aufrufen und drei Parameter mitgeben:
./ard-plus-series-dl.sh <url> <username> <password>
Die URL ist die Übersichtsseite eines Films oder einer Serie bei ARD Plus, zum Beispiel
Praxis Bülowbogen (Serie):
https://www.ardplus.de/details/a0T01000000a1LU-praxis-buelowbogen
Lola rennt (Film):
https://www.ardplus.de/details/a0S01000000EWYi-lola-rennt
Das Skript erkennt automatisch, ob es sich um einen Film oder eine Serie handelt. Filme werden unmittelbar geladen. Im Falle einer Serie werden alle gefundenen Staffeln aufgelistet und zur Auswahl angeboten.
Es können zusätzlich zu Filmen und Serien auch ganze Tatort Ausgaben pro Stadt geladen werden, z.B. alle Folgen aus Bremen mit der URL:
https://www.ardplus.de/kategorie/tatort-bremen
Die Zieldateien werden sinnvoll benannt, z.B.:
S01E01 - Schönes Wochenende.mp4
oder
Lola rennt (1998).mp4