Compare commits

...

6 Commits

Author SHA1 Message Date
Cp0204
c18f544c26 🔧 移除 dateutil 依赖
Some checks are pending
Docker Publish / build-and-push (push) Waiting to run
2025-05-10 20:23:42 +08:00
Cp0204
52d4216727 更新配置结构、移除老旧版本升级代码 2025-05-10 19:37:21 +08:00
Cp0204
4ece1ec80a ♻️ 调整 Quark 类初始化方法 2025-05-10 19:37:21 +08:00
Cp0204
f692ce57ee 增加通知推送测试的按钮和功能
- 在 run.py 中添加了处理测试请求的逻辑,设置 QUARK_TEST 环境变量
- 更新了 index.html,增加推送测试按钮
- 修改了 quark_auto_save.py,增加了转存测试和通知测试的功能
- 转存测试增加错误处理和日志输出
2025-05-10 19:37:20 +08:00
Cp0204
4669935200 🔧 优化通知配置读取 2025-05-10 17:11:17 +08:00
Cp0204
f005d4f614 WEBUI 端口可用环境变量配置
- 新增 HOST 和 PORT 环境变量,默认值分别为 0.0.0.0 和 5005
- 更新 app.run() 方法,使用新的环境变量配置
2025-05-10 12:45:31 +08:00
4 changed files with 107 additions and 78 deletions

View File

@ -48,6 +48,8 @@ SCRIPT_PATH = os.environ.get("SCRIPT_PATH", "./quark_auto_save.py")
CONFIG_PATH = os.environ.get("CONFIG_PATH", "./config/quark_config.json")
PLUGIN_FLAGS = os.environ.get("PLUGIN_FLAGS", "")
DEBUG = os.environ.get("DEBUG", "false").lower() == "true"
HOST = os.environ.get("HOST", "0.0.0.0")
PORT = os.environ.get("PORT", 5005)
config_data = {}
task_plugins_config_default = {}
@ -190,6 +192,14 @@ def run_script_now():
# 设置环境变量
process_env = os.environ.copy()
process_env["PYTHONIOENCODING"] = "utf-8"
if request.json.get("quark_test"):
process_env["QUARK_TEST"] = "true"
process_env["COOKIE"] = json.dumps(
request.json.get("cookie", []), ensure_ascii=False
)
process_env["PUSH_CONFIG"] = json.dumps(
request.json.get("push_config", {}), ensure_ascii=False
)
if tasklist:
process_env["TASKLIST"] = json.dumps(tasklist, ensure_ascii=False)
process = subprocess.Popen(
@ -264,7 +274,7 @@ def get_share_detail():
return jsonify({"success": False, "message": "未登录"})
shareurl = request.json.get("shareurl", "")
stoken = request.json.get("stoken", "")
account = Quark("", 0)
account = Quark()
pwd_id, passcode, pdir_fid, paths = account.extract_url(shareurl)
if not stoken:
get_stoken = account.get_stoken(pwd_id, passcode)
@ -291,7 +301,7 @@ def get_share_detail():
magic_regex = request.json.get("magic_regex", {})
mr = MagicRename(magic_regex)
mr.set_taskname(task.get("taskname", ""))
account = Quark(config_data["cookie"][0], 0)
account = Quark(config_data["cookie"][0])
get_fids = account.get_fids([task.get("savepath", "")])
if get_fids:
dir_file_list = account.ls_dir(get_fids[0]["fid"])["data"]["list"]
@ -338,7 +348,7 @@ def get_share_detail():
def get_savepath_detail():
if not is_login():
return jsonify({"success": False, "message": "未登录"})
account = Quark(config_data["cookie"][0], 0)
account = Quark(config_data["cookie"][0])
paths = []
if path := request.args.get("path"):
path = re.sub(r"/+", "/", path)
@ -374,7 +384,7 @@ def get_savepath_detail():
def delete_file():
if not is_login():
return jsonify({"success": False, "message": "未登录"})
account = Quark(config_data["cookie"][0], 0)
account = Quark(config_data["cookie"][0])
if fid := request.json.get("fid"):
response = account.delete([fid])
else:
@ -459,6 +469,8 @@ def init():
# 读取配置
config_data = Config.read_json(CONFIG_PATH)
Config.breaking_change_update(config_data)
if not config_data.get("magic_regex"):
config_data["magic_regex"] = MagicRename().magic_regex
# 默认管理账号
config_data["webui"] = {
@ -484,4 +496,8 @@ def init():
if __name__ == "__main__":
init()
reload_tasks()
app.run(debug=DEBUG, host="0.0.0.0", port=5005)
app.run(
debug=DEBUG,
host=HOST,
port=PORT,
)

View File

@ -102,13 +102,14 @@
</div>
<div class="row title" title="通知推送支持多个渠道见Wiki">
<div class="col-10">
<div class="col-8">
<h2 style="display: inline-block;"><i class="bi bi-bell"></i> 通知</h2>
<span class="badge badge-pill badge-light">
<a href="https://github.com/Cp0204/quark-auto-save/wiki/通知推送服务配置" target="_blank">?</a>
</span>
</div>
<div class="col-2 text-right">
<div class="col-4 text-right">
<button type="button" class="btn btn-outline-success" title="通知推送测试" @click="testPush()"><i class="bi bi-lightning"></i></button>
<button type="button" class="btn btn-outline-primary" @click="addPush()">+</button>
</div>
</div>
@ -701,6 +702,9 @@
if (this.formData.cookie[index] == "" || confirm("确认删除吗?"))
this.formData.cookie.splice(index, 1);
},
testPush() {
this.runScriptNow(1, true);
},
addPush() {
key = prompt("增加的键名", "");
if (key != "" && key != null)
@ -800,9 +804,15 @@
clearData(target) {
this[target] = "";
},
async runScriptNow(task_index = null) {
async runScriptNow(task_index = null, test = false) {
body = {};
if (task_index != null) {
if (test) {
body = {
"quark_test": true,
"cookie": this.formData.cookie,
"push_config": this.formData.push_config
};
} else if (task_index != null) {
task = { ...this.formData.tasklist[task_index] };
delete task.runweek;
delete task.enddate;
@ -836,12 +846,6 @@
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('Stream complete.');
this.modalLoading = false;
// 运行后刷新数据
if (task_index == null) {
this.fetchData();
}
break;
}
partialData += decoder.decode(value);
@ -851,8 +855,10 @@
const eventData = line.substring(5).trim();
if (eventData === '[DONE]') {
this.modalLoading = false;
this.fetchData();
return;
if (task_index == null) {
this.fetchData();
}
break;
}
this.run_log += eventData.replace('<', '<\u200B') + '\n';
// 在更新 run_log 后将滚动条滚动到底部

View File

@ -15,8 +15,8 @@ import time
import random
import requests
import importlib
import traceback
import urllib.parse
from dateutil import parser
from datetime import datetime
# 兼容青龙
@ -41,7 +41,7 @@ def send_ql_notify(title, body):
# 如未配置 push_config 则使用青龙环境通知设置
if CONFIG_DATA.get("push_config"):
notify.push_config = CONFIG_DATA["push_config"].copy()
notify.push_config.update(CONFIG_DATA["push_config"])
notify.push_config["CONSOLE"] = notify.push_config.get("CONSOLE", True)
notify.send(title, body)
except Exception as e:
@ -131,29 +131,10 @@ class Config:
return plugins_available, plugins_config, task_plugins_config
def breaking_change_update(config_data):
if config_data.get("emby"):
print("🔼 Update config v0.3.6.1 to 0.3.7")
config_data.setdefault("media_servers", {})["emby"] = {
"url": config_data["emby"]["url"],
"token": config_data["emby"]["apikey"],
}
del config_data["emby"]
for task in config_data.get("tasklist", {}):
task["media_id"] = task.get("emby_id", "")
if task.get("emby_id"):
del task["emby_id"]
if config_data.get("media_servers"):
print("🔼 Update config v0.3.8 to 0.3.9")
config_data["plugins"] = config_data.get("media_servers")
del config_data["media_servers"]
for task in config_data.get("tasklist", {}):
task["addition"] = {
"emby": {
"media_id": task.get("media_id", ""),
}
}
if task.get("media_id"):
del task["media_id"]
# 🔼 Update config v0.5.x to 0.6.0
for task in config_data.get("tasklist", []):
if "$TASKNAME" in task.get("replace", ""):
task["replace"] = task["replace"].replace("$TASKNAME", "{TASKNAME}")
class MagicRename:
@ -255,7 +236,6 @@ class MagicRename:
value = (
str(datetime.now().year)[: (8 - len(value))] + value
)
value = parser.parse(value).strftime("%Y%m%d")
replace = replace.replace(key, value)
break
# 非正则类替换变量
@ -360,7 +340,7 @@ class Quark:
BASE_URL_APP = "https://drive-m.quark.cn"
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/3.14.2 Chrome/112.0.5615.165 Electron/24.1.3.8 Safari/537.36 Channel/pckk_other_ch"
def __init__(self, cookie, index=None):
def __init__(self, cookie="", index=0):
self.cookie = cookie.strip()
self.index = index + 1
self.is_active = False
@ -761,11 +741,9 @@ class Quark:
pwd_id, passcode, pdir_fid, _ = self.extract_url(shareurl)
stoken = self.get_stoken(pwd_id, passcode)["data"]["stoken"]
share_file_list = self.get_detail(pwd_id, stoken, pdir_fid)["data"]["list"]
print(f"获取分享: {share_file_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]
if not fid_list:
return
get_fids = self.get_fids([savepath])
to_pdir_fid = (
get_fids[0]["fid"] if get_fids else self.mkdir(savepath)["data"]["fid"]
@ -773,30 +751,31 @@ class Quark:
save_file = self.save_file(
fid_list, fid_token_list, to_pdir_fid, pwd_id, stoken
)
if save_file["code"] == 41017:
return
elif save_file["code"] == 0:
dir_file_list = self.ls_dir(to_pdir_fid)["data"]["list"]
del_list = [
item["fid"]
for item in dir_file_list
if (item["file_name"] in file_name_list)
and ((datetime.now().timestamp() - item["created_at"]) < 60)
]
if del_list:
self.delete(del_list)
recycle_list = self.recycle_list()
record_id_list = [
item["record_id"]
for item in recycle_list
if item["fid"] in del_list
]
self.recycle_remove(record_id_list)
return save_file
else:
return []
print(f"转存文件: {save_file}")
if save_file["code"] == 0:
task_id = save_file["data"]["task_id"]
query_task = self.query_task(task_id)
print(f"查询转存: {query_task}")
if query_task["code"] == 0:
del_list = query_task["data"]["save_as"]["save_as_top_fids"]
if del_list:
delete_return = self.delete(del_list)
print(f"删除转存: {delete_return}")
recycle_list = self.recycle_list()
record_id_list = [
item["record_id"]
for item in recycle_list
if item["fid"] in del_list
]
recycle_remove = self.recycle_remove(record_id_list)
print(f"清理转存: {recycle_remove}")
print(f"✅ 转存测试成功")
return True
print(f"❌ 转存测试失败: 中断")
return False
except Exception as e:
print(f"转存测试失败: {str(e)}")
print(f"❌ 转存测试失败: {str(e)}")
traceback.print_exc()
def do_save_task(self, task):
# 判断资源失效记录
@ -1146,6 +1125,21 @@ def main():
print()
# 读取启动参数
config_path = sys.argv[1] if len(sys.argv) > 1 else "quark_config.json"
# 推送测试
if os.environ.get("QUARK_TEST", "").lower() == "true":
print(f"===============通知测试===============")
CONFIG_DATA["push_config"] = json.loads(os.environ.get("PUSH_CONFIG"))
send_ql_notify(
"【夸克自动转存】",
f"通知测试\n\n{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
)
print()
if cookies := json.loads(os.environ.get("COOKIE", "[]")):
print(f"===============转存测试===============")
accounts = Quark(cookies[0])
accounts.do_save_check("https://pan.quark.cn/s/1ed94d530d63", "/来自:分享")
print()
return
# 从环境变量中获取 TASKLIST
tasklist_from_env = []
if tasklist_json := os.environ.get("TASKLIST"):
@ -1172,8 +1166,6 @@ def main():
CONFIG_DATA = Config.read_json(config_path)
Config.breaking_change_update(CONFIG_DATA)
cookie_val = CONFIG_DATA.get("cookie")
if not CONFIG_DATA.get("magic_regex"):
CONFIG_DATA["magic_regex"] = MagicRename().magic_regex
cookie_form_file = True
# 获取cookie
cookies = Config.get_cookies(cookie_val)
@ -1203,7 +1195,7 @@ def main():
if NOTIFYS:
notify_body = "\n".join(NOTIFYS)
print(f"===============推送通知===============")
send_ql_notify("【夸克自动追更", notify_body)
send_ql_notify("【夸克自动转存", notify_body)
print()
if cookie_form_file:
# 更新配置

View File

@ -6,7 +6,7 @@
"QUARK_SIGN_NOTIFY": true,
"其他推送渠道//此项可删": "配置方法同青龙"
},
"media_servers": {
"plugins": {
"emby": {
"url": "",
"token": ""
@ -20,22 +20,37 @@
"$BLACK_WORD": {
"pattern": "^(?!.*纯享)(?!.*加更)(?!.*超前企划)(?!.*训练室)(?!.*蒸蒸日上).*",
"replace": ""
},
"$SHOW_PRO": {
"pattern": "^(?!.*纯享)(?!.*加更)(?!.*抢先)(?!.*预告).*?第\\d+期.*",
"replace": "{II}.{TASKNAME}.{DATE}.第{E}期{PART}.{EXT}"
},
"$TV_PRO": {
"pattern": "",
"replace": "{TASKNAME}.{SXX}E{E}.{EXT}"
}
},
"tasklist": [
{
"taskname": "测试-魔法匹配剧集这是一组有效分享配置CK后可测试任务是否正常",
"shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试",
"savepath": "/夸克自动转存测试",
"savepath": "/夸克自动转存测试/剧集",
"pattern": "$TV",
"replace": "",
"enddate": "2099-01-30",
"update_subdir": "4k|1080p"
},
{
"taskname": "测试-广告过滤",
"taskname": "测试-综艺命名",
"shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-%E5%A4%B8%E5%85%8B%E8%87%AA%E5%8A%A8%E8%BD%AC%E5%AD%98%E6%B5%8B%E8%AF%95/71df3902f42d4270a58c0eb12aa2b014-%E7%BB%BC%E8%89%BA%E5%91%BD%E5%90%8D",
"savepath": "/夸克自动转存测试/综艺命名",
"pattern": "^(?!.*纯享)(?!.*加更)(?!.*抢先)(?!.*预告).*?第\\d+期.*",
"replace": "{II}.{TASKNAME}.{DATE}.第{E}期{PART}.{EXT}"
},
{
"taskname": "测试-去广告字符",
"shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试/680d91e490814da0927c38b432f88edc-带广告文件夹",
"savepath": "/夸克自动转存测试/带广告文件夹",
"savepath": "/夸克自动转存测试/去广告字符",
"pattern": "【XX电影网】(.*)\\.(mp4|mkv)",
"replace": "\\1.\\2",
"enddate": "2099-01-30"
@ -43,7 +58,7 @@
{
"taskname": "测试-超期任务",
"shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试",
"savepath": "/夸克自动转存测试",
"savepath": "/夸克自动转存测试/不会运行",
"pattern": "",
"replace": "",
"enddate": "2000-01-30",