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")
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 = {}
@ -192,14 +190,6 @@ 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(
@ -274,7 +264,7 @@ def get_share_detail():
return jsonify({"success": False, "message": "未登录"})
shareurl = request.json.get("shareurl", "")
stoken = request.json.get("stoken", "")
account = Quark()
account = Quark("", 0)
pwd_id, passcode, pdir_fid, paths = account.extract_url(shareurl)
if not stoken:
get_stoken = account.get_stoken(pwd_id, passcode)
@ -301,7 +291,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])
account = Quark(config_data["cookie"][0], 0)
get_fids = account.get_fids([task.get("savepath", "")])
if get_fids:
dir_file_list = account.ls_dir(get_fids[0]["fid"])["data"]["list"]
@ -348,7 +338,7 @@ def get_share_detail():
def get_savepath_detail():
if not is_login():
return jsonify({"success": False, "message": "未登录"})
account = Quark(config_data["cookie"][0])
account = Quark(config_data["cookie"][0], 0)
paths = []
if path := request.args.get("path"):
path = re.sub(r"/+", "/", path)
@ -384,7 +374,7 @@ def get_savepath_detail():
def delete_file():
if not is_login():
return jsonify({"success": False, "message": "未登录"})
account = Quark(config_data["cookie"][0])
account = Quark(config_data["cookie"][0], 0)
if fid := request.json.get("fid"):
response = account.delete([fid])
else:
@ -469,8 +459,6 @@ 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"] = {
@ -496,8 +484,4 @@ def init():
if __name__ == "__main__":
init()
reload_tasks()
app.run(
debug=DEBUG,
host=HOST,
port=PORT,
)
app.run(debug=DEBUG, host="0.0.0.0", port=5005)

View File

@ -102,14 +102,13 @@
</div>
<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>
<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-4 text-right">
<button type="button" class="btn btn-outline-success" title="通知推送测试" @click="testPush()"><i class="bi bi-lightning"></i></button>
<div class="col-2 text-right">
<button type="button" class="btn btn-outline-primary" @click="addPush()">+</button>
</div>
</div>
@ -702,9 +701,6 @@
if (this.formData.cookie[index] == "" || confirm("确认删除吗?"))
this.formData.cookie.splice(index, 1);
},
testPush() {
this.runScriptNow(1, true);
},
addPush() {
key = prompt("增加的键名", "");
if (key != "" && key != null)
@ -804,15 +800,9 @@
clearData(target) {
this[target] = "";
},
async runScriptNow(task_index = null, test = false) {
async runScriptNow(task_index = null) {
body = {};
if (test) {
body = {
"quark_test": true,
"cookie": this.formData.cookie,
"push_config": this.formData.push_config
};
} else if (task_index != null) {
if (task_index != null) {
task = { ...this.formData.tasklist[task_index] };
delete task.runweek;
delete task.enddate;
@ -846,6 +836,12 @@
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);
@ -855,10 +851,8 @@
const eventData = line.substring(5).trim();
if (eventData === '[DONE]') {
this.modalLoading = false;
if (task_index == null) {
this.fetchData();
}
break;
this.fetchData();
return;
}
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.update(CONFIG_DATA["push_config"])
notify.push_config = CONFIG_DATA["push_config"].copy()
notify.push_config["CONSOLE"] = notify.push_config.get("CONSOLE", True)
notify.send(title, body)
except Exception as e:
@ -131,10 +131,29 @@ class Config:
return plugins_available, plugins_config, task_plugins_config
def breaking_change_update(config_data):
# 🔼 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}")
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"]
class MagicRename:
@ -236,6 +255,7 @@ 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
# 非正则类替换变量
@ -340,7 +360,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=0):
def __init__(self, cookie, index=None):
self.cookie = cookie.strip()
self.index = index + 1
self.is_active = False
@ -741,9 +761,11 @@ 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"]
@ -751,31 +773,30 @@ class Quark:
save_file = self.save_file(
fid_list, fid_token_list, to_pdir_fid, pwd_id, stoken
)
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
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 []
except Exception as e:
print(f"❌ 转存测试失败: {str(e)}")
traceback.print_exc()
print(f"转存测试失败: {str(e)}")
def do_save_task(self, task):
# 判断资源失效记录
@ -1125,21 +1146,6 @@ 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"):
@ -1166,6 +1172,8 @@ 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)
@ -1195,7 +1203,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,
"其他推送渠道//此项可删": "配置方法同青龙"
},
"plugins": {
"media_servers": {
"emby": {
"url": "",
"token": ""
@ -20,37 +20,22 @@
"$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": "测试-综艺命名",
"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": "测试-去广告字符",
"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"
@ -58,7 +43,7 @@
{
"taskname": "测试-超期任务",
"shareurl": "https://pan.quark.cn/s/d07a34a9c695#/list/share/7e25ddd87cf64443b637125478733295-夸克自动转存测试",
"savepath": "/夸克自动转存测试/不会运行",
"savepath": "/夸克自动转存测试",
"pattern": "",
"replace": "",
"enddate": "2000-01-30",