Skip to content

Instantly share code, notes, and snippets.

@szero
Last active June 11, 2020 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save szero/59c6bb98f5b7807de1a49e3c79db5b3c to your computer and use it in GitHub Desktop.
Save szero/59c6bb98f5b7807de1a49e3c79db5b3c to your computer and use it in GitHub Desktop.
Python volafile downloader for linux, type $ volander.py -h to check usage
#!/usr/bin/env python3
import sys
import re
import os
import argparse
from tempfile import NamedTemporaryFile
from subprocess import run
from shutil import which
from urllib.parse import quote
from colorama import Fore
from volapi import Room
if which("wget2"):
wget = "wget2"
elif which("wget"):
wget = "wget"
else:
print("No wgetz, no downloadz", file=sys.stderr)
sys.exit(1)
def parse_args():
usage = """
Download stuff from vola room that matches your given regex.
You can set enviorment variables of VOLA_USER and VOLA_PASS
with your vola username and password so you won't have to
specify them everytime you want to download with faster speeds.
Press Ctrl + C while in script to exit."""
reqs = """Requirements:
https://github.com/volafiled/python-volapi
https://gitlab.com/gnuwget/wget2
https://pypi.org/project/colorama
"""
parser = argparse.ArgumentParser(
description=usage,
epilog=reqs,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"rgx",
metavar="REGEX",
nargs="?",
default="",
type=str,
help="Your regex search string, to learn more about regex, "
"check this link: https://docs.python.org/3/library/re.html",
)
parser.add_argument("-r", "--room", dest="room", required=True)
parser.add_argument(
"-n", "--nick", dest="nick", default=os.environ.get("VOLA_USER", "")
)
parser.add_argument(
"-p", "--pass", dest="passwd", default=os.environ.get("VOLA_PASS", "")
)
parser.add_argument(
"-u",
"--roompass",
dest="roompass",
default="",
help="Required to get access to passworded rooms",
)
parser.add_argument(
"-i",
"--ignore-case",
dest="caseignore",
action="store_true",
help="Specify this option to make your searches case insensitive",
)
args = parser.parse_args()
if not args.nick and args.passwd:
parser.error("You are a nibba so you get no ribba!")
if not args.nick:
args.nick = "Volaphile"
args.caseignore = re.I if args.caseignore else 0
return args
def natural_sort(val):
"""Returns a tuple from a string that can be used as a sort key for
natural sorting."""
return [int(i) if i.isdigit() else i for i in re.split(r"(\d+)", val)]
def find_in_tuple(tpl, pattern, if_rgx):
if not if_rgx:
return True
for e in tpl[1:]:
if pattern.search(str(e)):
return True
return False
def get_files():
args = parse_args()
session = None
known_files = {}
while True:
match_list = set()
if args.rgx == "":
args.rgx = input(
"Gimme your regex (leave empty to select all files in the room): "
)
pattern = re.compile(args.rgx, re.M | args.caseignore)
with Room(args.room, args.nick, password=args.roompass) as r:
def handle_initial_files(flist):
if not flist:
print(Fore.YELLOW + "No files in the room! Closing the program...")
print(Fore.RESET, end="")
sys.exit(0)
for i in flist:
if i.fid not in known_files:
known_files[i.fid] = i
i = known_files[i.fid]
match_tpl = (i.url, i.name, i.uploader)
if find_in_tuple(match_tpl, pattern, args.rgx):
match_list.add(match_tpl)
if match_list:
return False
for i in flist:
fi = known_files.get(i.fid) or i
try:
filetype = fi.filetype
except AttributeError:
# can't call fileinfo on dead objects
filetype = i.filetype
fi = i
match_tpl = ()
if filetype == "video":
match_tpl = (fi.url, fi.name, fi.uploader, fi.title, fi.codec)
elif filetype == "audio":
match_tpl = (
fi.url,
fi.name,
fi.uploader,
fi.title,
fi.album,
fi.artist,
fi.codec,
)
if find_in_tuple(match_tpl, pattern, args.rgx):
match_list.add(match_tpl)
return False
r.add_listener("initial_files", handle_initial_files)
if session is None and args.passwd:
r.user.login(args.passwd)
session = r.user.session
r.listen()
if r.user.logged_in:
r.user.logout()
if match_list:
match_list = sorted(match_list, key=lambda x: natural_sort(x[1]))
print(Fore.MAGENTA + "---BEGINNING OF MATCHED FILES---" + Fore.RESET)
match_list = [item[:3] for item in match_list]
for _, name, uploader in match_list:
print(f"{name}, uploaded by {uploader}")
print(Fore.MAGENTA + "---END OF MATCHED FILES---" + Fore.RESET)
check = input(
"\nDo you want to download the files matched above?"
+ Fore.GREEN
+ " [Yy]es"
+ Fore.RESET
+ "|"
+ Fore.RED
+ "[Nn]o"
+ Fore.RESET
+ "|"
+ Fore.WHITE
+ "[Qq]uit"
+ Fore.RESET
+ ": "
)
if "Y" in check or "y" in check:
return match_list, session
if "Q" in check or "q" in check:
print(Fore.YELLOW + "See ya around!")
print(Fore.RESET, end="")
sys.exit(0)
else:
print(Fore.YELLOW + "Nothing got matched, my dude!" + Fore.RESET)
args.rgx = ""
def main():
files_to_dl, session = get_files()
headers = '--header "Cookie: allow-download=1"'
if session is not None:
headers = f'{headers} --header "Cookie: session={session}"'
with NamedTemporaryFile(mode="w", encoding="utf8") as cfg:
for url, _name, _uploader in files_to_dl:
cfg.write(f"{quote(url, safe='/:')}\n")
cfg.seek(0)
print(Fore.YELLOW)
run(
f"{wget} -q --force-progress --progress=bar -c -r -nc -nd -E -H -k "
f"-e robots=off {headers} -i {cfg.name}",
shell=True, check=False
)
print(Fore.RESET, end="")
return 0
if __name__ == "__main__":
try:
sys.exit(main())
except KeyboardInterrupt:
print(Fore.RESET, end="")
sys.exit(1)
@szero
Copy link
Author

szero commented Jun 11, 2020

To install requirements do pip3 install volapi colorama
You will also need wget. You can also install wget2 with your package manager for nice and fast parallel downloads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment