Compare commits

..

No commits in common. "c18f544c2648927575bbd7374eaa1588414d2b0b" and "a7e61cd9376726c12ec08d9b17804231ba7bbba3" have entirely different histories.

4 changed files with 78 additions and 107 deletions

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
"QUARK_SIGN_NOTIFY": true, "QUARK_SIGN_NOTIFY": true,
"其他推送渠道//此项可删": "配置方法同青龙" "其他推送渠道//此项可删": "配置方法同青龙"
}, },
"plugins": { "media_servers": {
"emby": { "emby": {
"url": "", "url": "",
"token": "" "token": ""
@ -20,37 +20,22 @@
"$BLACK_WORD": { "$BLACK_WORD": {
"pattern": "^(?!.*纯享)(?!.*加更)(?!.*超前企划)(?!.*训练室)(?!.*蒸蒸日上).*", "pattern": "^(?!.*纯享)(?!.*加更)(?!.*超前企划)(?!.*训练室)(?!.*蒸蒸日上).*",
"replace": "" "replace": ""
},
"$SHOW_PRO": {
"pattern": "^(?!.*纯享)(?!.*加更)(?!.*抢先)(?!.*预告).*?第\\d+期.*",
"replace": "{II}.{TASKNAME}.{DATE}.第{E}期{PART}.{EXT}"
},
"$TV_PRO": {
"pattern": "",
"replace": "{TASKNAME}.{SXX}E{E}.{EXT}"
} }
}, },
"tasklist": [ "tasklist": [
{ {
"taskname": "测试-魔法匹配剧集这是一组有效分享配置CK后可测试任务是否正常", "taskname": "测试-魔法匹配剧集这是一组有效分享配置CK后可测试任务是否正常",
"shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试", "shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试",
"savepath": "/夸克自动转存测试/剧集", "savepath": "/夸克自动转存测试",
"pattern": "$TV", "pattern": "$TV",
"replace": "", "replace": "",
"enddate": "2099-01-30", "enddate": "2099-01-30",
"update_subdir": "4k|1080p" "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-带广告文件夹", "shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试/680d91e490814da0927c38b432f88edc-带广告文件夹",
"savepath": "/夸克自动转存测试/去广告字符", "savepath": "/夸克自动转存测试/带广告文件夹",
"pattern": "【XX电影网】(.*)\\.(mp4|mkv)", "pattern": "【XX电影网】(.*)\\.(mp4|mkv)",
"replace": "\\1.\\2", "replace": "\\1.\\2",
"enddate": "2099-01-30" "enddate": "2099-01-30"
@ -58,7 +43,7 @@
{ {
"taskname": "测试-超期任务", "taskname": "测试-超期任务",
"shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试", "shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试",
"savepath": "/夸克自动转存测试/不会运行", "savepath": "/夸克自动转存测试",
"pattern": "", "pattern": "",
"replace": "", "replace": "",
"enddate": "2000-01-30", "enddate": "2000-01-30",