refactor: download login, factor out the download function

This commit is contained in:
Kentai Radiquum 2025-05-15 19:27:35 +05:00
parent 69fb1584e5
commit da5158db56
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
3 changed files with 165 additions and 82 deletions

View file

@ -3,3 +3,4 @@ flaskwebgui
requests requests
Pillow Pillow
flask-socketio flask-socketio
tqdm

View file

@ -1,63 +1,15 @@
import os import os
from . import apiDownload from . import apiDownload
from flask import request, jsonify, send_file, redirect, url_for, abort from flask import request, jsonify
from config import PACKS_FOLDER from config import PACKS_FOLDER
import json import json
from flask_socketio import emit from flask_socketio import emit
import requests
from shared.download import download
def download(path, url, name, total):
r = requests.get(url, stream=True)
if r.status_code != 200:
emit(
"download_current",
{
"status": "error",
"message": f"Got a HTTP ERROR {r.status_code} while downloading {name}",
},
)
return {
"status": "error",
"message": f"Got a HTTP ERROR {r.status_code} while downloading {name}",
}
downloaded = 0
if os.path.exists(f"{path}/{name}"):
emit(
"download_current",
{"status": "ok", "message": f"{name} already downloaded"},
namespace="/",
broadcast=True,
)
return {"status": "ok", "message": f"{name} already downloaded"}
with open(f"{path}/{name}", "wb") as fp:
for data in r.iter_content(chunk_size=1024):
size = fp.write(data)
downloaded += size
emit(
"download_current",
{
"status": "pending",
"total_bytes": total,
"download_bytes": downloaded,
},
namespace="/",
broadcast=True,
)
emit(
"download_current",
{"status": "ok", "message": f"{name} downloaded"},
namespace="/",
broadcast=True,
)
return {
"status": "ok",
"message": f"{name} downloaded",
}
@apiDownload.route("/pack", methods=["POST"]) @apiDownload.route("/pack", methods=["POST"])
def downloadPack(): def downloadPackEndpoint():
pack = {} pack = {}
pack_id = request.json.get("pack_id") pack_id = request.json.get("pack_id")
@ -66,11 +18,33 @@ def downloadPack():
fp.close() fp.close()
mods = pack.get("mods", []) mods = pack.get("mods", [])
total = len(mods) queue = []
for mod in mods:
queue.append(
{
"slug": mod.get("slug"),
"title": mod.get("file").get("title"),
"url": mod.get("file").get("url"),
"filename": mod.get("file").get("filename"),
"size": mod.get("file").get("size"),
}
)
for dep in mod.get("dependencies"):
queue.append(
{
"slug": dep.get("slug"),
"title": dep.get("file").get("title"),
"url": dep.get("file").get("url"),
"filename": dep.get("file").get("filename"),
"size": dep.get("file").get("size"),
}
)
queue = list({mod["slug"]: mod for mod in queue}.values())
total = len(queue)
os.makedirs(f"{PACKS_FOLDER}/{pack_id}/mods", exist_ok=True) os.makedirs(f"{PACKS_FOLDER}/{pack_id}/mods", exist_ok=True)
for i, mod in enumerate(mods): for i, mod in enumerate(queue):
emit( emit(
"download_total", "download_total",
{ {
@ -78,17 +52,37 @@ def downloadPack():
"total": total, "total": total,
"current": i, "current": i,
"title": mod.get("title"), "title": mod.get("title"),
"filename": mod.get("file").get("filename"), "filename": mod.get("filename"),
}, },
namespace="/", namespace="/",
broadcast=True, broadcast=True,
) )
download( status, message = download(
f"{PACKS_FOLDER}/{pack_id}/mods", f"{PACKS_FOLDER}/{pack_id}/mods",
mod.get("file").get("url"), mod.get("url"),
mod.get("file").get("filename"), mod.get("filename"),
mod.get("file").get("size"), mod.get("size"),
) )
if status is False:
emit(
"download_current",
{
"status": "error",
"message": message,
},
namespace="/",
broadcast=True,
)
else:
emit(
"download_current",
{
"status": "ok",
"message": mod.get("filename"),
},
namespace="/",
broadcast=True,
)
emit( emit(
"download_total", "download_total",
@ -111,7 +105,7 @@ def downloadPack():
@apiDownload.route("/mods", methods=["POST"]) @apiDownload.route("/mods", methods=["POST"])
def downloadMods(): def downloadModsEndpoint():
pack = {} pack = {}
pack_id = request.json.get("pack_id") pack_id = request.json.get("pack_id")
mods_slugs = request.json.get("mods") mods_slugs = request.json.get("mods")
@ -121,31 +115,73 @@ def downloadMods():
fp.close() fp.close()
mods = pack.get("mods", []) mods = pack.get("mods", [])
total = len(mods_slugs) queue = []
for slug in mods_slugs:
for mod in mods:
if mod.get("slug") == slug:
queue.append(
{
"slug": mod.get("slug"),
"title": mod.get("file").get("title"),
"url": mod.get("file").get("url"),
"filename": mod.get("file").get("filename"),
"size": mod.get("file").get("size"),
}
)
for dep in mod.get("dependencies"):
queue.append(
{
"slug": dep.get("slug"),
"title": dep.get("file").get("title"),
"url": dep.get("file").get("url"),
"filename": dep.get("file").get("filename"),
"size": dep.get("file").get("size"),
}
)
queue = list({mod["slug"]: mod for mod in queue}.values())
total = len(queue)
os.makedirs(f"{PACKS_FOLDER}/{pack_id}/mods", exist_ok=True) os.makedirs(f"{PACKS_FOLDER}/{pack_id}/mods", exist_ok=True)
for i, slug in enumerate(mods_slugs): for i, mod in enumerate(queue):
for mod in mods: emit(
if mod.get("slug") == slug: "download_total",
emit( {
"download_total", "status": "ok",
{ "total": total,
"status": "ok", "current": i,
"total": total, "title": mod.get("title"),
"current": i, "filename": mod.get("filename"),
"title": mod.get("title"), },
"filename": mod.get("file").get("filename"), namespace="/",
}, broadcast=True,
namespace="/", )
broadcast=True, status, message = download(
) f"{PACKS_FOLDER}/{pack_id}/mods",
download( mod.get("url"),
f"{PACKS_FOLDER}/{pack_id}/mods", mod.get("filename"),
mod.get("file").get("url"), mod.get("size"),
mod.get("file").get("filename"), )
mod.get("file").get("size"), if status is False:
) emit(
"download_current",
{
"status": "error",
"message": message,
},
namespace="/",
broadcast=True,
)
else:
emit(
"download_current",
{
"status": "ok",
"message": mod.get("filename"),
},
namespace="/",
broadcast=True,
)
emit( emit(
"download_total", "download_total",
@ -162,6 +198,6 @@ def downloadMods():
return jsonify( return jsonify(
{ {
"status": "ok", "status": "ok",
"message": f"download of {pack_id} with {total} mods finished", "message": f"download of {total} mods finished",
}, },
) )

46
src/shared/download.py Normal file
View file

@ -0,0 +1,46 @@
import os
from flask_socketio import emit
import requests
from typing import Literal
from tqdm import tqdm
def download(
path, url, name, total
) -> tuple[Literal[True], None] | tuple[Literal[False], str]:
if os.path.exists(f"{path}/{name}"):
return True, None
r = requests.get(url, stream=True)
if r.status_code != 200:
return False, f"Got a HTTP ERROR {r.status_code} while downloading {name}"
totalBytes = int(r.headers.get("Content-Length", total))
if os.getenv("is_cli"):
with open(f"{path}/{name}", "wb") as fp, tqdm(
desc=name.ljust(40),
total=totalBytes,
miniters=100,
unit="b",
unit_scale=True,
unit_divisor=1024,
) as bar:
for data in r.iter_content(chunk_size=1024):
size = fp.write(data)
bar.update(size)
else:
downloaded = 0
with open(f"{path}/{name}", "wb") as fp:
for data in r.iter_content(chunk_size=1024):
size = fp.write(data)
downloaded += size
emit(
"download_current",
{
"status": "pending",
"total_bytes": totalBytes,
"download_bytes": downloaded,
},
namespace="/",
broadcast=True,
)
return True, None