Compare commits

...

5 Commits

Author SHA1 Message Date
Cp0204
71b4fca6c2 📝 更新文档
Some checks are pending
Docker Publish / build-and-push (push) Waiting to run
2025-04-26 18:08:29 +08:00
Cp0204
b6aca2e2e9 油猴脚本:一键推送助手更新至 0.4
- QAS 地址支持填入 https
- 变更更新链接为 GitHub 地址
- 添加默认正则和替换设置
2025-04-26 17:04:35 +08:00
Cp0204
996210f8c7 🐛 修复正则预览后搜资源 界面未复位 #73
- 同时修复切换资源提示 非法token
2025-04-26 17:04:35 +08:00
Cp0204
de6e4356a4 🎨 优化样式和布局,显示油猴脚本链接
- 添加教程二维码
- 增强按钮的工具提示功能
2025-04-26 17:04:35 +08:00
Cp0204
da7a5e93c8 🐛 修复网络异常时记录为分享失效 #71
- 调整分享详情和文件列表的返回结构
- 增强网络异常时的错误处理
2025-04-26 17:04:35 +08:00
10 changed files with 163 additions and 82 deletions

View File

@ -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块钱让我知道开源有价值。谢谢
![WeChatPay](https://cdn.jsdelivr.net/gh/Cp0204/Cp0204@main/img/wechat_pay_qrcode.png)
## 声明
程序为个人兴趣开发,开源仅供学习与交流使用
项目为个人兴趣开发,旨在通过程序自动化提高网盘使用效率
程序没有任何破解行为只是对于夸克已有的API进行封装所有数据来自于夸克官方API本人不对网盘内容负责、不对夸克官方API未来可能的改动导致的后果负责。
程序没有任何破解行为只是对于夸克已有的API进行封装所有数据来自于夸克官方API本人不对网盘内容负责、不对夸克官方API未来可能的变动导致的影响负责请自行斟酌使用。
开源仅供学习与交流使用,未盈利也未授权商业使用,严禁用于非法用途。

View File

@ -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})

View File

@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -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,

View File

@ -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();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 313 KiB

View File

@ -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,7 +695,7 @@ 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)
tree.create_node(
@ -808,7 +814,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: