️ Rewrite download manager

This commit is contained in:
zhbaor 2023-03-04 13:53:05 +08:00
parent e47a92b77e
commit afc9c112cb
4 changed files with 68 additions and 53 deletions

View file

@ -23,9 +23,5 @@ def get_progress():
@app.post("/download") @app.post("/download")
def download(): def download():
parent_dir = Path(request.json["parent_dir"]) parent_dir = Path(request.json["parent_dir"])
id = request.json["id"] manager.download(parent_dir)
try:
manager.download(id, parent_dir)
return "OK" return "OK"
except:
return "Not ready"

View file

@ -11,33 +11,8 @@ const state_list = ref([]);
const auto_download = ref(false); const auto_download = ref(false);
onMounted(() => {
setInterval(() => {
axios.get("http://localhost:8000/progress").then((resp) => {
state_list.value = resp.data;
for (const [i, s] of state_list.value.entries()) {
if (
auto_download.value &&
counter.value.downloading == 0 &&
s.number &&
s.title &&
s.total == 0
) {
axios.post("http://localhost:8000/download", {
id: i,
parent_dir: "/home/zhao/Desktop/tmp",
});
break;
}
}
});
}, 500);
});
const counter = computed(() => { const counter = computed(() => {
if (state_list.value.length == 0) { const total = state_list.value.length;
return { fetching: true, downloading: false };
}
let ready = 0; let ready = 0;
let downloading = 0; let downloading = 0;
let finished = 0; let finished = 0;
@ -45,30 +20,55 @@ const counter = computed(() => {
if (s.number && s.title && s.total == 0) { if (s.number && s.title && s.total == 0) {
ready++; ready++;
} else if (s.received < s.total) { } else if (s.received < s.total) {
ready++;
downloading++; downloading++;
} else if (s.total <= s.received && s.total != 0) { } else if (s.total != 0 && s.received == s.total) {
ready++;
finished++; finished++;
} }
}); });
return { ready: ready, downloading: downloading, finished: finished }; return {
total: total,
ready: ready,
downloading: downloading,
finished: finished,
};
}); });
const progress_info = computed(() => { const progress_info = computed(() => {
const total = state_list.value.length; const { ready, downloading, finished, total } = counter.value;
const { ready, downloading, finished } = counter.value;
const fetch_info = "Fetching Information"; const fetch_info = "Fetching Information";
const ready_info = "Ready";
const download_info = "Downloading"; const download_info = "Downloading";
const finished_info = "Downloads Complete"; const finished_info = "Downloads Complete";
if (total == 0) { if (ready < total) {
return { display: fetch_info, finished: 0, total: 0 };
} else if (ready < total && downloading == 0 && finished == 0) {
return { display: fetch_info, finished: ready, total: total }; return { display: fetch_info, finished: ready, total: total };
} else if (finished + downloading + ready == total && finished < total) { } else if (ready == total && !downloading && !finished) {
return { display: download_info, finished: finished + downloading, total: total }; return { display: ready_info, finished: ready, total: total };
} else if (finished < total) {
return {
display: download_info,
finished: finished,
total: total,
};
} else if (finished == total) { } else if (finished == total) {
return { display: finished_info, finished: finished, total: total }; return { display: finished_info, finished: finished, total: total };
} }
}); });
function start_download() {
axios.post("http://localhost:8000/download", {
parent_dir: "/home/zhao/Desktop/tmp",
});
}
onMounted(() => {
setInterval(() => {
axios.get("http://localhost:8000/progress").then((resp) => {
state_list.value = resp.data;
});
}, 200);
});
</script> </script>
<template> <template>
@ -87,7 +87,8 @@ const progress_info = computed(() => {
</div> </div>
<DownloadButton <DownloadButton
@enable-download="auto_download = true" @enable-download="auto_download = true"
v-if="counter.ready == state_list.length" v-if="!auto_download && counter.ready == counter.total"
@click="start_download"
></DownloadButton> ></DownloadButton>
<TotalProgress v-else v-bind="progress_info"></TotalProgress> <TotalProgress v-else v-bind="progress_info"></TotalProgress>
</div> </div>

View file

@ -1,13 +1,22 @@
from video import Video from video import Video
from threading import Thread from threading import Thread
from queue import SimpleQueue
from sanitize_filename import sanitize from sanitize_filename import sanitize
from pathlib import Path from pathlib import Path
from time import sleep
class Manager: class Manager:
def __init__(self): def __init__(self):
self.video_list: list[Video] = [] self.video_list: list[Video] = []
self.bvid_set = set() self.bvid_set = set()
self.queue = SimpleQueue()
def get_info_worker(self):
while not self.queue.empty():
video: Video = self.queue.get()
video.get_info()
sleep(5)
def add_videos_by_number(self, video_numbers: list[str]): def add_videos_by_number(self, video_numbers: list[str]):
for video_number in video_numbers: for video_number in video_numbers:
@ -18,19 +27,23 @@ class Manager:
if (bvid := video.v.get_bvid()) not in self.bvid_set: if (bvid := video.v.get_bvid()) not in self.bvid_set:
self.bvid_set.add(bvid) self.bvid_set.add(bvid)
self.video_list.append(video) self.video_list.append(video)
Thread(target=video.get_info).start() self.queue.put(video)
Thread(target=self.get_info_worker).start()
def download(self, id: int, parent_dir: str | Path = Path(".")): def download_worker(self, parent_dir: Path):
while not self.queue.empty():
video: Video = self.queue.get()
filename = sanitize(video.title) + ".m4a"
video.download(parent_dir / filename)
sleep(5)
def download(self, parent_dir: str | Path = Path(".")):
if isinstance(parent_dir, str): if isinstance(parent_dir, str):
parent_dir = Path(parent_dir) parent_dir = Path(parent_dir)
if not 0 <= id < len(self.video_list): for video in self.video_list:
raise Exception(f"id ({id}) out of range!") print(video)
video = self.video_list[id] self.queue.put(video)
if not hasattr(video, "title"): Thread(target=self.download_worker, args=(parent_dir,)).start()
raise Exception(f"No information for video {video.number}")
filename = sanitize(video.title) + ".m4a"
t = Thread(target=video.download, args=(parent_dir / filename,))
t.start()
def get_progress(self): def get_progress(self):
return [ return [

View file

@ -1,8 +1,13 @@
from .exceptions import * from .exceptions import *
from bilibili_api import video, sync, HEADERS from bilibili_api import video, sync
from httpx import stream from httpx import stream
from os import PathLike from os import PathLike
HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0",
"Referer": "https://www.bilibili.com",
}
class Video: class Video:
def __init__(self, video_number: str): def __init__(self, video_number: str):