Skip to content
Extraits de code Groupes Projets
Vérifiée Valider de280848 rédigé par Krocoh's avatar Krocoh Validation de Kubat
Parcourir les fichiers

KAGARI: Add option to download multiple files at once

parent a969060b
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!161Kagari update
...@@ -25,8 +25,9 @@ def create_parser(): ...@@ -25,8 +25,9 @@ def create_parser():
usage = "kagari [-h] (dl [dl options] | search [search options])" usage = "kagari [-h] (dl [dl options] | search [search options])"
desc = """Client to interact with the Kurisu API. Two main modes: desc = """Client to interact with the Kurisu API. Two main modes:
-dl: downloads the specified file, or a tar file of the entire database -search: searches the database with filters for info on the files
-search: searches the database with filters for info on the files""" -dl: downloads the target file with an ID, or multiple files with filters
To download the entire database, use neither ID nor filters"""
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
usage=usage, usage=usage,
...@@ -52,7 +53,7 @@ def create_parser(): ...@@ -52,7 +53,7 @@ def create_parser():
"-i", "-i",
"--id", "--id",
help='In "dl" mode, if specified, downloads target video file.' help='In "dl" mode, if specified, downloads target video file.'
+ "\nIf absent in this mode, downloads the tar of the whole base." + "\nIf absent in this mode, filter arguments are used instead."
+ '\nIn "search" mode, returns info of the target file.\n ', + '\nIn "search" mode, returns info of the target file.\n ',
) )
...@@ -70,32 +71,32 @@ def create_parser(): ...@@ -70,32 +71,32 @@ def create_parser():
"--check", "--check",
action="store_true", action="store_true",
help='In "dl" mode, first displays info on the targeted' help='In "dl" mode, first displays info on the targeted'
+ "\nfile, and asks for confirmation before downloading.\n ", + "\nfile(s), and asks for confirmation before downloading.\n ",
) )
parser.add_argument( parser.add_argument(
"-a", "-a",
"--author", "--author",
help='In "search" mode, filters by author. (case insensitive)' help='In either mode, filters by author. (case insensitive)',
) )
parser.add_argument( parser.add_argument(
"-c", "-c",
"--category", "--category",
dest="cat", dest="cat",
help='In "search" mode, filters by category.\n ', help='In either mode, filters by category.\n ',
) )
parser.add_argument( parser.add_argument(
"-t", "--type", help='In "search" mode, filters by type.\n ' "-t", "--type", help='In either mode, filters by type.\n '
) )
parser.add_argument( parser.add_argument(
"-s", "-s",
"--string", "--string",
dest="search", dest="search",
help='In "search" mode, filters on the names of sources and songs' help='In either mode, filters on the names of sources and songs'
+ "\nmatching the given string. (case insensitive)\n " + "\nmatching the given string. (case insensitive)\n ",
) )
parser.add_argument( parser.add_argument(
...@@ -110,7 +111,7 @@ def create_parser(): ...@@ -110,7 +111,7 @@ def create_parser():
"-j", "-j",
"--json", "--json",
action="store_true", action="store_true",
help='In "search" mode, output the result as a json.' help='In "search" mode, output the result as a json.',
) )
return parser return parser
...@@ -132,6 +133,44 @@ def make_request(url): ...@@ -132,6 +133,44 @@ def make_request(url):
return response return response
def search_query(args):
"Searches the database with ID or filters, and returns the response json"
url = "https://kurisu.iiens.net/api"
url_values = dict()
# If ID, it's the only parameter needed
if args.id:
url_values["id"] = args.id
# No ID, building the query parameters
else:
for arg_name in ["author", "cat", "type", "search", "random"]:
arg = getattr(args, arg_name)
if arg:
url_values[arg_name] = arg
url_args = urlencode(url_values)
if url_args:
url += "?" + url_args
response = make_request(url)
try:
kara_json = json.loads(response.read().decode("utf-8"))
except ValueError:
emsg = "The response JSON could not be loaded."
print(emsg)
sys.exit(1)
# Handling an error json
if "error" in kara_json:
default_emsg = "An unknown error happened when searching the database."
emsg = kara_json.get("message", default_emsg)
print(emsg)
sys.exit(1)
return kara_json
def build_kara_name(data): def build_kara_name(data):
"Builds the name of the file from the response dictionary" "Builds the name of the file from the response dictionary"
src_name = data["source_name"] src_name = data["source_name"]
...@@ -148,9 +187,13 @@ def build_kara_name(data): ...@@ -148,9 +187,13 @@ def build_kara_name(data):
return kara_name, kara_additional return kara_name, kara_additional
def kara_prompt(kara_string): def kara_prompt(kara_string="", kara_nbr=0):
"Simple yes/no prompt to confirm the download or not" "Simple yes/no prompt to confirm the download or not"
prompt_str = "You are about to download " + kara_string prompt_str = "You are about to download "
if kara_string:
prompt_str += kara_string
else:
prompt_str += f"{kara_nbr} files"
prompt_str += "\nDo you want to proceed ? ([y]/n) " prompt_str += "\nDo you want to proceed ? ([y]/n) "
answers = {"y": True, "n": False, "ye": True, "yes": True, "no": False} answers = {"y": True, "n": False, "ye": True, "yes": True, "no": False}
...@@ -162,49 +205,38 @@ def kara_prompt(kara_string): ...@@ -162,49 +205,38 @@ def kara_prompt(kara_string):
ans = "y" ans = "y"
except KeyboardInterrupt: except KeyboardInterrupt:
ans = "n" ans = "n"
print("\n") print("")
except EOFError: except EOFError:
ans = "y" ans = "y"
return answers[ans] return answers[ans]
def dl_mode(args): def dl_mode(args, kara_json):
"Downloads either the whole database as a tar, or a single video file" "Downloads the targeted files"
# No ID, download the tar of the database kara_id = None
if not args.id: kara_string = ""
url = "https://kurisu.iiens.net/kara.tar" kara_nbr = 0
path = args.path if args.path else os.getcwd()
filename = path + "/kara.tar"
print(f'Downloading and writing archive as "{filename}"') if len(kara_json) == 1:
response = make_request(url) if type(kara_json) is list:
kara_json = kara_json[0]
# Writing the tar file kara_name, kara_additional = build_kara_name(kara_json)
with open(filename, 'wb') as out_file: kara_string = '"' + kara_name + '"' + kara_additional
try: kara_id = kara_json["id"]
shutil.copyfileobj(response, out_file)
except KeyboardInterrupt:
print("\nDownload interrupted by user input.")
else:
print("All done !")
# An ID, download target file
else: else:
search_url = f"https://kurisu.iiens.net/api?id={args.id}" kara_nbr = len(kara_json)
search = make_request(search_url)
kara_data = json.loads(search.read().decode("utf-8"))
kara_name, kara_additional = build_kara_name(kara_data)
# If asked for check, display the prompt # If asked for check, display the prompt
if args.check: if args.check:
kara_string = '"' + kara_name + '"' + kara_additional prompt = kara_prompt(kara_string, kara_nbr)
prompt = kara_prompt(kara_string)
if not prompt: if not prompt:
print("Download cancelled.") print("Download cancelled.")
return return
url = f"https://kurisu.iiens.net/api/download/{args.id}" if kara_id:
url = f"https://kurisu.iiens.net/api/download/{kara_id}"
path = args.path if args.path else os.getcwd() path = args.path if args.path else os.getcwd()
filename = path + "/" + kara_name + ".mkv" filename = path + "/" + kara_name + ".mkv"
...@@ -212,71 +244,64 @@ def dl_mode(args): ...@@ -212,71 +244,64 @@ def dl_mode(args):
response = make_request(url) response = make_request(url)
# Writing the video file # Writing the video file
with open(filename, 'wb') as out_file: with open(filename, "wb") as out_file:
try:
shutil.copyfileobj(response, out_file) shutil.copyfileobj(response, out_file)
except KeyboardInterrupt:
print("\nDownload interrupted by user input.")
else:
print("All done !")
def search_mode(args):
"Performs a search request on the database and returns the answer"
url = "https://kurisu.iiens.net/api"
url_values = dict()
# If ID, it's the only parameter needed
if args.id:
url_values["id"] = args.id
# No ID, building the query parameters
else: else:
for arg_name in ["author", "cat", "type", "search", "random"]: print(f"Download in progress: 0/{kara_nbr}", end="")
arg = getattr(args, arg_name) sys.stdout.flush()
if arg: for curr_nbr, kara in enumerate(kara_json):
url_values[arg_name] = arg kara_id = kara["id"]
kara_name, _ = build_kara_name(kara)
url_args = urlencode(url_values) url = f"https://kurisu.iiens.net/api/download/{kara_id}"
if url_args: path = args.path if args.path else os.getcwd()
url += "?" + url_args filename = path + "/" + kara_name + ".mkv"
response = make_request(url) response = make_request(url)
try: # Writing the video file
kara_json = json.loads(response.read().decode("utf-8")) with open(filename, "wb") as out_file:
except ValueError: shutil.copyfileobj(response, out_file)
emsg = "The response JSON could not be loaded." print(f"\rDownload in progress: {curr_nbr + 1}/{kara_nbr}", end="")
print(emsg) sys.stdout.flush()
sys.exit(1) print("")
print("All done !")
def search_mode(args, kara_json):
"Performs a search request on the database and returns the answer"
if args.json: if args.json:
pretty_output = json.dumps(kara_json, indent=4, ensure_ascii=False) pretty_output = json.dumps(kara_json, indent=4, ensure_ascii=False)
pretty_output += "\n"
else: else:
pretty_output = "" pretty_output = ""
for res in kara_json: for res in kara_json:
new_kara = (" NEW!" if res['is_new'] == "1" else "") new_kara = " NEW!" if res["is_new"] == "1" else ""
output_string = build_kara_name(res) output_info = build_kara_name(res)
output_string = f"[{res['id']}] {output_string[0]}\n" + \ output_string = (
f"{output_string[1]} in {res['author_year']}{new_kara}\n" + \ f"[{res['id']}] {output_info[0]}\n"
f" Size: {res['size']} Kio\n" + f"{output_info[1]} in {res['author_year']}{new_kara}\n"
+ f" Size: {res['size']} Kio\n"
)
pretty_output += output_string pretty_output += output_string
if res['popularity']: if res["popularity"]:
pretty_output += " Popularity: " + res['popularity'] + "\n" pretty_output += " Popularity: " + res["popularity"] + "\n"
if res['upload_comment']: if res["upload_comment"]:
for comment_line in wrap(res['upload_comment'], fix_sentence_endings=True): for comment_line in wrap(
res["upload_comment"], fix_sentence_endings=True
):
pretty_output += " " + comment_line + "\n" pretty_output += " " + comment_line + "\n"
pretty_output += "\n" pretty_output += "\n"
# Displaying the received JSON, or writing it to a file # Displaying the received JSON, or writing it to a file
if not args.path: if not args.path:
print(pretty_output, end='') print(pretty_output, end="")
else: else:
try: try:
with open(args.path, "w") as output_file: with open(args.path, "w") as output_file:
output_file.write(pretty_output) output_file.write(pretty_output)
except OSError as err: except OSError as err:
emsg = "Cannot create/open the search output file: " emsg = "Cannot create/open the search output file: "
emsg += err emsg += str(err)
print(emsg) print(emsg)
sys.exit(1) sys.exit(1)
...@@ -286,10 +311,15 @@ def run(): ...@@ -286,10 +311,15 @@ def run():
parser = create_parser() parser = create_parser()
args = parser.parse_args() args = parser.parse_args()
kara_json = search_query(args)
if args.mode == "dl": if args.mode == "dl":
dl_mode(args) try:
dl_mode(args, kara_json)
except KeyboardInterrupt:
print("\nDownload interrupted by user input.")
elif args.mode == "search": elif args.mode == "search":
search_mode(args) search_mode(args, kara_json)
else: else:
print(f'Unknown mode "{args.mode}". Use either "dl" or "search".') print(f'Unknown mode "{args.mode}". Use either "dl" or "search".')
sys.exit(1) sys.exit(1)
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter