Skip to content

Commit

Permalink
feat(aria2): multiple files/folder download (close alist-org/alist#4283
Browse files Browse the repository at this point in the history
… in #88)

Co-authored-by: Andy Hsu <i@nn.ci>
  • Loading branch information
orangejx and xhofe committed May 27, 2023
1 parent cfd5597 commit 9e072ce
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 23 deletions.
158 changes: 136 additions & 22 deletions src/hooks/useDownload.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
import axios from "axios"
import { local, selectedObjs } from "~/store"
import { notify } from "~/utils"
import { useSelectedLink, useLink, useT } from "."
import { local, password, selectedObjs as _selectedObjs } from "~/store"
import { fsList, notify, pathJoin } from "~/utils"
import { getLinkByDirAndObj, useRouter, useT } from "~/hooks"
import { useSelectedLink } from "~/hooks"
import { Obj } from "~/types"

interface File {
path: string
dir: string
url: string
name: string
}

function isEmpty(value: string | object): boolean {
return value === undefined || value === null || value === ""
}
function isNullOrUndefined(value: string | object): boolean {
return value === undefined || value === null
}

async function getSaveDir(rpc_url: string, rpc_secret: string) {
let save_dir: string = "/downloads/alist"

const resp = await axios.post(rpc_url, {
id: Math.random().toString(),
jsonrpc: "2.0",
method: "aria2.getGlobalOption",
params: ["token:" + rpc_secret ?? ""],
})
console.log(resp)
if (resp.status === 200) {
if (!isEmpty(resp.data.result.dir)) {
save_dir = resp.data.result.dir
}
save_dir = save_dir.endsWith("/") ? save_dir.slice(0, -1) : save_dir
}
return save_dir
}
export const useDownload = () => {
const { rawLinks } = useSelectedLink()
const { rawLink } = useLink()
const t = useT()
const { pathname } = useRouter()
return {
batchDownloadSelected: () => {
const urls = rawLinks(true)
Expand All @@ -15,29 +49,109 @@ export const useDownload = () => {
})
},
sendToAria2: async () => {
const selectedFiles = selectedObjs().filter((obj) => !obj.is_dir)
const { aria2_rpc_url, aria2_rpc_secret, aria2_dir } = local
const selectedObjs = _selectedObjs()
const fetchFolderStructure = async (
pre: string,
obj: Obj
): Promise<File[] | string> => {
if (!obj.is_dir) {
return [
{
path: pathJoin(pre, obj.name),
dir: pre,
url: getLinkByDirAndObj(
pathJoin(pathname(), pre),
obj,
"direct",
true
),
name: obj.name,
},
]
} else {
const resp = await fsList(
pathJoin(pathname(), pre, obj.name),
password()
)
if (resp.code !== 200) {
return resp.message
}
const res: File[] = []
for (const _obj of resp.data.content ?? []) {
const _res = await fetchFolderStructure(
pathJoin(pre, obj.name),
_obj
)
if (typeof _res === "string") {
return _res
} else {
res.push(..._res)
}
}
return res
}
}
const { aria2_rpc_url, aria2_rpc_secret } = local
if (!aria2_rpc_url) {
notify.warning(t("home.toolbar.aria2_not_set"))
return
}
try {
for (const file of selectedFiles) {
const resp = await axios.post(aria2_rpc_url, {
id: Math.random().toString(),
jsonrpc: "2.0",
method: "aria2.addUri",
params: [
"token:" + aria2_rpc_secret ?? "",
[rawLink(file)],
{
out: file.name,
// dir: aria2_dir,
"check-certificate": "false",
},
],
})
console.log(resp)
let save_dir = "/downloads/alist"
// TODO: select dir, but it seems there is no way to get the full path
// if (window.showDirectoryPicker) {
// const dirHandle = await window.showDirectoryPicker()
// save_dir = dirHandle.name
// console.log(dirHandle)
// return
// }
save_dir = await getSaveDir(aria2_rpc_url, aria2_rpc_secret)
let isStartAria2Mission = false
notify.info(`${t("home.package_download.fetching_struct")}`)
for (const obj of selectedObjs) {
const res = await fetchFolderStructure("", obj)

if (typeof res !== "object" || res.length === undefined) {
notify.error(
`${t("home.package_download.fetching_struct_failed")}: ${res}`
)
return res
} else {
for (let key = 0; key < res.length; key++) {
if (
isEmpty(res[key].path) ||
isNullOrUndefined(res[key].dir) ||
isEmpty(res[key].url) ||
isEmpty(res[key].name)
) {
notify.error(
`${t(
"home.package_download.fetching_struct_failed"
)}: ${JSON.stringify(res[key])}`
)
continue
}
if (!isStartAria2Mission) {
isStartAria2Mission = true
notify.info(`${t("home.package_download.downloading")}`)
}
const resp = await axios.post(aria2_rpc_url, {
id: Math.random().toString(),
jsonrpc: "2.0",
method: "aria2.addUri",
params: [
"token:" + aria2_rpc_secret ?? "",
[res[key].url],
{
out: res[key].name,
dir: save_dir + res[key].dir,
"check-certificate": "false",
},
],
})
console.log(resp)
}
}
}
notify.success(t("home.toolbar.send_aria2_success"))
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion src/store/local_settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function isValidKey(
export const initialLocalSettings = {
aria2_rpc_url: "http://localhost:6800/jsonrpc",
aria2_rpc_secret: "",
// aria2_dir: "alist",
// aria2_dir: "/downloads/alist",
}
for (const key in initialLocalSettings) {
if (!local[key] && isValidKey(key, initialLocalSettings)) {
Expand Down

0 comments on commit 9e072ce

Please sign in to comment.