Greasy Fork is available in English.
115原石会员批量转存助手,可批量转存>500个文件
当前为
// ==UserScript==
// @name 115原石会员转存助手-突破500限制
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 115原石会员批量转存助手,可批量转存>500个文件
// @author @ejmkod
// @match *://115.com/s/*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function() {
'use strict';
GM_addStyle(`
#batchTransferButton {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
z-index: 1000;
}
#batchTransferButton:hover {
background-color: #0056b3;
}
#startIndexInputLabel, #cidInputLabel, #batchSizeInputLabel,
#startIndexInput, #cidInput, #batchSizeInput {
position: fixed;
z-index: 1000;
}
#cidInputLabel {
bottom: 140px;
right: 200px;
}
#cidInput {
bottom: 140px;
right: 20px;
}
#batchSizeInputLabel {
bottom: 100px;
right: 200px;
}
#batchSizeInput {
bottom: 100px;
right: 20px;
}
#startIndexInputLabel {
bottom: 60px;
right: 200px;
}
#startIndexInput {
bottom: 60px;
right: 20px;
}
#progressOverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
color: white;
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
display: none;
flex-direction: column;
}
#progressBar {
width: 80%;
height: 20px;
background: #555;
border-radius: 10px;
overflow: hidden;
margin-bottom: 10px;
position: relative;
}
#progressFill {
height: 100%;
width: 0;
background: #4caf50;
transition: width 0.2s;
}
#progressText {
position: absolute;
width: 100%;
text-align: center;
top: 50%;
transform: translateY(-50%);
color: white;
font-weight: bold;
}
#toast {
visibility: hidden;
min-width: 250px;
margin-left: -125px;
background-color: #333;
color: white;
text-align: center;
border-radius: 2px;
padding: 16px;
position: fixed;
z-index: 1001;
left: 50%;
bottom: 30px;
font-size: 17px;
}
#toast.show {
visibility: visible;
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
animation: fadein 0.5s, fadeout 0.5s 2.5s;
}
@-webkit-keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
@keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
@-webkit-keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
@keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
#errorLabel {
position: fixed;
bottom: 170px;
right: 20px;
color: red;
z-index: 1000;
display: none;
}
`);
const cidInputLabel = document.createElement('label');
cidInputLabel.id = 'cidInputLabel';
cidInputLabel.for = 'cidInput';
cidInputLabel.innerText = 'CID: ';
const startIndexInputLabel = document.createElement('label');
startIndexInputLabel.id = 'startIndexInputLabel';
startIndexInputLabel.for = 'startIndexInput';
startIndexInputLabel.innerText = 'Start Index: ';
const batchSizeInputLabel = document.createElement('label');
batchSizeInputLabel.id = 'batchSizeInputLabel';
batchSizeInputLabel.for = 'batchSizeInput';
batchSizeInputLabel.innerText = 'Batch Size: ';
const cidInput = document.createElement('input');
cidInput.id = 'cidInput';
cidInput.type = 'text';
cidInput.placeholder = 'Enter CID';
const startIndexInput = document.createElement('input');
startIndexInput.id = 'startIndexInput';
startIndexInput.type = 'number';
startIndexInput.placeholder = 'Enter start index';
startIndexInput.value = '0';
const batchSizeInput = document.createElement('input');
batchSizeInput.id = 'batchSizeInput';
batchSizeInput.type = 'number';
batchSizeInput.placeholder = 'Enter batch size';
batchSizeInput.value = '20';
const button = document.createElement('button');
button.id = 'batchTransferButton';
button.innerText = '批量转存';
const progressOverlay = document.createElement('div');
progressOverlay.id = 'progressOverlay';
progressOverlay.innerHTML = `
<div id="progressBar">
<div id="progressFill"></div>
<div id="progressText">转存中请稍后,当前进度 0%</div>
</div>
`;
const label = document.createElement('label');
label.id = 'errorLabel';
const toast = document.createElement('div');
toast.id = 'toast';
document.body.appendChild(cidInputLabel);
document.body.appendChild(cidInput);
document.body.appendChild(batchSizeInputLabel);
document.body.appendChild(batchSizeInput);
document.body.appendChild(startIndexInputLabel);
document.body.appendChild(startIndexInput);
document.body.appendChild(button);
document.body.appendChild(progressOverlay);
document.body.appendChild(label);
document.body.appendChild(toast);
function showToastAndLabel(message, index) {
showToast(message);
label.innerText = message;
label.style.display = 'block';
}
function showToast(message) {
toast.innerText = message;
toast.className = "show";
setTimeout(() => { toast.className = toast.className.replace("show", ""); }, 3000);
}
async function sendPostRequest(fileid, currentIndex) {
const formData = new FormData();
formData.append("cid", cidInput.value);
formData.append("user_id", document.querySelector('span[rel="user_id"]').textContent);
formData.append("share_code", new URL(location).pathname.replace('/s/', ''));
formData.append("receive_code", document.querySelector('em[rel="receive_code"]').textContent);
formData.append("file_id", fileid);
console.log('formData', JSON.stringify(Object.fromEntries(formData.entries())));
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST",
url: "https://webapi.115.com/share/receive",
data: formData,
onload: function(response) {
try {
const jsonResponse = JSON.parse(response.responseText);
console.log('Parsed JSON Response:', JSON.stringify(jsonResponse));
if (jsonResponse.state === false) {
showToastAndLabel(`转存错误:${jsonResponse.error},当前index ${currentIndex}`, currentIndex);
reject('Stop request due to error 4100013');
} else {
resolve();
}
} catch (error) {
console.error('Error parsing JSON:', error);
reject(error);
}
},
onerror: function(error) {
console.error('Error:', error);
reject(error);
}
});
});
}
async function processACidAttributes() {
// 检查 CID 输入是否为空
if (!cidInput.value.trim()) {
showToast('先输入CID');
return;
}
// Click the button with id="js_load_all"
document.getElementById('js_load_all').click();
progressOverlay.style.display = 'flex';
document.getElementById('progressText').innerText = `转存中请稍后...`;
// Wait for 3 seconds
await new Promise(resolve => setTimeout(resolve, 3000));
const liTags = document.querySelectorAll('#js-list li');
const aCidList = [];
liTags.forEach(a => {
if (a.hasAttribute('fid') && a.getAttribute('fid')) {
aCidList.push(a.getAttribute('fid'));
}else if(a.hasAttribute('cid')){
aCidList.push(a.getAttribute('cid'));
}
});
let currentIndex = parseInt(startIndexInput.value, 10);
const batchSize = parseInt(batchSizeInput.value, 10);
for (let i = currentIndex; i < aCidList.length; i += batchSize) {
const fileid = aCidList.slice(i, i + batchSize).join(',');
try {
await sendPostRequest(fileid, i);
} catch (error) {
console.error(error);
break;
}
currentIndex = i + batchSize;
const progress = Math.min(100, (currentIndex / aCidList.length) * 100);
document.getElementById('progressFill').style.width = progress + '%';
document.getElementById('progressText').innerText = `转存中请稍后,当前进度 ${progress.toFixed(2)}%`;
await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 4000) + 3000)); // Sleep 3-7 seconds
}
progressOverlay.style.display = 'none';
}
button.addEventListener('click', processACidAttributes);
})();