// ==UserScript==
// @name 百度网盘不限速下载-KDown🔥🔥🔥
// @namespace https://kdown.moiu.net
// @description 一款百度云加速程序,加速永无止境,无视黑号
// @version 1.5.6
// @license MIT
// @icon https://upload.moiu.net/MoTeam-CDN-img/logo.png
// @resource https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-ms/limonte-sweetalert2/11.4.4/sweetalert2.min.css
// @require https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/limonte-sweetalert2/11.4.4/sweetalert2.all.min.js
// @require https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-ms/jquery/3.6.0/jquery.min.js
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_setClipboard
// @match *://pan.baidu.com/disk/home*
// @match *://yun.baidu.com/disk/home*
// @match *://pan.baidu.com/disk/main*
// @match *://yun.baidu.com/disk/main*
// @connect moiu.cn
// @connect jsdelivr.net
// @connect baidu.com
// ==/UserScript==
(() => {
let aria2Url = localStorage.getItem('aria2Url') || 'http://127.0.0.1:16800/jsonrpc';
let userAgent = 'netdisk'; // 默认的 UA,在解析接口返回数据后会更新
let currentLinkIndex = 0;
let downloadLinks = [];
GetNotify();
if (window.location.pathname === "/disk/home") {
window.location.replace("/disk/main");
}
AddElement();
function GetNotify() {
GM_xmlhttpRequest({
method: "GET",
url: "https://api.moiu.cn/JavaScript/users/info_v2",
onload: function(response) {
try {
const jsondata = JSON.parse(response.responseText);
const { code, message, ua, gg, open } = jsondata;
if (open === 1 && code === 200) {
Swal.fire({
icon: "info",
title: gg,
text: message,
confirmButtonText: "关闭",
});
}
} catch (e) {
console.error("Error fetching announcement:", e);
}
},
});
}
let userInfo = {};
function fetchUserInfo() {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: "https://pan.baidu.com/rest/2.0/membership/user/info?method=query&clienttype=0&app_id=250528",
onload: function(response) {
try {
const data = JSON.parse(response.responseText);
resolve(data.user_info);
} catch (error) {
reject(error);
}
},
onerror: function(error) {
reject(error);
}
});
});
}
async function getUserInfoOnPageLoad() {
try {
const data = await fetchUserInfo();
userInfo = data;
console.log("User info fetched on page load:", userInfo);
} catch (error) {
console.error("Error fetching user info on page load:", error);
}
}
function AddElement() {
if (document.getElementById("KDown") === null) {
const toolbar = document.querySelector("div.wp-s-agile-tool-bar__header");
if (toolbar) {
const newButton = document.createElement("button");
newButton.id = "KDown";
newButton.className = "u-button nd-file-list-toolbar-action-item u-button--primary";
newButton.style.marginRight = "8px";
newButton.innerText = "KDown";
toolbar.prepend(newButton);
const statusButton = document.createElement("button");
statusButton.id = "KDownStatus";
statusButton.className = "u-button nd-file-list-toolbar-action-item u-button--primary";
statusButton.style.marginRight = "8px";
statusButton.innerText = "KDown Status";
toolbar.prepend(statusButton);
newButton.addEventListener("click", handleKDownClick);
statusButton.addEventListener("click", handleKDownStatusClick);
} else {
setTimeout(AddElement, 100);
}
} else {
console.log("KDown button already added.");
}
}
async function handleKDownClick() {
console.log("KDown button clicked.");
let selectedElements = document.querySelectorAll(".wp-s-pan-table__body-row.mouse-choose-item.selected, .wp-s-file-grid-list__item.text-center.cursor-p.mouse-choose-item.is-checked, .wp-s-file-contain-list__item.text-center.cursor-p.mouse-choose-item.is-checked");
let selectedIds = Array.from(selectedElements).map(item => item.getAttribute("data-id"));
console.log("Selected elements:", selectedElements);
console.log("Selected IDs:", selectedIds);
if (selectedIds.length === 0) {
Swal.fire({
showConfirmButton: true,
title: '系统提示',
text: '请选择需要下载的文件',
icon: 'error'
});
return;
}
if (selectedIds.length > 1) {
Swal.fire({
showConfirmButton: true,
title: '系统提示',
text: '暂时只能下载一个文件',
icon: 'error'
});
return;
}
let selectedItems = Array.from(selectedElements);
if (selectedItems.some(item => item.dataset.isdir === "true")) {
Swal.fire({
title: '系统提示',
text: '请不要选择文件夹解析,因为还没学会.',
icon: 'error'
});
return;
}
const { value: requestType } = await Swal.fire({
title: '选择请求类型',
html: `
<div>
<input type="radio" id="cloud" name="requestType" value="cloud" checked>
<label for="cloud">1号接口(无法保证全天稳定,推荐2号接口)</label>
</div>
<div>
<input type="radio" id="local" name="requestType" value="local">
<label for="local">2号接口(稳定,加速需要自带SVIP账号)</label>
</div>
`,
showCancelButton: true,
cancelButtonText: '取消',
preConfirm: () => {
const requestType = document.querySelector('input[name="requestType"]:checked').value;
return requestType;
}
});
if (!requestType) {
Swal.fire("提示", "您需要选择一个请求类型来继续", "info");
return;
}
const { value: password } = await Swal.fire({
title: '输入密码',
input: 'password',
inputLabel: '使用前请先获取密码,地址(https://pan.quark.cn/s/11d137f012ef)',
inputPlaceholder: '这也是为了回老本,没办法,理解下',
inputAttributes: {
maxlength: 12,
autocapitalize: 'off',
autocorrect: 'off'
}
});
if (!password) {
Swal.fire("提示", "需要密码来继续", "info");
return;
}
Swal.fire({
title: "正在获取下载链接...",
onBeforeOpen: () => {
Swal.showLoading();
}
});
if (requestType === 'local') {
try {
const rootListResponse = await fetchBaiduRootFileList();
const rootFileList = rootListResponse.list;
console.log("Baidu root file list response:", rootFileList);
const myResourceFolderExists = rootFileList.some(file => file.path === "/我的资源");
if (!myResourceFolderExists) {
Swal.fire({
title: '错误',
text: '似乎你解析的文件没有放在 我的资源 文件夹,或者你根本没创建这个文件夹',
icon: 'error'
});
return;
}
let pathLocal;
let filename;
try {
const listResponse = await fetchBaiduFileList();
const fileList = listResponse.list;
console.log("Baidu file list response:", fileList);
fileList.forEach(file => {
if (selectedIds.includes(file.fs_id.toString())) {
pathLocal = file.path;
filename = file.server_filename;
}
});
if (!pathLocal || !filename) {
Swal.fire("错误", "未找到匹配的文件或文件名", "error");
return;
}
console.log("Matched file path:", pathLocal);
console.log("Matched file name:", filename);
// 生成下载链接的请求
const bdstoken = await getBdsToken();
if (!bdstoken) {
Swal.fire("错误", "无法获取bdstoken", "error");
return;
}
const queryParams = new URLSearchParams({
"target": JSON.stringify([pathLocal]),
"dlink": 1,
"channel": "chunlei",
"web": 1,
"app_id": 250528,
"bdstoken": bdstoken,
"logid": "QzBQUQORDY1N0E0QzMzNzEyRDDBNjZDZjc1NzJFQUY6Rkc9MQ%3D%3D",
"clienttype": 0
});
const requestUrl = `https://pan.baidu.com/api/filemetas?${queryParams.toString()}`;
// 发起请求以获取下载链接
const downloadLinkResponse = await fetch(requestUrl);
const downloadLinkData = await downloadLinkResponse.json();
if (downloadLinkData.errno === 0) {
console.log("Download link data:", downloadLinkData);
const downloadLink = downloadLinkData.info[0].dlink;
// 显示下载链接
Swal.fire({
icon: 'success',
title: '下载链接获取成功',
html: `<a href="${downloadLink}" target="_blank">${downloadLink}</a>`,
showCancelButton: true,
cancelButtonText: '关闭',
confirmButtonText: '复制链接',
preConfirm: async () => {
try {
await navigator.clipboard.writeText(downloadLink);
Swal.fire({
icon: 'success',
title: '已复制',
text: '下载链接已复制到剪贴板',
showConfirmButton: false,
timer: 1500,
});
} catch (err) {
console.error("Failed to copy: ", err);
Swal.fire("复制失败", "无法将链接复制到剪贴板", "error");
}
},
willClose: () => {
return false; // 防止弹窗关闭
},
allowOutsideClick: false, // 防止外部点击关闭
allowEscapeKey: false, // 防止按 ESC 关闭
allowEnterKey: false // 防止按回车键关闭
});
} else {
Swal.fire("错误", "无法获取下载链接", "error");
}
} catch (error) {
Swal.fire("错误", "无法获取文件列表", "error");
console.error("Error fetching file list:", error);
return;
}
} catch (error) {
Swal.fire("错误", "无法获取根目录文件列表", "error");
console.error("Error fetching root directory file list:", error);
return;
}
} else if (requestType === 'cloud') {
try {
const bdstoken = await getBdsToken();
const shareResponse = await shareFiles(bdstoken, selectedIds);
const shorturl = extractShortUrl(shareResponse.link);
if (!shorturl) {
Swal.fire("错误", "无法提取shorturl", "error");
return;
}
const wxlistResponse = await callWxlistApi(shorturl, password);
const extractedData = extractWxlistData(wxlistResponse);
const parseResponseData = await postToSaveApi(extractedData, password, userInfo.uk, shorturl);
userAgent = parseResponseData.ua || userAgent; // 从解析接口的 data 中提取 ua
downloadLinks = [parseResponseData.dlink, ...parseResponseData.urls]; // 获取下载链接
// 显示下载链接并显示动态获取到的 UA
showDownloadLink();
} catch (error) {
Swal.fire("错误", error.statusText || "处理过程中出现错误", "error");
console.error("Error:", error);
}
}
}
function showDownloadLink() {
Swal.fire({
icon: 'success',
title: '下载链接获取成功',
html: `
<div style="border: 1px solid #ddd; padding: 10px; margin-bottom: 10px;">
<a href="${downloadLinks[currentLinkIndex]}" target="_blank">${downloadLinks[currentLinkIndex].substring(0, 50)}...</a>
</div>
<div style="border: 1px solid #ddd; padding: 10px; margin-bottom: 10px;">
<div>当前的 UA:</div>
<div>${userAgent}</div>
</div>`,
showCancelButton: true,
cancelButtonText: '关闭',
confirmButtonText: '复制链接',
showDenyButton: true,
denyButtonText: '发送到 Aria2',
footer: `<button id="SetAria2" class="swal2-deny">设置 Aria2 地址</button><button id="ChangeLink" class="swal2-deny">换个下载链接</button>`,
preConfirm: async () => {
try {
await navigator.clipboard.writeText(downloadLinks[currentLinkIndex]);
Swal.fire({
icon: 'success',
title: '已复制',
text: '下载链接已复制到剪贴板',
showConfirmButton: false,
timer: 1500,
});
} catch (err) {
console.error("Failed to copy: ", err);
Swal.fire("复制失败", "无法将链接复制到剪贴板", "error");
}
},
willClose: () => {
return false; // 防止弹窗关闭
},
allowOutsideClick: false, // 防止外部点击关闭
allowEscapeKey: false, // 防止按 ESC 关闭
allowEnterKey: false // 防止按回车键关闭
}).then((result) => {
if (result.isDenied) {
sendToAria2([downloadLinks[currentLinkIndex]]);
}
});
document.getElementById("SetAria2").addEventListener("click", setAria2Config);
document.getElementById("ChangeLink").addEventListener("click", () => {
if (currentLinkIndex < downloadLinks.length - 1) {
currentLinkIndex++;
showDownloadLink();
}
if (currentLinkIndex === downloadLinks.length - 1) {
document.getElementById("ChangeLink").disabled = true;
document.getElementById("ChangeLink").innerText = "没有更多链接";
}
});
}
function sendToAria2(downloadLinks) {
const aria2Config = {
jsonrpc: "2.0",
method: "aria2.addUri",
id: Date.now(),
params: [
downloadLinks,
{
header: [`User-Agent: ${userAgent}`] // 使用动态获取到的 UA
}
]
};
fetch(aria2Url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(aria2Config)
})
.then(response => response.json())
.then(data => {
if (data.error) {
console.error("Aria2 Error:", data.error.message);
} else {
console.log("Aria2 Download Added:", data.result);
}
})
.catch(fetchError => {
console.error("Fetch Error:", fetchError);
});
}
function setAria2Config() {
Swal.fire({
title: '设置 Aria2 地址',
input: 'text',
inputLabel: 'Aria2 RPC 地址',
inputValue: aria2Url,
showCancelButton: true,
inputValidator: (value) => {
if (!value) {
return '地址不能为空!';
}
}
}).then((result) => {
if (result.isConfirmed) {
aria2Url = result.value;
localStorage.setItem('aria2Url', aria2Url);
Swal.fire('成功!', 'Aria2 地址已保存', 'success');
}
});
}
async function getBdsToken() {
var htmlString = $("html").html();
var regex = /"bdstoken":"(\w+)"/;
var match = regex.exec(htmlString);
console.log("bdstoken:", match ? match[1] : null);
return match ? match[1] : null;
}
async function shareFiles(bdstoken, selectedIds) {
const bdpassword = "7777";
console.log("Sharing files with bdstoken:", bdstoken, "selectedIds:", selectedIds, "bdpassword:", bdpassword);
return $.post("https://pan.baidu.com/share/set?channel=chunlei&bdstoken=" + bdstoken, {
period: 1,
pwd: bdpassword,
eflag_disable: true,
channel_list: "[]",
schannel: 4,
fid_list: JSON.stringify(selectedIds)
}).then(response => response);
}
function extractShortUrl(link) {
const regex = /https:\/\/pan\.baidu\.com\/s\/([a-zA-Z0-9-_]+)/;
const match = regex.exec(link);
console.log("Extracted short URL:", match ? match[1] : null);
return match ? match[1] : null;
}
function callWxlistApi(shorturl, password) {
console.log("Calling Wxlist API with shorturl:", shorturl, "password:", password);
const bdpassword = "7777";
return new Promise((resolve, reject) => {
const url = "https://api.moiu.cn/api/List";
const formParams = {
"surl": shorturl,
"dir": "/",
"password": password,
"pwd": bdpassword
};
$.ajax({
type: "POST",
url: url,
data: formParams,
success: function(response) {
console.log("Wxlist API response:", response);
resolve(response);
},
error: function(xhr, status, error) {
console.error("Error calling Wxlist API:", xhr, status, error);
reject({
status: xhr.status,
statusText: xhr.statusText
});
}
});
});
}
function extractWxlistData(responseBody) {
const data = responseBody.data;
console.log("Extracted data from Wxlist response:", data);
return {
uk: data.uk,
shareid: data.shareid,
randsk: data.randsk,
list: data.list,
fsidlist: data.list.map(item => item.fs_id.toString()),
size: data.list[0]?.size || 0, // 提取第一个列表项的 size 属性
filename: data.list[0]?.server_filename || 0, // 提取第一个列表项的 filename 属性
};
}
function postToSaveApi(data, password, userid, shorturl) {
const requestData = {
fsidlist: String(data.list[0].fs_id),
sekey: data.randsk,
uk: data.uk,
shareid: data.shareid,
password,
surl: shorturl,
userid,
size: data.size,
filename: data.filename // 添加 filename 参数
};
console.log("Prepared request data for Save API:", requestData);
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST",
url: "https://api.moiu.cn/api/v0/parse",
headers: {
"Content-Type": "application/json"
},
data: JSON.stringify(requestData),
onload: function(response) {
const responseData = JSON.parse(response.responseText);
console.log("Save API response:", responseData);
if (responseData.code !== 200) {
Swal.fire("错误", responseData.message, "error");
reject({
status: response.status,
statusText: responseData.message
});
} else {
resolve(responseData.data); // 直接返回data对象
}
},
onerror: function(response) {
const errorMessage = JSON.parse(response.responseText).message || '网络错误';
Swal.fire("错误", errorMessage, "error");
console.error("Error posting to Save API:", response);
reject({
status: response.status,
statusText: errorMessage
});
}
});
});
}
async function handleKDownStatusClick() {
Swal.fire("检查中...", "正在检查服务器状态,请稍候...", "info");
GM_xmlhttpRequest({
method: "GET",
url: "https://api.moiu.cn/api/v0/status",
onload: function(response) {
try {
const data = JSON.parse(response.responseText);
const { code, message } = data;
console.log("Server status response:", data);
if (code === 200) {
Swal.fire({
icon: "success",
title: "服务器状态",
text: message,
});
} else if (code === 201) {
Swal.fire({
icon: "error",
title: "服务器状态",
text: message,
});
} else {
Swal.fire({
icon: "warning",
title: "服务器状态",
text: "未知状态",
});
}
} catch (error) {
Swal.fire("错误", "处理服务器响应时发生错误", "error");
console.error("Error handling server response:", error);
}
},
onerror: function(error) {
Swal.fire("错误", "无法连接到服务器", "error");
console.error("Error connecting to server:", error);
},
});
}
async function fetchBaiduRootFileList() {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: "https://pan.baidu.com/api/list?clienttype=0&app_id=250528&web=1&order=time&desc=1&dir=%2F&num=100&page=1",
onload: function(response) {
try {
const data = JSON.parse(response.responseText);
if (data.errno === 0) {
resolve(data);
} else {
reject(new Error("API 返回错误: " + data.errno));
}
} catch (error) {
reject(error);
}
},
onerror: function(error) {
reject(error);
}
});
});
}
async function fetchBaiduFileList() {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: "https://pan.baidu.com/api/list?clienttype=0&app_id=250528&web=1&order=time&desc=1&dir=%2F%E6%88%91%E7%9A%84%E8%B5%84%E6%BA%90&num=100&page=1",
onload: function(response) {
try {
const data = JSON.parse(response.responseText);
if (data.errno === 0) {
resolve(data);
} else {
reject(new Error("API 返回错误: " + data.errno));
}
} catch (error) {
reject(error);
}
},
onerror: function(error) {
reject(error);
}
});
});
}
// 在页面加载完成后请求用户信息
getUserInfoOnPageLoad();
})();