Last active
October 5, 2022 01:09
-
-
Save MaxMatti/098e377e03cf4d7b3b6ad567ead940c5 to your computer and use it in GitHub Desktop.
Downloads files from volafile with multiple simultaneous connections.
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 | |
begintime="$(date +%s)" | |
OPTS=`getopt -o c:u:p:d: -l connections:,uniqueness:,parts:,destination:,useragent: -- "$@"` | |
if [ $? != 0 ] ; then | |
echo "Usage: $0 [-c <connections>] [-u <uniqueness>] [-p <parts>] [-d <destination>] [--useragent <useragent>] <path>" 1>&2 | |
exit 1 | |
fi | |
eval set -- "$OPTS" | |
connections=20 | |
uniqueness=0 | |
parts=200 | |
destination="$PWD" | |
useragent="" | |
while true ; do | |
case "$1" in | |
-c | --connections ) connections="$2"; shift 2 ;; | |
-u | --uniqueness ) | |
case "$2" in | |
"" ) uniqueness=0; shift 2 ;; | |
* ) uniqueness="$2"; shift 2 ;; | |
esac ;; | |
-p | --parts ) parts="$2"; shift 2 ;; | |
-d | --destination ) destination="$2"; shift 2 ;; | |
--useragent ) useragent="$2"; shift 2 ;; | |
-- ) shift; break ;; | |
* ) break ;; | |
esac | |
done | |
jobfifo="$(mktemp -t job-XXXX)" | |
feedfifo="$(mktemp -t feed-XXXX)" | |
ipfifo="$(mktemp -t ip-XXXX)" | |
lock="$(mktemp -t lock-XXXX)" | |
rm "$jobfifo" | |
mkfifo "$jobfifo" | |
rm "$feedfifo" | |
mkfifo "$feedfifo" | |
rm "$ipfifo" | |
mkfifo "$ipfifo" | |
cleanup() { | |
if [[ -p "$jobfifo" ]]; then | |
rm -f "$jobfifo" | |
fi | |
if [[ -p "$feedfifo" ]]; then | |
rm -f "$feedfifo" | |
fi | |
if [[ -p "$ipfifo" ]]; then | |
rm -f "$ipfifo" | |
fi | |
allfiles="" | |
for i in $(seq 0 $parts); do | |
allfiles="$allfiles \"$tmpdownloaddir/$name.$i\"" | |
done | |
echo "$allfiles" | xargs rm &>/dev/null | |
if [[ -d "$tmpdownloaddir" ]]; then | |
rm -df "$tmpdownloaddir" | |
fi | |
} | |
fillfifo() { | |
# parameters: host name ref chunk | |
for i in $(seq 0 $parts); do | |
read -s stuff <"$feedfifo" | |
echo "\"$1\" \"$2\" \"$i\" \"$((i * $4))\" \"$(($((i + 1)) * $4 - 1))\"" >"$jobfifo" | |
done | |
rm "$jobfifo" | |
rm "$feedfifo" | |
} | |
retrieve_line() { | |
if [ $# -lt 1 ]; then | |
return 1 | |
fi | |
if [ -p "$1" ]; then | |
while true; do | |
flock 3 | |
echo "stuff" >"$feedfifo" | |
read -st 1 data <"$jobfifo" | |
read_status=$? | |
flock -u 3 | |
if [[ $read_status -eq 0 ]]; then | |
echo "$data" | |
break | |
elif [[ $read_status -gt 128 ]]; then | |
continue | |
else | |
return 1 | |
fi | |
done 3<"$lock" | |
else | |
return 1 | |
fi | |
} | |
torthread() { | |
temp="$(mktemp -d)" | |
cd "$temp" | |
tempvar=1 | |
until [[ $tempvar == 0 ]]; do | |
while [[ true ]]; do | |
port=$((RANDOM%64511+1024)) | |
echo -ne "\035" | telnet 127.0.0.1 $port &> /dev/null | |
if [ $? -eq 1 ]; then | |
break | |
fi | |
done | |
tor -f - <<EOF &>/dev/null & | |
ClientOnly 1 | |
SocksPort $port | |
DataDirectory $temp | |
ExcludeNodes $2 | |
EOF | |
torpid=$! | |
tempvar=$? | |
done | |
cd "$tmpdownloaddir" | |
until tempvar="$(curl -s --socks4a "localhost:$port" ipinfo.io/ip 2>&1)"; do | |
sleep 5 | |
done | |
echo "$tempvar" >"$ipfifo" | |
errcount=0 | |
while true; do | |
line="$(retrieve_line "$jobfifo")" | |
if [ $? -eq 0 ]; then | |
declare -a "words=($line)" | |
curl -L --socks4a "localhost:$port" --retry 100 --range "${words[3]}-${words[4]}" -H 'Cookie: allow-download=1' "$server" -o "${words[1]}.${words[2]}" &>/dev/null | |
if [ $? != 0 ]; then | |
echo "$line" >"$jobfifo" | |
kill "$torpid" -HUP &>/dev/null | |
((errcount++)) | |
if [[ $errcount -gt $parts ]]; then | |
return | |
fi | |
fi | |
else | |
break | |
fi | |
done | |
kill "$torpid" &>/dev/null | |
wait | |
rm -rf "$temp" | |
} | |
trap cleanup EXIT | |
server="$(curl -s "$1" | sed -e 's/.*href=\"//g' -e 's/\".*//g')" | |
ref="$(echo "$server" | sed -e 's/get/redir\/get/g' | cut -d/ -f 1,2,3,4,5,6)" | |
host="$(echo "$server" | cut -d/ -f 3)" | |
name="$(echo "$server" | cut -d/ -f 6 | sed 's/\%20/ /g')" | |
size="$(curl -L -vvv --range 0-0 -H 'Cookie: allow-download=1' "$server" -o /dev/null 2>&1 >/dev/null | awk -F '/' '/Content-Range/ { print $2+0 }')" | |
if [ $size -eq 0 ]; then | |
echo "Error getting filesize." 1>&2 | |
exit 1 | |
fi | |
if [ $size -lt $((parts * 1024 * 1024)) ]; then | |
parts=$((size / 1024 / 1024 + 1)) | |
echo "Excessive amount of parts. Lowered to $parts." | |
fi | |
if [ $parts -lt $connections ]; then | |
connections=$parts | |
echo "Excessive amount of connections. Lowered to $connections." | |
fi | |
if [ $parts -eq 0 ]; then | |
echo "Amount of parts was somehow set to 0, setting to 1." | |
parts=20 | |
fi | |
chunk=$((size / parts)) | |
if [ $((size/1024)) -gt $(df -k --output=avail "$destination" | tail -n 1) ]; then | |
echo "Not enough space for file in destination." 1>&2 | |
exit 1 | |
fi | |
if [ -e "$destination/$name" ]; then | |
read -r -p "File already exists. Overwrite? [Y/n] " response | |
case "$response" in | |
[yY]) | |
rm "$destination/$name" ;; | |
*) | |
exit 1 ;; | |
esac | |
fi | |
if [ $((size/1024)) -gt $(df -k --output=avail /tmp | tail -n 1) ]; then | |
tmpdownloaddir="$(mktemp -d -p "$destination")" | |
else | |
tmpdownloaddir="$(mktemp -d)" | |
fi | |
fillfifo "$host" "$name" "$ref" "$chunk" & | |
iplist="" | |
if [[ $uniqueness -gt 0 ]]; then | |
for i in $(seq 1 $uniqueness $connections); do | |
for j in $(seq 0 $uniqueness); do | |
if [ $((i + j - 1)) -ge $connections ]; then | |
break | |
fi | |
torthread "$iplist" & | |
done | |
for j in $(seq 1 $uniqueness); do | |
if [ $((i + j - 1)) -gt $connections ]; then | |
break | |
fi | |
until read ipentry; do | |
sleep 1 | |
done < "$ipfifo" | |
echo "Connected to Exit-Node $((i + j - 1))/$connections: $ipentry" | |
iplist="$iplist,$ipentry" | |
done | |
done | |
else | |
for i in $(seq 1 $connections); do | |
torthread "" & | |
done | |
fi | |
downloaded=0 | |
formatsize="$(numfmt --to=iec-i --suffix=B $size)" | |
width="$(($(tput cols) - 51 - ${#formatsize} - (${#connections} * 2)))" | |
startedJobs=0 | |
while [[ -n $(jobs -r) ]]; do | |
runningJobs="$(jobs -r | grep tor | wc -l)" | |
echo -ne "\r " | |
printf "%${#connections}s" "$((startedJobs<$runningJobs?$startedJobs:$runningJobs))" | |
echo -ne "/$connections connections active - [" | |
speed="$downloaded" | |
downloaded="$(($(du -c "$tmpdownloaddir/$name.*" 2>/dev/null | awk 'END{ print $1 }')*1024))" | |
speed="$((downloaded-speed))" | |
if [[ speed -lt 0 ]]; then | |
speed=0 | |
fi | |
if [ $downloaded -gt 0 ]; then | |
for i in $(seq 0 $((width * downloaded / size))); do | |
echo -ne "#" | |
done | |
fi | |
if [ $downloaded -lt $size ]; then | |
for i in $(seq 0 $((width * (size - downloaded) / size))); do | |
echo -ne " " | |
done | |
fi | |
echo -ne "] ($(numfmt --to=iec-i --suffix=B --padding=7 $downloaded)/$formatsize) @ $(numfmt --to=iec-i --suffix=B/s --padding=9 $speed) " | |
if [ $startedJobs -lt $connections ]; then | |
echo "buffer" >"$ipfifo" & | |
sleep 1 | |
((startedJobs+=$(($(cat "$ipfifo" | wc -l) - 1)))) | |
else | |
sleep 1 | |
fi | |
done | |
totaltime=$(($(date +%s) - $begintime)) | |
totaltime="$(printf "%02d" "$((totaltime/(60*60)))"):$(printf "%02d" "$((totaltime/60%60))"):$(printf "%02d" "$((totaltime%60))")" | |
echo -e "\r\033[KDownloaded $formatsize in $parts parts in $totaltime." | |
rm "$ipfifo" | |
wait | |
allfiles="" | |
for i in $(seq 0 $parts); do | |
allfiles="$allfiles \"$tmpdownloaddir/$name.$i\"" | |
done | |
echo "$allfiles" | xargs cat >>"$destination/$name" |
Usage: volafile-downloader.sh [-c <connections>] [-u <uniqueness>] [-p <parts>] [-d <destination>] [--useragent <useragent>] <path>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How do you use this?