A simple downloader written in bash
./nekosama.sh "$(./nekosama-tui.sh)"
- gum
- curl-impersonator
- jq
#!/bin/bash | |
if ! [ -x "$(command -v gum)" ]; then | |
echo 'Error: gum is not installed.' >&2 | |
exit 1 | |
fi | |
if ! [ -x "$(command -v jq)" ]; then | |
echo 'Error: jq is not installed.' >&2 | |
exit 1 | |
fi | |
function generateSequence { | |
local sequence="" | |
local nbrOfEpisodes=$1 | |
((++nbrOfEpisodes)) | |
while((nbrOfEpisodes--)); do | |
if [[ $nbrOfEpisodes -eq 0 ]]; then | |
break | |
fi | |
if [[ $nbrOfEpisodes -lt 10 ]]; then | |
sequence="0$nbrOfEpisodes $sequence" | |
continue | |
fi | |
sequence="$nbrOfEpisodes $sequence" | |
done | |
echo "$sequence" | |
} | |
JSON="$(curl -s https://neko-sama.fr/animes-search-vostfr.json)" | |
SERIE_NAME="$(echo "$JSON" | jq -r '.[] | .title' | gum filter)" | |
if [ $? -ne 0 ]; then | |
exit 0 | |
fi | |
# printf "User choose to watch '%s'\n" "$SERIE_NAME" | |
SERIE_JSON="$(echo "$JSON" | jq 'map(select(.title == "'"$SERIE_NAME"'")) | .[]')" | |
SERIE_URL="$(echo "$SERIE_JSON" | jq -r '.url' | cut -d "/" -f 4 | cut -d '_' -f 1)" | |
SERIE_EPISODES="$(echo "$SERIE_JSON" | jq -r '.nb_eps')" | |
if [[ $SERIE_EPISODES != "Film" ]]; then | |
EPISODE="$(gum choose --header "Episode of $SERIE_NAME" $(generateSequence "$SERIE_EPISODES"))" | |
if [ $? -ne 0 ]; then | |
exit 0 | |
fi | |
else | |
EPISODE="01" | |
fi | |
printf "https://neko-sama.fr/anime/episode/%s-%s_vostfr\n" "$SERIE_URL" "$EPISODE" |
#!/bin/bash | |
if ! [ -x "$(command -v curl_ff109)" ]; then | |
echo "Error: curl-impersonate is not installed." >&2 | |
exit 10 | |
fi | |
if [[ $# -ne 1 ]]; then | |
echo "Illegal number of parameters" >&2 | |
exit 2 | |
fi | |
function fail { | |
printf '%s\n' "$1" >&2 ## Send message to stderr. | |
exit "${2-1}" ## Return a code specified by $2, or 1 by default. | |
} | |
mkdir "/tmp/nekosama" || true | |
ANIME_NAME=$(echo "$1" | rev | cut -d "/" -f 1 | rev) | |
echo "Getting the Video provider's URL for $ANIME_NAME" | |
VIDEO_PROVIDER_URL=$(curl_ff109 -s $1 | grep -E "\s+video\[0\] = 'https://.+'" | cut -d "'" -f 2) | |
URL="" | |
fv_parse () { | |
#Actual code | |
echo "Getting the M3U8 file" | |
local FV_GET_JS_SCRIPT=$(curl_ff109 -s "$VIDEO_PROVIDER_URL" | grep "https://fusevideo.io/f/u/u/u/u" | cut -d '"' -f 2) | |
local FV_GET_M3U8_URL=$(curl_ff109 -s "$FV_GET_JS_SCRIPT" | grep -o -E "\(n=atob\(\".+=\")" | cut -d "\"" -f 2 | base64 --decode | grep -o -E "https:.+\"" | cut -d "\"" -f 1 | sed 's/\\\//\//g') | |
echo "Parsing the M3U8" | |
URL=$(curl_ff109 -s "$FV_GET_M3U8_URL" | grep "https://" | head -n 1) | |
} | |
case "$VIDEO_PROVIDER_URL" in | |
"https://fusevideo.io"*) | |
# echo "Fuse video" | |
fv_parse | |
echo "Done:" "$URL";; | |
*) | |
echo "$VIDEO_PROVIDER_URL" "isn't supported yet" | |
exit 1;; | |
esac | |
old_pwd=$(pwd) | |
mkdir "/tmp/nekosama/$ANIME_NAME" || fail "Couldn't create directory in /tmp/nekosama" 3 | |
cd "/tmp/nekosama/$ANIME_NAME" || fail "Couldn't CD in /tmp/$ANIME_NAME" 4 | |
M3U_URLS=$(curl_ff109 "$URL" | grep -E "^https://") | |
curl --remote-name-all --max-time 10 --retry 5 --retry-delay 0 --retry-max-time 40 $M3U_URLS || fail "Couldn't download all .ts files" 5 | |
for i in $(\ls *.ts | sort -V); do echo "file '$i'"; done >> mylist.txt && ffmpeg -f concat -i mylist.txt -c copy -bsf:a aac_adtstoasc video.mp4 && rm *.ts && rm mylist.txt | |
cd "$old_pwd" || exit | |
mpv "/tmp/nekosama/$ANIME_NAME/video.mp4" | |
rm -rf "/tmp/nekosama/$ANIME_NAME" |