mirror of
https://github.com/CoolnsX/dra-cla.git
synced 2025-12-20 07:15:25 +05:30
322 lines
9.8 KiB
Bash
Executable File
322 lines
9.8 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
#shellcheck disable=SC2154
|
|
|
|
# most important variables.
|
|
VERSION="3.0.1"
|
|
CHANNEL="main"
|
|
base_url="https://streamcool.pro"
|
|
logdir="${XDG_CACHE_HOME:-$HOME/.cache}"
|
|
logfile="$logdir/dra-hsts"
|
|
quality=best
|
|
scrape=query
|
|
agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/12$(head -5 /dev/urandom | tr -dc '0-2' | cut -c1).0.0.0 Safari/537.36"
|
|
trap 'rm -f '"$logfile"'.new' INT HUP
|
|
|
|
############
|
|
# help #
|
|
############
|
|
|
|
help_text() {
|
|
while IFS= read -r line; do
|
|
printf "%s\n" "$line"
|
|
done <<-EOF
|
|
|
|
Usage:
|
|
${0##*/} [-v] [-q <quality>] [-a <episode>] [-d | -p <download_dir>] [<query>]
|
|
${0##*/} [-v] [-q <quality>] -c
|
|
${0##*/} -h | -U | -V
|
|
|
|
Options:
|
|
-c continue watching drama from history
|
|
-a specify episode to watch
|
|
-h show helptext
|
|
-d download episode
|
|
-p download episode to specified directory
|
|
-q set video quality (best|worst|360|480|720|1080)
|
|
-v use VLC as the media player
|
|
-D Delete Entire history
|
|
-U fetch update from github
|
|
-V print version number and exit
|
|
|
|
Episode selection:
|
|
Multiple episodes can be chosen given a range
|
|
Choose episode [1-13]: 1 6
|
|
This would choose episodes 1 2 3 4 5 6
|
|
|
|
When selecting non-interactively (eg: -a <ep_no>), the first result will be
|
|
selected, if drama is passed as Args
|
|
EOF
|
|
}
|
|
|
|
############
|
|
# Update #
|
|
############
|
|
|
|
update_script() {
|
|
log "Checking For Updates.." >&2
|
|
update="$(curl -A "$agent" -s "https://raw.githubusercontent.com/CoolnsX/dra-cla/$CHANNEL/dra-cla" | diff -u "$0" -)"
|
|
if [ -z "$update" ]; then
|
|
log "Script is up to date :)\n" "32" >&2
|
|
exit 0
|
|
fi
|
|
#dry run
|
|
if [ "$1" -eq 0 ]; then
|
|
log "Update Available!!\n" "32" >&2
|
|
log "To Update, type: ${sudo}${0##*/} -U" "33" >&2
|
|
exit 0
|
|
fi
|
|
#warning: this updates the codebase of script.
|
|
if printf '%s\n' "$update" | patch "$0" -; then
|
|
log "Script has been updated\n" "32" >&2
|
|
exit 0
|
|
else
|
|
log "Can't update for some reason!\n" "31" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
############
|
|
# UI #
|
|
############
|
|
|
|
log() {
|
|
#shellcheck disable=SC2059
|
|
printf "\033[2K\r\033[1;${2:-36}m${1}\033[0m"
|
|
}
|
|
|
|
menu() {
|
|
fzf --prompt="$1 >> " --layout=reverse --border --height=20 -0 -1 -m
|
|
}
|
|
|
|
ask() {
|
|
log "$1" "33"
|
|
}
|
|
|
|
#############
|
|
# Logic #
|
|
#############
|
|
|
|
dep_ch() {
|
|
for dep in $(printf "%s" "$1" | tr ' ' '\n'); do
|
|
command -v "$dep" >/dev/null || {
|
|
log "Program $dep not found. Please install it\n" "31"
|
|
[ "$dep" = "aria2c" ] && log "To install $dep, Type <your_package_manager> aria2" "32"
|
|
exit 1
|
|
}
|
|
done
|
|
}
|
|
|
|
download() {
|
|
case "$1" in
|
|
*m3u8*)
|
|
log "Fetching Metadata"
|
|
data=$(curl -s -A "$agent" "$1" | sed '/#/d')
|
|
printf '%s' "$data" | nl -n'rz' | sed -E "s|^([0-9]*)[[:space:]]*(.*)|${3}\2\n\tout=\1.ts|g" | aria2c -x16 -s16 -j50 -d "$logdir/dra-hls" -i - --download-result=hide --summary-interval=0 --allow-overwrite=true
|
|
log "\nConcatenating Pieces..\n"
|
|
cat "$logdir/dra-hls"/* | ffmpeg -loglevel error -stats -i - -c copy "$download_dir/$2.mp4" -y
|
|
rm -f "$logdir/dra-hls"/*
|
|
;;
|
|
*)
|
|
aria2c --enable-rpc=false --check-certificate=false --continue --summary-interval=0 -x16 -s16 "$1" --dir="$download_dir" -o "$2.mp4" --download-result=hide
|
|
;;
|
|
esac
|
|
tput clear
|
|
log "Downloaded $2/$4"
|
|
}
|
|
|
|
open_episode() {
|
|
tput clear
|
|
log "Fetching $title Episode $episode.."
|
|
[ -z "$dpage_link" ] && dpage_link=$(curl -s -A "$agent" "$base_url/videos/${id}${episode}" | sed -nE 's_^[[:space:]]*<iframe src="([^"]*)".*_https:\1_p')
|
|
get_video_url
|
|
if grep -q "$id" "$logfile"; then
|
|
sed -E "s/^${id}.*/${id}$((episode + 1))/" "$logfile" >"${logfile}.new"
|
|
else
|
|
printf "%s%s\n" "$id" "$((episode + 1))" >>"$logfile"
|
|
fi
|
|
[ -z "$video_link" ] && log "Video URL not found" "31"
|
|
[ "$player_function" = "download" ] && display="Downloading" || display="Streaming"
|
|
log "$display $title Episode $episode/$total_eps\n" "32"
|
|
[ -z "$nohup" ] && ! printf "%s" "$player_function" | grep -q "android" && log "To play next Episode, quit the player."
|
|
|
|
#media Player
|
|
case "$player_function" in
|
|
mpv*) $nohup $player_function --force-media-title="${title} Episode ${episode}" "$video_link" >/dev/null 2>&1 ;;
|
|
android_mpv) am start --user 0 -a android.intent.action.VIEW -d "$video_link" -n is.xyz.mpv/.MPVActivity >/dev/null 2>&1 ;;
|
|
vlc*) $nohup $player_function --play-and-exit --meta-title="${title} Episode ${episode}" "$video_link" >/dev/null 2>&1 ;;
|
|
android_vlc) am start --user 0 -a android.intent.action.VIEW -d "$video_link" -n org.videolan.vlc/org.videolan.vlc.gui.video.VideoPlayerActivity -e "title" "${title} Episode ${episode}" >/dev/null 2>&1 ;;
|
|
download) "$player_function" "$video_link" "${title} Episode ${episode}" "$relative_link" "$total_eps";;
|
|
esac
|
|
|
|
dpage_link=""
|
|
[ -f "$logfile.new" ] && mv "${logfile}.new" "$logfile"
|
|
}
|
|
|
|
decrypt_link() {
|
|
secret_key='3933343232313932343333393532343839373532333432393038353835373532'
|
|
iv='39323632383539323332343335383235'
|
|
ajax_url="$base_url/encrypt-ajax.php"
|
|
ajax=$(printf "%s" "$1" | sed -nE 's/.*id=([^&]*)&.*/\1/p' | openssl enc -e -aes256 -K "$secret_key" -iv "$iv" -a)
|
|
video_url=$(curl -A "$agent" -s -H "X-Requested-With:XMLHttpRequest" "$ajax_url" -d "id=$ajax" | sed -e 's/{"data":"//' -e 's/"}/\n/' -e 's/\\//g' | base64 -d | openssl enc -d -aes256 -K "$secret_key" -iv "$iv" | sed -e 's/\].*/\]/' -e 's/\\//g' | tr '{|}' '\n' | sed -nE 's/\"file\":"([^"]*)".*label.*P.*/\1/p')
|
|
}
|
|
|
|
get_video_url() {
|
|
decrypt_link "$dpage_link"
|
|
relative_link=$(printf "%s" "$video_url" | sed 's|[^/]*$||')
|
|
video_links=$(curl -s -A "$agent" "$video_url" | sed "s|^#.*x||g; s|,.*|p|g; /^#/d; \$!N; s|\n| >${relative_link}|")
|
|
case $quality in
|
|
best)
|
|
video_link=$(printf '%s' "$video_links" | tail -n 1 | cut -d'>' -f2)
|
|
;;
|
|
worst)
|
|
video_link=$(printf '%s' "$video_links" | head -n 1 | cut -d'>' -f2)
|
|
;;
|
|
*)
|
|
video_link=$(printf '%s' "$video_links" | sed -n "/${quality}p >/p" | cut -d'>' -f2)
|
|
if [ -z "$video_link" ]; then
|
|
log "Current video quality is not available (defaulting to best quality)\n" "31"
|
|
quality=best
|
|
video_link=$(printf '%s' "$video_links" | tail -n 1 | cut -d'>' -f2)
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
############
|
|
# Main #
|
|
############
|
|
|
|
#create history file
|
|
[ -d "$logdir" ] || mkdir "$logdir"
|
|
[ -f "$logfile" ] || : >"$logfile"
|
|
download_dir="."
|
|
|
|
# OS detection for player selection and default download location.
|
|
case "$(uname -a)" in
|
|
*MINGW* | *WSL2*)
|
|
player_function="mpv.exe"
|
|
alt_player="vlc.exe"
|
|
;;
|
|
*ndroid*)
|
|
player_function="android_mpv"
|
|
download_dir="/sdcard"
|
|
alt_player="android_vlc"
|
|
;;
|
|
*)
|
|
player_function="mpv"
|
|
alt_player="vlc"
|
|
command -v "doas" >/dev/null && sudo="doas " || sudo="sudo "
|
|
;;
|
|
esac
|
|
|
|
while getopts 'vq:dp:chDUVa:' OPT; do
|
|
case $OPT in
|
|
d)
|
|
player_function="download"
|
|
;;
|
|
a)
|
|
ep_start=$OPTARG
|
|
;;
|
|
D)
|
|
: >"$logfile"
|
|
exit 0
|
|
;;
|
|
p)
|
|
player_function="download"
|
|
download_dir=$OPTARG
|
|
;;
|
|
q)
|
|
quality=$OPTARG
|
|
;;
|
|
c)
|
|
scrape=history
|
|
;;
|
|
v)
|
|
player_function=$alt_player
|
|
;;
|
|
U)
|
|
update_script 1
|
|
;;
|
|
V)
|
|
log "Version: $VERSION\n" >&2
|
|
log "Channel: $CHANNEL\n" >&2
|
|
update_script 0
|
|
;;
|
|
*)
|
|
help_text
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
shift $((OPTIND - 1))
|
|
|
|
#dependency checking
|
|
log "Checking Dependencies.."
|
|
dep_ch "curl sed grep openssl fzf"
|
|
if [ "$player_function" = "download" ]; then
|
|
dep_ch "aria2c ffmpeg"
|
|
elif ! printf "%s" "$player_function" | grep -q "android"; then
|
|
dep_ch "$player_function"
|
|
fi
|
|
|
|
if [ "$scrape" = "query" ]; then
|
|
[ -z "$*" ] && ask "Search Drama: " && read -r query || query=$*
|
|
log "Searching Drama.."
|
|
response=$(curl -A "$agent" -s "$base_url/search.html" -G --data-urlencode "keyword=$query" | sed -nE 's_^[[:space:]]*<a href="/videos/([^"]*)-episode-([0-9]*)">_\1 (\2 Episodes)_p')
|
|
[ -z "$response" ] && log "No Results Found" "31" && exit 0
|
|
log ""
|
|
id=$(printf "%s" "$response" | tr '-' ' ' | menu "Select Drama")
|
|
[ -z "$id" ] && log "No Drama Selected" "31" && exit 0
|
|
# sets $title and $total_eps variable
|
|
eval "$(printf %s "$id" | tr -s ' ' | sed -nE 's|(.*) \(([0-9]*) Episodes\)$|title="\1";total_eps="\2"|p')"
|
|
id=$(printf "%s" "$id" | sed 's| ([0-9]* Episodes)|-episode-|g' | tr ' ' '-')
|
|
|
|
else
|
|
log ""
|
|
[ ! -s "$logfile" ] && log "History is empty" "31" && exit 0
|
|
id=$(tr '-' ' ' <"$logfile" | menu "Continue" | tr ' ' '-')
|
|
[ -z "$id" ] && log "No Drama Selected" "31" && exit 0
|
|
ep_start=$(printf "%s" "$id" | sed -nE 's|.*-episode-([0-9]*)|\1|p')
|
|
log "Checking Episode $ep_start"
|
|
response=$(curl -s "$base_url/videos/$id" -A "$agent" | sed '/Latest Episodes/,$d' | sed -nE 's_^[[:space:]]*<a href.*/videos/.*-episode-([0-9]*)">.*_\1_p;s_^[[:space:]]*<iframe src="([^"]*)".*_https:\1_p')
|
|
[ -z "$response" ] && log "Episode Not Released" "31" && exit 0
|
|
id=$(printf "%s" "$id" | sed 's|-episode-.*|-episode-|g')
|
|
total_eps=$(printf "%s" "$response" | sed -n '2p')
|
|
title=$(printf "%s" "$id" | sed 's|-episode-.*||g' | tr '-' ' ' | tr -s ' ')
|
|
dpage_link=$(printf "%s" "$response" | head -1)
|
|
fi
|
|
|
|
#shows prompt if select episode is not specified via args
|
|
if [ -z "$ep_start" ]; then
|
|
log "Selected: $title\n" "32"
|
|
printf "%s" "$player_function" | grep -q "android" && display="Range is broken for android." || display="To specify a range, use: start_number end_number"
|
|
log "$display\n"
|
|
ask "Episodes [1-$total_eps]: "
|
|
read -r ep_start ep_end
|
|
fi
|
|
|
|
[ -z "$ep_start" ] && log "No Episode Selected" "31" && exit 1
|
|
if [ -n "$ep_end" ]; then
|
|
for episode in $(seq "$ep_start" "$ep_end"); do
|
|
open_episode
|
|
done
|
|
else
|
|
nohup="setsid -f"
|
|
episode="${ep_start}"
|
|
open_episode
|
|
fi
|
|
episode="${ep_end:-$ep_start}"
|
|
|
|
while cmd=$(printf "next\nreplay\nprevious\nselect\nchange_quality\nquit" | menu "Select Option"); do
|
|
case "$cmd" in
|
|
next) [ "$episode" -lt "$total_eps" ] && : $((episode += 1)) || flag=1 ;;
|
|
replay) ;;
|
|
previous) [ "$episode" -gt 1 ] && : $((episode -= 1)) || flag=1 ;;
|
|
select) ask "Episodes [1-$total_eps]: " && read -r episode ;;
|
|
*) log "" && exit 0 ;;
|
|
esac
|
|
[ -n "$flag" ] && log "Out of Range" "31" && flag="" && continue
|
|
open_episode
|
|
done
|