Last active
September 15, 2021 14:35
-
-
Save Sg4Dylan/7eca02e43d585da15c508edc06a79920 to your computer and use it in GitHub Desktop.
配合 phuslu 的 autoindex,实现 nginx 自动列目录导出到 aria2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name NginxAutoindexExporter | |
// @namespace http://tampermonkey.net/ | |
// @version 20180915(0.2) | |
// @description Export link from nginx autoindex to aria2 | |
// @author SgDylan | |
// @match https://example.com/* | |
// @grant none | |
// ==/UserScript== | |
let downloadFileUrl = []; | |
let downloadFolder = []; | |
let iterationDeepth = 3; | |
const basic_auth = "BASIC AUTH BASE64 CODE"; | |
const aria2_rpc = "http://127.0.0.1:6800/jsonrpc"; | |
addCallerLink(); | |
// 绑定界面 | |
function addCallerLink() { | |
// 添加提示区域 | |
var tip = document.createElement("th"); | |
tip.innerHTML = "下载状态: 准备就绪"; | |
tip.id = "ariaTip"; | |
document.getElementsByTagName('th')[0].parentNode.appendChild(tip); | |
// 添加按钮 | |
var link = document.createElement("th"); | |
link.innerHTML = "<button id=\"ariaLink\">Download via Aria2</button>"; | |
document.getElementsByTagName('th')[0].parentNode.appendChild(link); | |
document.getElementById('ariaLink').addEventListener('click', callAria2, false); | |
// 添加单独链接 | |
let pre_line_body = document.getElementsByTagName('a'); | |
for (var index=0; index<pre_line_body.length; index++) { | |
let pre_link = document.createElement("td"); | |
let pre_insert_parent = pre_line_body[index].parentNode.parentNode; | |
if(pre_line_body[index].href.endsWith("/")) { | |
pre_insert_parent.insertBefore(pre_link, pre_insert_parent.childNodes[1]); | |
continue; | |
} | |
// 忽略指向 deluge 的链接 | |
if(pre_line_body[index].href.endsWith("/deluge")) { | |
continue; | |
} | |
pre_link.innerHTML = "<button id=\"precall" + index.toString() + "\">Download</button>"; | |
pre_insert_parent.insertBefore(pre_link, pre_insert_parent.childNodes[1]); | |
document.getElementById('precall'+index.toString()).addEventListener('click', callAria2Once, false); | |
} | |
} | |
// 更新界面 | |
function updateTip(content) { | |
console.log("下载状态: " + content); | |
document.getElementById('ariaTip').innerHTML = "下载状态: " + content; | |
} | |
// 调用 Aria2 模块 | |
function callAria2() { | |
updateTip("开始解析页面"); | |
parseAll(); | |
updateTip("开始召唤Aria2"); | |
var aria2 = new ARIA2(aria2_rpc); | |
for (var index=0; index<downloadFileUrl.length; index++) { | |
//console.log("FilePath: "+downloadFileUrl[index].path+" FileURL: "+downloadFileUrl[index].url); | |
aria2.addUri(downloadFileUrl[index].url, {out: downloadFileUrl[index].path, header: 'Authorization: Basic '+basic_auth}); | |
} | |
updateTip("召唤Aria2完成"); | |
} | |
function callAria2Once(evt) { | |
let pre_index = evt.target.id.substring(7); | |
let pre_link = document.getElementsByTagName('a')[pre_index].href; | |
let pre_path = safeName(document.getElementsByTagName('a')[pre_index].getAttribute("href").replace(/\\+\*?/g,"/")); | |
updateTip("开始召唤Aria2"); | |
console.log("Link:"+pre_link+" Path:"+pre_path); | |
var aria2 = new ARIA2(aria2_rpc); | |
aria2.addUri(pre_link, {out: pre_path, header: 'Authorization: Basic '+basic_auth}); | |
updateTip("召唤Aria2完成"); | |
} | |
// 解析调用 | |
function parseAll() { | |
downloadFileUrl = []; | |
downloadFolder = []; | |
iterationDeepth = 3; | |
updateTip("全页面第一次解析开始"); | |
parseLinkOnce(window.location.href, document.getElementsByTagName('a')); | |
while(downloadFolder.length>0 && iterationDeepth>0) { | |
unpackFolder(); | |
iterationDeepth--; | |
} | |
console.log(downloadFileUrl); | |
} | |
// 解析标签列表 | |
function parseLinkOnce(baseUrl, rawTag) { | |
for (var index=1; index<rawTag.length; index++) { | |
updateTip("解析进度("+index.toString()+"/"+(rawTag.length-1).toString()+")"); | |
if(typeof(rawTag[index].href) === 'undefined') { | |
console.log("Undef ERROR"); | |
continue; | |
} | |
console.log(rawTag[index].href); | |
// 忽略指向根路径的链接 | |
if(rawTag[index].href==window.location.origin+"/") { | |
continue; | |
} | |
// 忽略指向上一层的链接 | |
if(rawTag[index].getAttribute("href")=="../") { | |
continue; | |
} | |
// 忽略指向 deluge 的链接 | |
if(rawTag[index].href.endsWith("/deluge")) { | |
continue; | |
} | |
// 忽略浏览器插件带来的链接 | |
if(rawTag[index].href.startsWith("chrome-extension://")) { | |
continue; | |
} | |
// 忽略 paypal 链接 | |
if(rawTag[index].href.startsWith("https://www.paypal.com/")) { | |
continue; | |
} | |
// 过滤出文件夹 | |
if(rawTag[index].href.endsWith("/")) { | |
downloadFolder.push(baseUrl + rawTag[index].getAttribute("href")); | |
// console.log("DIR: " + baseUrl + rawTag[index].getAttribute("href")); | |
continue; | |
} | |
// 待下载文件 | |
let temp_item = {}; | |
temp_item.url = baseUrl + rawTag[index].getAttribute("href"); | |
temp_item.path = getFullPath(baseUrl) + "/" + safeName(rawTag[index].getAttribute("href").replace(/\\+\*?/g,"/")); | |
downloadFileUrl.push(temp_item); | |
} | |
} | |
// 过滤不合规的字符 | |
function safeName(nameDesu) { | |
return decodeURIComponent(nameDesu).replace(/[\\\|\:\*\"\?\<\>]/g,"_"); | |
} | |
// 处理文件夹路径 | |
function getFullPath(baseUrl) { | |
// 找到任务目录 | |
let basePathName = safeName(window.location.href.substring(document.getElementsByTagName('a')[0].href.length,window.location.href.length-1)); | |
// 如果就在任务目录 | |
if (window.location.href == baseUrl) { | |
return basePathName; | |
} | |
// 如果再更深的目录 | |
let extra_path = baseUrl.substring(window.location.href.length).split('/'); | |
for (var index=0; index<extra_path.length; index++) { | |
extra_path[index] = safeName(extra_path[index]); | |
} | |
let final_path = extra_path.join('/'); | |
final_path = basePathName + "/" + final_path; | |
if (final_path.endsWith('/')) { | |
final_path = final_path.substring(0,final_path.length-1); | |
} | |
return final_path; | |
} | |
// 展开文件夹 | |
function unpackFolder() { | |
for (var index=downloadFolder.length-1; index>=0; index--) { | |
updateTip("文件夹展开进度("+(downloadFolder.length-1-index).toString()+"/"+(downloadFolder.length-1).toString()+")"); | |
let xhr = new XMLHttpRequest(); | |
let target_url = downloadFolder[index]; | |
downloadFolder.splice(index, 1); | |
// 响应本体 | |
// console.log("UnpackFoler URL: " + target_url); | |
xhr.onreadystatechange = function (e) { | |
if (xhr.readyState == 4 && xhr.status == 200) { | |
let tempDiv = document.createElement('div'); | |
tempDiv.innerHTML = xhr.responseText; | |
parseLinkOnce(target_url, tempDiv.getElementsByTagName('a')); | |
} | |
}; | |
xhr.open("GET", target_url, false); | |
xhr.send(); | |
} | |
} | |
var ARIA2 = (function() { | |
const jsonrpc_version = '2.0'; | |
function get_auth(url) { | |
return url.match(/^(?:(?![^:@]+:[^:@\/]*@)[^:\/?#.]+:)?(?:\/\/)?(?:([^:@]*(?::[^:@]*)?)?@)?/)[1]; | |
} | |
function request(jsonrpc_path, method, params) { | |
let xhr = new XMLHttpRequest(); | |
let auth = get_auth(jsonrpc_path); | |
jsonrpc_path = jsonrpc_path.replace(/^((?![^:@]+:[^:@\/]*@)[^:\/?#.]+:)?(\/\/)?(?:(?:[^:@]*(?::[^:@]*)?)?@)?(.*)/, '$1$2$3'); // auth string not allowed in url for firefox | |
let request_obj = { | |
jsonrpc: jsonrpc_version, | |
method: method, | |
id: (new Date()).getTime().toString(), | |
}; | |
if (params) request_obj.params = params; | |
if (auth && auth.indexOf('token:') === 0) params.unshift(auth); | |
xhr.open("POST", jsonrpc_path+"?tm="+(new Date()).getTime().toString(), true); | |
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); | |
if (auth && auth.indexOf('token:') !== 0) { | |
xhr.setRequestHeader("Authorization", "Basic "+btoa(auth)); | |
} | |
xhr.send(JSON.stringify(request_obj)); | |
} | |
return function(jsonrpc_path) { | |
this.jsonrpc_path = jsonrpc_path; | |
this.addUri = function (uri, options) { | |
request(this.jsonrpc_path, 'aria2.addUri', [[uri, ], options]); | |
}; | |
return this; | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment