Compare commits
7 Commits
a3216891ff
...
2bff5239ce
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bff5239ce | ||
|
|
71b4fca6c2 | ||
|
|
b6aca2e2e9 | ||
|
|
996210f8c7 | ||
|
|
de6e4356a4 | ||
|
|
da7a5e93c8 | ||
|
|
50d01bb4d8 |
20
README.md
@ -29,13 +29,13 @@
|
||||
> ⛔️⛔️⛔️ 注意!资源不会每时每刻更新,**严禁设定过高的定时运行频率!** 以免账号风控和给夸克服务器造成不必要的压力。雪山崩塌,每一片雪花都有责任!
|
||||
|
||||
> [!NOTE]
|
||||
> 因不想当客服处理各种使用咨询,即日起 Issues 关闭,如果你发现了 bug 、有好的想法或功能建议,欢迎通过 PR 和我对话,谢谢!
|
||||
> 开发者≠客服,开源免费≠帮你解决使用问题;本项目Wiki和已经相对完善,遇到问题请先翻阅 Issues 和 Wiki ,请勿盲目发问。
|
||||
|
||||
## 功能
|
||||
|
||||
- 部署方式
|
||||
- [x] 兼容青龙
|
||||
- [x] 支持 Docker 独立部署,WebUI 配置
|
||||
- [x] 可能~~兼容青龙~~
|
||||
- [x] Docker 部署,WebUI 配置
|
||||
|
||||
- 分享链接
|
||||
- [x] 支持分享链接的子目录
|
||||
@ -58,7 +58,7 @@
|
||||
- 媒体库整合
|
||||
- [x] 根据任务名搜索 Emby 媒体库
|
||||
- [x] 追更或整理后自动刷新 Emby 媒体库
|
||||
- [x] **媒体库模块化,用户可很方便地[开发自己的媒体库hook模块](./plugins)**
|
||||
- [x] 媒体库模块化,用户可很方便地[开发自己的媒体库hook模块](./plugins)
|
||||
|
||||
- 其它
|
||||
- [x] 每日签到领空间 <sup>[?](https://github.com/Cp0204/quark-auto-save/wiki/使用技巧集锦#每日签到领空间)</sup>
|
||||
@ -74,10 +74,10 @@ Docker 部署提供 WebUI 管理配置,图形化配置已能满足绝大多数
|
||||
```shell
|
||||
docker run -d \
|
||||
--name quark-auto-save \
|
||||
-p 5005:5005 \
|
||||
-p 5005:5005 \ # 映射端口,:前的可以改,即部署后访问的端口,:后的不可改
|
||||
-e WEBUI_USERNAME=admin \
|
||||
-e WEBUI_PASSWORD=admin123 \
|
||||
-v ./quark-auto-save/config:/app/config \
|
||||
-v ./quark-auto-save/config:/app/config \ # 必须,配置持久化
|
||||
-v ./quark-auto-save/media:/media \ # 可选,模块alist_strm_gen生成strm使用
|
||||
--network bridge \
|
||||
--restart unless-stopped \
|
||||
@ -167,12 +167,14 @@ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtow
|
||||
|
||||
## 打赏
|
||||
|
||||
如果这个项目让你受益,你可以打赏我1块钱,让我知道开源有价值。谢谢!
|
||||
如果这个项目让你受益,你可以无偿赠与我1块钱,让我知道开源有价值。谢谢!
|
||||
|
||||

|
||||
|
||||
## 声明
|
||||
|
||||
本程序为个人兴趣开发,开源仅供学习与交流使用。
|
||||
本项目为个人兴趣开发,旨在通过程序自动化提高网盘使用效率。
|
||||
|
||||
程序没有任何破解行为,只是对于夸克已有的API进行封装,所有数据来自于夸克官方API,本人不对网盘内容负责、不对夸克官方API未来可能的改动导致的后果负责。
|
||||
程序没有任何破解行为,只是对于夸克已有的API进行封装,所有数据来自于夸克官方API;本人不对网盘内容负责、不对夸克官方API未来可能的变动导致的影响负责,请自行斟酌使用。
|
||||
|
||||
开源仅供学习与交流使用,未盈利也未授权商业使用,严禁用于非法用途。
|
||||
31
app/run.py
@ -268,15 +268,26 @@ def get_share_detail():
|
||||
account = Quark("", 0)
|
||||
pwd_id, passcode, pdir_fid, paths = account.extract_url(shareurl)
|
||||
if not stoken:
|
||||
is_sharing, stoken = account.get_stoken(pwd_id, passcode)
|
||||
if not is_sharing:
|
||||
return jsonify({"success": False, "data": {"error": stoken}})
|
||||
get_stoken = account.get_stoken(pwd_id, passcode)
|
||||
if get_stoken.get("status") == 200:
|
||||
stoken = get_stoken["data"]["stoken"]
|
||||
else:
|
||||
return jsonify(
|
||||
{"success": False, "data": {"error": get_stoken.get("message")}}
|
||||
)
|
||||
share_detail = account.get_detail(pwd_id, stoken, pdir_fid, _fetch_share=1)
|
||||
share_detail["paths"] = paths
|
||||
share_detail["stoken"] = stoken
|
||||
|
||||
if share_detail.get("code") != 0:
|
||||
return jsonify(
|
||||
{"success": False, "data": {"error": share_detail.get("message")}}
|
||||
)
|
||||
|
||||
data = share_detail["data"]
|
||||
data["paths"] = paths
|
||||
data["stoken"] = stoken
|
||||
|
||||
# 正则处理预览
|
||||
def preview_regex(share_detail):
|
||||
def preview_regex(data):
|
||||
regex = request.json.get("regex", {})
|
||||
pattern, replace = account.magic_regex_func(
|
||||
regex.get("pattern", ""),
|
||||
@ -284,7 +295,7 @@ def get_share_detail():
|
||||
regex.get("taskname", ""),
|
||||
regex.get("magic_regex", {}),
|
||||
)
|
||||
for item in share_detail["list"]:
|
||||
for item in data["list"]:
|
||||
file_name = item["file_name"]
|
||||
if re.search(pattern, item["file_name"]):
|
||||
item["file_name_re"] = (
|
||||
@ -293,9 +304,9 @@ def get_share_detail():
|
||||
return share_detail
|
||||
|
||||
if request.json.get("regex"):
|
||||
share_detail = preview_regex(share_detail)
|
||||
share_detail = preview_regex(data)
|
||||
|
||||
return jsonify({"success": True, "data": share_detail})
|
||||
return jsonify({"success": True, "data": data})
|
||||
|
||||
|
||||
@app.route("/get_savepath_detail")
|
||||
@ -328,7 +339,7 @@ def get_savepath_detail():
|
||||
else:
|
||||
fid = request.args.get("fid", "0")
|
||||
file_list = {
|
||||
"list": account.ls_dir(fid),
|
||||
"list": account.ls_dir(fid)["data"]["list"],
|
||||
"paths": paths,
|
||||
}
|
||||
return jsonify({"success": True, "data": file_list})
|
||||
|
||||
@ -45,7 +45,7 @@ body {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
table.jsoneditor-tree>tbody>tr.jsoneditor-expandable:first-child {
|
||||
table.jsoneditor-tree > tbody > tr.jsoneditor-expandable:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -82,14 +82,14 @@ table.jsoneditor-tree>tbody>tr.jsoneditor-expandable:first-child {
|
||||
/* Behind the navbar */
|
||||
padding: 54px 0 0;
|
||||
/* Height of navbar */
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.sidebar-sticky {
|
||||
position: relative;
|
||||
top: 0;
|
||||
height: calc(100vh - 54px);
|
||||
padding-top: .5rem;
|
||||
padding-top: 0.5rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
/* Scrollable contents if viewport is shorter than content. */
|
||||
@ -125,9 +125,8 @@ table.jsoneditor-tree>tbody>tr.jsoneditor-expandable:first-child {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
|
||||
.sidebar-heading {
|
||||
font-size: .75rem;
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@ -136,10 +135,10 @@ table.jsoneditor-tree>tbody>tr.jsoneditor-expandable:first-child {
|
||||
*/
|
||||
|
||||
.navbar-brand {
|
||||
padding-top: .75rem;
|
||||
padding-bottom: .75rem;
|
||||
background-color: rgba(0, 0, 0, .25);
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.navbar .navbar-toggler {
|
||||
@ -147,22 +146,53 @@ table.jsoneditor-tree>tbody>tr.jsoneditor-expandable:first-child {
|
||||
}
|
||||
|
||||
.navbar .form-control {
|
||||
padding: .75rem 1rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.form-control-dark {
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, .1);
|
||||
border-color: rgba(255, 255, 255, .1);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.form-control-dark:focus {
|
||||
border-color: transparent;
|
||||
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
|
||||
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-bottom {
|
||||
position: absolute;
|
||||
bottom: 32px;
|
||||
width: 100%;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.position-relative:hover .position-absolute {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.qrcode-tutorial {
|
||||
display: none;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 100%;
|
||||
margin-bottom: 10px;
|
||||
z-index: 1000;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
max-width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qrcode-tutorial img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
BIN
app/static/img/qrcode_tutorial.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
@ -2,7 +2,7 @@
|
||||
// @name QAS一键推送助手
|
||||
// @namespace https://github.com/Cp0204/quark-auto-save
|
||||
// @license AGPL
|
||||
// @version 0.3
|
||||
// @version 0.4
|
||||
// @description 在夸克网盘分享页面添加推送到 QAS 的按钮
|
||||
// @icon https://pan.quark.cn/favicon.ico
|
||||
// @author Cp0204
|
||||
@ -11,41 +11,53 @@
|
||||
// @grant GM_setValue
|
||||
// @grant GM_xmlhttpRequest
|
||||
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11
|
||||
// @downloadURL https://update.greasyfork.org/scripts/533201/QAS%E4%B8%80%E9%94%AE%E6%8E%A8%E9%80%81%E5%8A%A9%E6%89%8B.user.js
|
||||
// @updateURL https://update.greasyfork.org/scripts/533201/QAS%E4%B8%80%E9%94%AE%E6%8E%A8%E9%80%81%E5%8A%A9%E6%89%8B.meta.js
|
||||
// @downloadURL https://cdn.jsdelivr.net/gh/Cp0204/quark-auto-save@refs/heads/main/app/static/js/qas.addtask.user.js
|
||||
// @updateURL https://cdn.jsdelivr.net/gh/Cp0204/quark-auto-save@refs/heads/main/app/static/js/qas.addtask.user.js
|
||||
// ==/UserScript==
|
||||
|
||||
(function() {
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
let qas_base = GM_getValue('qas_base', '');
|
||||
let qas_token = GM_getValue('qas_token', '');
|
||||
let default_pattern = GM_getValue('default_pattern', '');
|
||||
let default_replace = GM_getValue('default_replace', '');
|
||||
|
||||
// QAS 设置弹窗函数
|
||||
function showQASSettingDialog(callback) {
|
||||
Swal.fire({
|
||||
title: 'QAS 设置',
|
||||
showCancelButton: true,
|
||||
html: `
|
||||
<label for="qas_base">QAS 服务器</label>
|
||||
<input id="qas_base" class="swal2-input" placeholder="例如: 192.168.1.8:5005" value="${qas_base}">
|
||||
<label for="qas_base">QAS 地址</label>
|
||||
<input id="qas_base" class="swal2-input" placeholder="如: http://192.168.1.8:5005" value="${qas_base}">
|
||||
<label for="qas_token">QAS Token</label>
|
||||
<input id="qas_token" class="swal2-input" placeholder="v0.5+ 系统配置中查找" value="${qas_token}">
|
||||
<label for="qas_token">默认正则</label>
|
||||
<input id="default_pattern" class="swal2-input" placeholder="如 $TV" value="${default_pattern}">
|
||||
<label for="qas_token">默认替换</label><input id="default_replace" class="swal2-input" value="${default_replace}">
|
||||
`,
|
||||
focusConfirm: false,
|
||||
preConfirm: () => {
|
||||
qas_base = document.getElementById('qas_base').value;
|
||||
qas_token = document.getElementById('qas_token').value;
|
||||
default_pattern = document.getElementById('default_pattern').value;
|
||||
default_replace = document.getElementById('default_replace').value;
|
||||
if (!qas_base || !qas_token) {
|
||||
Swal.showValidationMessage('请填写 QAS 服务器和 Token');
|
||||
Swal.showValidationMessage('请填写 QAS 地址和 Token');
|
||||
}
|
||||
return { qas_base: qas_base, qas_token: qas_token }
|
||||
return { qas_base: qas_base, qas_token: qas_token, default_pattern: default_pattern, default_replace: default_replace }
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
GM_setValue('qas_base', result.value.qas_base);
|
||||
GM_setValue('qas_token', result.value.qas_token);
|
||||
GM_setValue('default_pattern', result.value.default_pattern);
|
||||
GM_setValue('default_replace', result.value.default_replace);
|
||||
qas_base = result.value.qas_base;
|
||||
qas_token = result.value.qas_token;
|
||||
default_pattern = result.value.default_pattern;
|
||||
default_replace = result.value.default_replace;
|
||||
if (callback) {
|
||||
callback(); // 执行回调函数
|
||||
}
|
||||
@ -93,18 +105,18 @@
|
||||
qasButton.type = 'button';
|
||||
qasButton.className = 'ant-btn share-save';
|
||||
qasButton.style.marginLeft = '10px';
|
||||
qasButton.innerHTML = '<span class="share-save-ico"></span><span>推送到QAS</span>';
|
||||
qasButton.innerHTML = '<span class="share-save-ico"></span><span>创建QAS任务</span>';
|
||||
|
||||
let taskname, shareurl, savepath; // 声明变量
|
||||
|
||||
// 获取数据函数
|
||||
function getData() {
|
||||
const currentUrl = window.location.href;
|
||||
taskname = currentUrl.lastIndexOf('-') > 0 ? decodeURIComponent(currentUrl.match(/.*\/[^-]+-(.+)$/)[1]) : document.querySelector('.author-name').textContent;
|
||||
taskname = currentUrl.lastIndexOf('-') > 0 ? decodeURIComponent(currentUrl.match(/.*\/[^-]+-(.+)$/)[1]).replace('*101', '-') : document.querySelector('.author-name').textContent;
|
||||
shareurl = currentUrl;
|
||||
let pathElement = document.querySelector('.path-name')
|
||||
let pathElement = document.querySelector('.path-name');
|
||||
savepath = pathElement ? pathElement.title.replace('全部文件', '').trim() : "";
|
||||
savepath += "/" + taskname
|
||||
savepath += "/" + taskname;
|
||||
qasButton.title = `任务名称: ${taskname}\n分享链接: ${shareurl}\n保存路径: ${savepath}`;
|
||||
}
|
||||
|
||||
@ -119,11 +131,19 @@
|
||||
qasButton.addEventListener('click', () => {
|
||||
getData(); // 点击时重新获取数据,确保最新
|
||||
|
||||
const apiUrl = `http://${qas_base}/api/add_task?token=${qas_token}`;
|
||||
// 检查 qas_base 是否包含 http 或 https,如果没有则添加 http://
|
||||
let qasApiBase = qas_base;
|
||||
if (!qasApiBase.startsWith('http')) {
|
||||
qasApiBase = 'http://' + qasApiBase;
|
||||
}
|
||||
const apiUrl = `${qasApiBase}/api/add_task?token=${qas_token}`;
|
||||
|
||||
const data = {
|
||||
"taskname": taskname,
|
||||
"shareurl": shareurl,
|
||||
"savepath": savepath,
|
||||
"pattern": default_pattern,
|
||||
"replace": default_replace,
|
||||
};
|
||||
|
||||
GM_xmlhttpRequest({
|
||||
@ -133,7 +153,7 @@
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(data),
|
||||
onload: function(response) {
|
||||
onload: function (response) {
|
||||
try {
|
||||
const jsonResponse = JSON.parse(response.responseText);
|
||||
if (jsonResponse.success) {
|
||||
@ -142,7 +162,7 @@
|
||||
html: `<small>
|
||||
<b>任务名称:</b> ${taskname}<br><br>
|
||||
<b>保存路径:</b> ${savepath}<br><br>
|
||||
<a href="http://${qas_base}" target="_blank">去 QAS 查看</a>
|
||||
<a href="${qasApiBase}" target="_blank">去 QAS 查看</a>
|
||||
<small>`,
|
||||
icon: 'success'
|
||||
});
|
||||
@ -161,7 +181,7 @@
|
||||
});
|
||||
}
|
||||
},
|
||||
onerror: function(error) {
|
||||
onerror: function (error) {
|
||||
Swal.fire({
|
||||
title: '任务创建失败',
|
||||
text: error,
|
||||
|
||||
@ -49,9 +49,17 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="text-center" style="position: absolute; bottom: 32px; width: 100%; font-size: small;">
|
||||
<p><a class="" target="_blank" href="https://github.com/Cp0204/quark-auto-save/wiki"><i class="bi bi-wechat"></i> 使用交流</a></p>
|
||||
<p><a target="_blank" href="https://github.com/Cp0204/quark-auto-save"><i class="bi bi-github"></i> quark-auto-save</a></p>
|
||||
<div class="nav-bottom text-center">
|
||||
<p class="position-relative" hidden>
|
||||
<b class="text-success"><i class="bi bi-record-circle mr-1"></i>视频教程</b>
|
||||
<span class="position-absolute qrcode-tutorial">
|
||||
使用夸克扫码查看<br>
|
||||
<img src="./static/img/qrcode_tutorial.png">
|
||||
</span>
|
||||
</p>
|
||||
<p><a target="_blank" href="https://github.com/Cp0204/quark-auto-save/wiki"><i class="bi bi-wechat mr-1"></i>使用交流</a></p>
|
||||
<p><a href="./static/js/qas.addtask.user.js"><i class="bi bi-cloud-plus-fill mr-1"></i>推送任务油猴脚本</a></p>
|
||||
<p><a target="_blank" href="https://github.com/Cp0204/quark-auto-save"><i class="bi bi-github mr-1"></i>quark-auto-save</a></p>
|
||||
<p><span v-html="versionTips"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
@ -391,9 +399,9 @@
|
||||
</div>
|
||||
|
||||
<div class="bottom-buttons">
|
||||
<button class="btn btn-success" title="保存 CTRL+S"><i class="bi bi-floppy2-fill"></i></button>
|
||||
<button type="button" class="btn btn-primary" title="运行 CTRL+R" @click="runScriptNow()"><i class="bi bi-play-fill"></i></button>
|
||||
<button type="button" class="btn btn-info" @click="scrollToX(0)" @dblclick="scrollToX()" data-toggle="tooltip" data-placement="top" title="单击回顶,双击到底"><i class="bi bi-chevron-bar-up"></i></button>
|
||||
<button class="btn btn-success" data-toggle="tooltip" data-placement="top" title="保存 CTRL+S"><i class="bi bi-floppy2-fill"></i></button>
|
||||
<button type="button" class="btn btn-primary" data-toggle="tooltip" data-placement="top" title="运行 CTRL+R" @click="runScriptNow()"><i class="bi bi-play-fill"></i></button>
|
||||
<button type="button" class="btn btn-info" data-toggle="tooltip" data-placement="top" title="单击回顶,双击到底" @click="scrollToX(0)" @dblclick="scrollToX()"><i class="bi bi-chevron-bar-up"></i></button>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
@ -605,7 +613,7 @@
|
||||
latestVersion = response.data[0].name;
|
||||
console.log(`检查版本:当前 ${this.version} 最新 ${latestVersion}`);
|
||||
if (latestVersion != this.version) {
|
||||
this.versionTips += ` <sup><span class="badge badge-pill badge-danger">${latestVersion}</span></sup>`;
|
||||
this.versionTips += ` <sup><span class="position-absolute badge badge-pill badge-danger">${latestVersion}</span></sup>`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
@ -922,6 +930,8 @@
|
||||
},
|
||||
selectSuggestion(index, suggestion) {
|
||||
this.smart_param.showSuggestions = false;
|
||||
this.fileSelect.selectDir = true;
|
||||
this.fileSelect.previewRegex = false;
|
||||
this.showShareSelect(index, suggestion.shareurl);
|
||||
},
|
||||
addMagicRegex() {
|
||||
@ -1021,10 +1031,12 @@
|
||||
this.fileSelect.fileList = [];
|
||||
this.fileSelect.paths = [];
|
||||
this.fileSelect.error = undefined;
|
||||
if (this.getShareurl(this.fileSelect.shareurl) != this.getShareurl(this.formData.tasklist[index].shareurl)) {
|
||||
// 如果分享链接发生变化,则重置 stoken
|
||||
const newShareurl = shareurl || this.formData.tasklist[index].shareurl
|
||||
if (this.getShareurl(this.fileSelect.shareurl) != this.getShareurl(newShareurl)) {
|
||||
this.fileSelect.stoken = "";
|
||||
}
|
||||
this.fileSelect.shareurl = shareurl || this.formData.tasklist[index].shareurl;
|
||||
this.fileSelect.shareurl = newShareurl;
|
||||
this.fileSelect.index = index;
|
||||
$('#fileSelectModal').modal('toggle');
|
||||
this.getShareDetail();
|
||||
|
||||
BIN
img/run_log.png
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 241 KiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 313 KiB |
@ -240,7 +240,9 @@ class Quark:
|
||||
print(f"_send_request error:\n{e}")
|
||||
fake_response = requests.Response()
|
||||
fake_response.status_code = 500
|
||||
fake_response._content = b'{"status": 500, "message": "request error"}'
|
||||
fake_response._content = (
|
||||
b'{"status": 500, "code": 1, "message": "request error"}'
|
||||
)
|
||||
return fake_response
|
||||
|
||||
def init(self):
|
||||
@ -312,10 +314,7 @@ class Quark:
|
||||
response = self._send_request(
|
||||
"POST", url, json=payload, params=querystring
|
||||
).json()
|
||||
if response.get("status") == 200:
|
||||
return True, response["data"]["stoken"]
|
||||
else:
|
||||
return False, response["message"]
|
||||
return response
|
||||
|
||||
def get_detail(self, pwd_id, stoken, pdir_fid, _fetch_share=0):
|
||||
list_merge = []
|
||||
@ -338,7 +337,7 @@ class Quark:
|
||||
}
|
||||
response = self._send_request("GET", url, params=querystring).json()
|
||||
if response["code"] != 0:
|
||||
return {"error": response["message"]}
|
||||
return response
|
||||
if response["data"]["list"]:
|
||||
list_merge += response["data"]["list"]
|
||||
page += 1
|
||||
@ -347,7 +346,7 @@ class Quark:
|
||||
if len(list_merge) >= response["metadata"]["_total"]:
|
||||
break
|
||||
response["data"]["list"] = list_merge
|
||||
return response["data"]
|
||||
return response
|
||||
|
||||
def get_fids(self, file_paths):
|
||||
fids = []
|
||||
@ -369,7 +368,7 @@ class Quark:
|
||||
return fids
|
||||
|
||||
def ls_dir(self, pdir_fid, **kwargs):
|
||||
file_list = []
|
||||
list_merge = []
|
||||
page = 1
|
||||
while True:
|
||||
url = f"{self.BASE_URL}/1/clouddrive/file/sort"
|
||||
@ -387,15 +386,16 @@ class Quark:
|
||||
}
|
||||
response = self._send_request("GET", url, params=querystring).json()
|
||||
if response["code"] != 0:
|
||||
return {"error": response["message"]}
|
||||
return response
|
||||
if response["data"]["list"]:
|
||||
file_list += response["data"]["list"]
|
||||
list_merge += response["data"]["list"]
|
||||
page += 1
|
||||
else:
|
||||
break
|
||||
if len(file_list) >= response["metadata"]["_total"]:
|
||||
if len(list_merge) >= response["metadata"]["_total"]:
|
||||
break
|
||||
return file_list
|
||||
response["data"]["list"] = list_merge
|
||||
return response
|
||||
|
||||
def save_file(self, fid_list, fid_token_list, to_pdir_fid, pwd_id, stoken):
|
||||
url = f"{self.BASE_URL}/1/clouddrive/share/sharepage/save"
|
||||
@ -595,8 +595,8 @@ class Quark:
|
||||
def do_save_check(self, shareurl, savepath):
|
||||
try:
|
||||
pwd_id, passcode, pdir_fid, _ = self.extract_url(shareurl)
|
||||
_, stoken = self.get_stoken(pwd_id, passcode)
|
||||
share_file_list = self.get_detail(pwd_id, stoken, pdir_fid)["list"]
|
||||
stoken = self.get_stoken(pwd_id, passcode)["data"]["stoken"]
|
||||
share_file_list = self.get_detail(pwd_id, stoken, pdir_fid)["data"]["list"]
|
||||
fid_list = [item["fid"] for item in share_file_list]
|
||||
fid_token_list = [item["share_fid_token"] for item in share_file_list]
|
||||
file_name_list = [item["file_name"] for item in share_file_list]
|
||||
@ -612,7 +612,7 @@ class Quark:
|
||||
if save_file["code"] == 41017:
|
||||
return
|
||||
elif save_file["code"] == 0:
|
||||
dir_file_list = self.ls_dir(to_pdir_fid)
|
||||
dir_file_list = self.ls_dir(to_pdir_fid)["data"]["list"]
|
||||
del_list = [
|
||||
item["fid"]
|
||||
for item in dir_file_list
|
||||
@ -644,10 +644,16 @@ class Quark:
|
||||
pwd_id, passcode, pdir_fid, _ = self.extract_url(task["shareurl"])
|
||||
|
||||
# 获取stoken,同时可验证资源是否失效
|
||||
is_sharing, stoken = self.get_stoken(pwd_id, passcode)
|
||||
if not is_sharing:
|
||||
add_notify(f"❌《{task['taskname']}》:{stoken}\n")
|
||||
task["shareurl_ban"] = stoken
|
||||
get_stoken = self.get_stoken(pwd_id, passcode)
|
||||
if get_stoken.get("status") == 200:
|
||||
stoken = get_stoken["data"]["stoken"]
|
||||
elif get_stoken.get("status") == 500:
|
||||
print(f"跳过任务:网络异常 {get_stoken.get("message")}")
|
||||
return
|
||||
else:
|
||||
message = get_stoken.get("message")
|
||||
add_notify(f"❌《{task['taskname']}》:{message}\n")
|
||||
task["shareurl_ban"] = message
|
||||
return
|
||||
# print("stoken: ", stoken)
|
||||
|
||||
@ -662,7 +668,7 @@ class Quark:
|
||||
def dir_check_and_save(self, task, pwd_id, stoken, pdir_fid="", subdir_path=""):
|
||||
tree = Tree()
|
||||
# 获取分享文件列表
|
||||
share_file_list = self.get_detail(pwd_id, stoken, pdir_fid)["list"]
|
||||
share_file_list = self.get_detail(pwd_id, stoken, pdir_fid)["data"]["list"]
|
||||
# print("share_file_list: ", share_file_list)
|
||||
|
||||
if not share_file_list:
|
||||
@ -678,7 +684,7 @@ class Quark:
|
||||
print("🧠 该分享是一个文件夹,读取文件夹内列表")
|
||||
share_file_list = self.get_detail(
|
||||
pwd_id, stoken, share_file_list[0]["fid"]
|
||||
)["list"]
|
||||
)["data"]["list"]
|
||||
|
||||
# 获取目标目录文件列表
|
||||
savepath = re.sub(r"/{2,}", "/", f"/{task['savepath']}{subdir_path}")
|
||||
@ -689,8 +695,19 @@ class Quark:
|
||||
print(f"❌ 目录 {savepath} fid获取失败,跳过转存")
|
||||
return tree
|
||||
to_pdir_fid = self.savepath_fid[savepath]
|
||||
dir_file_list = self.ls_dir(to_pdir_fid)
|
||||
dir_file_list = self.ls_dir(to_pdir_fid)["data"]["list"]
|
||||
# print("dir_file_list: ", dir_file_list)
|
||||
# 清空目标文件夹
|
||||
fid_list = [item["fid"] for item in dir_file_list]
|
||||
if fid_list:
|
||||
self.delete(fid_list)
|
||||
recycle_list = self.recycle_list()
|
||||
record_id_list = [
|
||||
item["record_id"] for item in recycle_list if item["fid"] in fid_list
|
||||
]
|
||||
self.recycle_remove(record_id_list)
|
||||
# 重新获取目标目录文件列表
|
||||
dir_file_list = self.ls_dir(to_pdir_fid)
|
||||
|
||||
tree.create_node(
|
||||
savepath,
|
||||
@ -808,7 +825,7 @@ class Quark:
|
||||
savepath = re.sub(r"/{2,}", "/", f"/{task['savepath']}{subdir_path}")
|
||||
if not self.savepath_fid.get(savepath):
|
||||
self.savepath_fid[savepath] = self.get_fids([savepath])[0]["fid"]
|
||||
dir_file_list = self.ls_dir(self.savepath_fid[savepath])
|
||||
dir_file_list = self.ls_dir(self.savepath_fid[savepath])["data"]["list"]
|
||||
dir_file_name_list = [item["file_name"] for item in dir_file_list]
|
||||
is_rename_count = 0
|
||||
for dir_file in dir_file_list:
|
||||
|
||||