Last active
June 11, 2020 20:56
-
-
Save szero/59c6bb98f5b7807de1a49e3c79db5b3c to your computer and use it in GitHub Desktop.
Python volafile downloader for linux, type $ volander.py -h to check usage
This file contains hidden or 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
#!/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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To install requirements do
pip3 install volapi colorama
You will also need
wget
. You can also installwget2
with your package manager for nice and fast parallel downloads.