mirror of
https://github.com/obskyr/khinsider.git
synced 2025-03-11 21:59:39 +01:00
Improved error output a bit.
Exit statuses! Stderr! Wahoo!
This commit is contained in:
parent
e44902bb8d
commit
a20948246b
90
khinsider.py
90
khinsider.py
@ -17,12 +17,6 @@ try:
|
|||||||
except ImportError: # Python 2
|
except ImportError: # Python 2
|
||||||
from urlparse import unquote, urljoin
|
from urlparse import unquote, urljoin
|
||||||
|
|
||||||
# Windows disallows a few more characters in filenames than Linux does.
|
|
||||||
if os.name == 'nt':
|
|
||||||
FILENAME_INVALID_RE = re.compile(r'[<>:"/\\|?*]')
|
|
||||||
else:
|
|
||||||
FILENAME_INVALID_RE = re.compile(r'/')
|
|
||||||
|
|
||||||
|
|
||||||
class Silence(object):
|
class Silence(object):
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
@ -36,7 +30,7 @@ class Silence(object):
|
|||||||
sys.stderr = self._stderr
|
sys.stderr = self._stderr
|
||||||
|
|
||||||
|
|
||||||
# --- Install prerequisites---
|
# --- Install prerequisites ---
|
||||||
|
|
||||||
# (This section in `if __name__ == '__main__':` is entirely unrelated to the
|
# (This section in `if __name__ == '__main__':` is entirely unrelated to the
|
||||||
# rest of the module, and doesn't even run if the module isn't run by itself.)
|
# rest of the module, and doesn't even run if the module isn't run by itself.)
|
||||||
@ -79,9 +73,11 @@ if __name__ == '__main__':
|
|||||||
if verbose:
|
if verbose:
|
||||||
print("Failed to install {}. "
|
print("Failed to install {}. "
|
||||||
"You may need to run the script as an administrator "
|
"You may need to run the script as an administrator "
|
||||||
"or superuser.".format(module[0]))
|
"or superuser.".format(module[0]),
|
||||||
|
file=sys.stderr)
|
||||||
print ("You can also try to install the package manually "
|
print ("You can also try to install the package manually "
|
||||||
"(pip install \"{}\")".format(module[2]))
|
"(pip install \"{}\")".format(module[2]),
|
||||||
|
file=sys.stderr)
|
||||||
raise e
|
raise e
|
||||||
def installRequiredModules(needed=None, verbose=True):
|
def installRequiredModules(needed=None, verbose=True):
|
||||||
needed = neededInstalls() if needed is None else needed
|
needed = neededInstalls() if needed is None else needed
|
||||||
@ -94,12 +90,12 @@ if __name__ == '__main__':
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
print("You don't seem to have pip installed!")
|
print("You don't seem to have pip installed!")
|
||||||
print("Get it from https://pip.readthedocs.org/en/latest/installing.html")
|
print("Get it from https://pip.readthedocs.org/en/latest/installing.html")
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
installRequiredModules(needed)
|
installRequiredModules(needed)
|
||||||
except OSError:
|
except OSError:
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
|
|
||||||
# ------
|
# ------
|
||||||
|
|
||||||
@ -108,9 +104,12 @@ from bs4 import BeautifulSoup
|
|||||||
|
|
||||||
BASE_URL = 'https://downloads.khinsider.com/'
|
BASE_URL = 'https://downloads.khinsider.com/'
|
||||||
|
|
||||||
|
# Although some of these are valid on Linux, keeping this the same
|
||||||
|
# across systems is nice for consistency AND it works on WSL.
|
||||||
|
FILENAME_INVALID_RE = re.compile(r'[<>:"/\\|?*]')
|
||||||
|
|
||||||
|
|
||||||
# Different printin' for different Pythons.
|
# Different printin' for different Pythons.
|
||||||
normalPrint = print
|
|
||||||
def unicodePrint(*args, **kwargs):
|
def unicodePrint(*args, **kwargs):
|
||||||
unicodeType = str if sys.version_info[0] > 2 else unicode
|
unicodeType = str if sys.version_info[0] > 2 else unicode
|
||||||
encoding = sys.stdout.encoding or 'utf-8'
|
encoding = sys.stdout.encoding or 'utf-8'
|
||||||
@ -119,7 +118,7 @@ def unicodePrint(*args, **kwargs):
|
|||||||
if isinstance(arg, unicodeType) else arg
|
if isinstance(arg, unicodeType) else arg
|
||||||
for arg in args
|
for arg in args
|
||||||
]
|
]
|
||||||
normalPrint(*args, **kwargs)
|
print(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def lazyProperty(func):
|
def lazyProperty(func):
|
||||||
@ -170,7 +169,7 @@ def friendlyDownloadFile(file, path, index, total, verbose=False):
|
|||||||
unicodePrint("Downloading {}: {}...".format(numberStr, filename))
|
unicodePrint("Downloading {}: {}...".format(numberStr, filename))
|
||||||
for triesElapsed in range(3):
|
for triesElapsed in range(3):
|
||||||
if verbose and triesElapsed:
|
if verbose and triesElapsed:
|
||||||
unicodePrint("Couldn't download {}. Trying again...".format(filename))
|
unicodePrint("Couldn't download {}. Trying again...".format(filename), file=sys.stderr)
|
||||||
try:
|
try:
|
||||||
file.download(path)
|
file.download(path)
|
||||||
except (requests.ConnectionError, requests.Timeout):
|
except (requests.ConnectionError, requests.Timeout):
|
||||||
@ -179,11 +178,14 @@ def friendlyDownloadFile(file, path, index, total, verbose=False):
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
unicodePrint("Couldn't download {}. Skipping over.".format(filename))
|
unicodePrint("Couldn't download {}. Skipping over.".format(filename), file=sys.stderr)
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
unicodePrint("Skipping over {}: {}. Already exists.".format(numberStr, filename))
|
unicodePrint("Skipping over {}: {}. Already exists.".format(numberStr, filename))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class NonexistentSoundtrackError(Exception):
|
class NonexistentSoundtrackError(Exception):
|
||||||
def __init__(self, soundtrackId=""):
|
def __init__(self, soundtrackId=""):
|
||||||
@ -262,6 +264,8 @@ class Soundtrack(object):
|
|||||||
example, FLAC files will be downloaded if available, and otherwise MP3.
|
example, FLAC files will be downloaded if available, and otherwise MP3.
|
||||||
|
|
||||||
Print progress along the way if `verbose` is set to True.
|
Print progress along the way if `verbose` is set to True.
|
||||||
|
|
||||||
|
Return True if all files were downloaded successfully, False if not.
|
||||||
"""
|
"""
|
||||||
path = os.path.join(os.getcwd(), path)
|
path = os.path.join(os.getcwd(), path)
|
||||||
path = os.path.abspath(os.path.realpath(path))
|
path = os.path.abspath(os.path.realpath(path))
|
||||||
@ -285,8 +289,12 @@ class Soundtrack(object):
|
|||||||
if makeDirs and not os.path.isdir(path):
|
if makeDirs and not os.path.isdir(path):
|
||||||
os.makedirs(os.path.abspath(os.path.realpath(path)))
|
os.makedirs(os.path.abspath(os.path.realpath(path)))
|
||||||
|
|
||||||
|
success = True
|
||||||
for fileNumber, file in enumerate(files, 1):
|
for fileNumber, file in enumerate(files, 1):
|
||||||
friendlyDownloadFile(file, path, fileNumber, totalFiles, verbose)
|
if not friendlyDownloadFile(file, path, fileNumber, totalFiles, verbose):
|
||||||
|
success = False
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
|
|
||||||
class Song(object):
|
class Song(object):
|
||||||
@ -345,7 +353,7 @@ def download(soundtrackId, path='', makeDirs=True, formatOrder=None, verbose=Fal
|
|||||||
"""Download the soundtrack with the ID `soundtrackId`.
|
"""Download the soundtrack with the ID `soundtrackId`.
|
||||||
See Soundtrack.download for more information.
|
See Soundtrack.download for more information.
|
||||||
"""
|
"""
|
||||||
Soundtrack(soundtrackId).download(path, makeDirs, formatOrder, verbose)
|
return Soundtrack(soundtrackId).download(path, makeDirs, formatOrder, verbose)
|
||||||
|
|
||||||
|
|
||||||
def search(term):
|
def search(term):
|
||||||
@ -366,12 +374,12 @@ if __name__ == '__main__':
|
|||||||
# Tiny details!
|
# Tiny details!
|
||||||
class KindArgumentParser(argparse.ArgumentParser):
|
class KindArgumentParser(argparse.ArgumentParser):
|
||||||
def error(self, message):
|
def error(self, message):
|
||||||
print("No soundtrack specified! As the first parameter, use the name the soundtrack uses in its URL.")
|
print("No soundtrack specified! As the first parameter, use the name the soundtrack uses in its URL.", file=sys.stderr)
|
||||||
print("If you want to, you can also specify an output directory as the second parameter.")
|
print("If you want to, you can also specify an output directory as the second parameter.", file=sys.stderr)
|
||||||
print("You can also search for soundtracks by using your search term as parameter - as long as it's not an existing soundtrack.")
|
print("You can also search for soundtracks by using your search term as parameter - as long as it's not an existing soundtrack.", file=sys.stderr)
|
||||||
print()
|
print(file=sys.stderr)
|
||||||
print("For detailed help and more options, run \"{} --help\".".format(SCRIPT_NAME))
|
print("For detailed help and more options, run \"{} --help\".".format(SCRIPT_NAME), file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(1)
|
||||||
|
|
||||||
# More tiny details!
|
# More tiny details!
|
||||||
class ProperHelpFormatter(argparse.RawTextHelpFormatter):
|
class ProperHelpFormatter(argparse.RawTextHelpFormatter):
|
||||||
@ -453,28 +461,38 @@ if __name__ == '__main__':
|
|||||||
print("No soundtracks found.")
|
print("No soundtracks found.")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
download(soundtrack, outPath, formatOrder=formatOrder, verbose=True)
|
success = download(soundtrack, outPath, formatOrder=formatOrder, verbose=True)
|
||||||
|
if not success:
|
||||||
|
print("\nNot all files could be downloaded.", file=sys.stderr)
|
||||||
|
return 1
|
||||||
except NonexistentSoundtrackError:
|
except NonexistentSoundtrackError:
|
||||||
searchResults = search(searchTerm)
|
searchResults = search(searchTerm)
|
||||||
print("\nThe soundtrack \"{}\" does not seem to exist.".format(soundtrack))
|
print("\nThe soundtrack \"{}\" does not seem to exist.".format(soundtrack), file=sys.stderr)
|
||||||
|
|
||||||
if searchResults: # aww yeah we gon' do some searchin'
|
if searchResults: # aww yeah we gon' do some searchin'
|
||||||
print()
|
print(file=sys.stderr)
|
||||||
print("These exist, though:")
|
print("These exist, though:", file=sys.stderr)
|
||||||
for soundtrack in searchResults:
|
for soundtrack in searchResults:
|
||||||
print(soundtrack.id)
|
print(soundtrack.id, file=sys.stderr)
|
||||||
|
|
||||||
|
return 1
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("Stopped download.")
|
print("Stopped download.", file=sys.stderr)
|
||||||
|
return 1
|
||||||
except (requests.ConnectionError, requests.Timeout):
|
except (requests.ConnectionError, requests.Timeout):
|
||||||
print("Could not connect to KHInsider.")
|
print("Could not connect to KHInsider.", file=sys.stderr)
|
||||||
print("Make sure you have a working internet connection.")
|
print("Make sure you have a working internet connection.", file=sys.stderr)
|
||||||
|
return 1
|
||||||
except Exception:
|
except Exception:
|
||||||
print()
|
print(file=sys.stderr)
|
||||||
print("An unexpected error occurred! "
|
print("An unexpected error occurred! "
|
||||||
"If it isn't too much to ask, please report to "
|
"If it isn't too much to ask, please report to "
|
||||||
"https://github.com/obskyr/khinsider/issues.")
|
"https://github.com/obskyr/khinsider/issues.",
|
||||||
print("Attach the following error message:")
|
file=sys.stderr)
|
||||||
print()
|
print("Attach the following error message:", file=sys.stderr)
|
||||||
|
print(file=sys.stderr)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
doIt()
|
return 0
|
||||||
|
|
||||||
|
sys.exit(doIt())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user