Compare commits

..

4 Commits

Author SHA1 Message Date
Super-Passerby
b9b80b33a6
Merge e0cb7443fe into d9fc4659b8 2025-04-15 22:54:08 +08:00
Cp0204
d9fc4659b8 优化资源搜索来源切换逻辑
Some checks failed
Docker Publish / build-and-push (push) Has been cancelled
- 优化 CloudSaver 启用判断逻辑
- 搜索增加来源信息显示
2025-04-15 03:08:44 +08:00
Cp0204
8309f4a4d4 优化任务建议搜索逻辑
- 增加搜索防抖功能,避免频繁请求
- 调整搜索建议方法参数,简化逻辑
- 移除不必要的时间限制,提升用户体验
2025-04-15 02:55:34 +08:00
Cp0204
805f624b89 优化 CloudSaver 资源搜索功能
- 修复清洗引发的 list index out of range
- 增加正则表达式清洗标题和内容的逻辑
- 实现链接去重
- 前端提供更明确的服务器地址格式
2025-04-15 02:54:51 +08:00
3 changed files with 57 additions and 38 deletions

View File

@ -46,7 +46,7 @@ PYTHON_PATH = "python3" if os.path.exists("/usr/bin/python3") else "python"
SCRIPT_PATH = os.environ.get("SCRIPT_PATH", "./quark_auto_save.py") 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) DEBUG = os.environ.get("DEBUG", "false").lower() == "true"
config_data = {} config_data = {}
task_plugins_config_default = {} task_plugins_config_default = {}
@ -86,10 +86,7 @@ def get_login_token():
def is_login(): def is_login():
login_token = get_login_token() login_token = get_login_token()
if ( if session.get("token") == login_token or request.args.get("token") == login_token:
session.get("token") == login_token
or request.args.get("token") == login_token
):
return True return True
else: else:
return False return False
@ -224,7 +221,12 @@ def get_task_suggestions():
query = request.args.get("q", "").lower() query = request.args.get("q", "").lower()
deep = request.args.get("d", "").lower() deep = request.args.get("d", "").lower()
try: try:
if cs_data := config_data.get("source", {}).get("cloudsaver", {}): cs_data = config_data.get("source", {}).get("cloudsaver", {})
if (
cs_data.get("server")
and cs_data.get("username")
and cs_data.get("password")
):
cs = CloudSaver(cs_data.get("server")) cs = CloudSaver(cs_data.get("server"))
cs.set_auth( cs.set_auth(
cs_data.get("username", ""), cs_data.get("username", ""),
@ -237,16 +239,16 @@ def get_task_suggestions():
cs_data["token"] = search.get("new_token") cs_data["token"] = search.get("new_token")
Config.write_json(CONFIG_PATH, config_data) Config.write_json(CONFIG_PATH, config_data)
search_results = cs.clean_search_results(search.get("data")) search_results = cs.clean_search_results(search.get("data"))
return jsonify({"success": True, "data": search_results}) return jsonify({"success": True, "source": "CloudSaver", "data": search_results})
else: else:
return jsonify({"success": True, "message": search.get("message")}) return jsonify({"success": True, "message": search.get("message")})
else: else:
base_url = base64.b64decode("aHR0cHM6Ly9zLjkxNzc4OC54eXo=").decode() base_url = base64.b64decode("aHR0cHM6Ly9zLjkxNzc4OC54eXo=").decode()
url = f"{base_url}/task_suggestions?q={query}&d={deep}" url = f"{base_url}/task_suggestions?q={query}&d={deep}"
response = requests.get(url) response = requests.get(url)
return jsonify({"success": True, "data": response.json()}) return jsonify({"success": True, "source": "网络公开", "data": response.json()})
except Exception as e: except Exception as e:
return jsonify({"success": False, "message": str(e)}) return jsonify({"success": True, "message": f"error: {str(e)}"})
@app.route("/get_share_detail") @app.route("/get_share_detail")

View File

@ -1,3 +1,4 @@
import re
import requests import requests
@ -76,7 +77,10 @@ class CloudSaver:
if result.get("success"): if result.get("success"):
return result return result
else: else:
if result.get("message") == "无效的 token" or result.get("message") == "未提供 token": if (
result.get("message") == "无效的 token"
or result.get("message") == "未提供 token"
):
login_result = self.login() login_result = self.login()
if login_result.get("success"): if login_result.get("success"):
result = self.search(keyword, last_message_id) result = self.search(keyword, last_message_id)
@ -99,26 +103,40 @@ class CloudSaver:
Returns: Returns:
list: 夸克网盘链接列表 list: 夸克网盘链接列表
""" """
pattern_title = r"(名称|标题)[:]?(.*)"
pattern_content = r"(描述|简介)[:]?(.*)(链接|标签)"
clean_results = [] clean_results = []
link_array = []
for channel in search_results: for channel in search_results:
for item in channel.get("list", []): for item in channel.get("list", []):
cloud_links = item.get("cloudLinks", []) cloud_links = item.get("cloudLinks", [])
for link in cloud_links: for link in cloud_links:
if link.get("cloudType") == "quark": if link.get("cloudType") == "quark":
clean_results.append( # 清洗标题
{ title = item.get("title", "")
"shareurl": link.get("link"), if match := re.search(pattern_title, title, re.DOTALL):
"taskname": item.get("title", "") title = match.group(2)
.strip("名称:") title = title.replace("&", "&").strip()
.replace("&", "&"), # 清洗内容
"content": item.get("content", "") content = item.get("content", "")
.split("描述:")[1] if match := re.search(pattern_content, content, re.DOTALL):
.split("链接:")[0] content = match.group(2)
.replace('<mark class="highlight">', "") content = content.replace('<mark class="highlight">', "")
.replace("</mark>", ""), content = content.replace("</mark>", "")
"tags": item.get("tags", []), content = content.strip()
} # 链接去重
) if link.get("link") not in link_array:
link_array.append(link.get("link"))
clean_results.append(
{
"shareurl": link.get("link"),
"taskname": title,
"content": content,
"tags": item.get("tags", []),
"channel": item.get("channel", ""),
"channel_id": item.get("channelId", ""),
}
)
return clean_results return clean_results

View File

@ -198,7 +198,7 @@
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label">服务器</label> <label class="col-sm-2 col-form-label">服务器</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" v-model="formData.source.cloudsaver.server" class="form-control" placeholder="资源搜索服务器地址"> <input type="text" v-model="formData.source.cloudsaver.server" class="form-control" placeholder="资源搜索服务器地址,如 http://172.17.0.1:8008">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
@ -272,7 +272,7 @@
<div class="input-group"> <div class="input-group">
<input type="text" name="taskname[]" class="form-control" v-model="task.taskname" placeholder="必填" @focus="smart_param.showSuggestions=true;focusTaskname(index, task)" @input="changeTaskname(index, task)"> <input type="text" name="taskname[]" class="form-control" v-model="task.taskname" placeholder="必填" @focus="smart_param.showSuggestions=true;focusTaskname(index, task)" @input="changeTaskname(index, task)">
<div class="dropdown-menu show task-suggestions" v-if="smart_param.showSuggestions && smart_param.taskSuggestions.success && smart_param.index === index"> <div class="dropdown-menu show task-suggestions" v-if="smart_param.showSuggestions && smart_param.taskSuggestions.success && smart_param.index === index">
<div class="text-muted text-center" style="font-size:12px;">{{ smart_param.taskSuggestions.message ? smart_param.taskSuggestions.message : smart_param.taskSuggestions.data.length ? "以下资源来自网络公开搜索,请自行辨识,如有侵权请联系资源方" : "未搜索到资源" }}</div> <div class="text-muted text-center" style="font-size:12px;">{{ smart_param.taskSuggestions.message ? smart_param.taskSuggestions.message : smart_param.taskSuggestions.data.length ? `以下资源来自 ${smart_param.taskSuggestions.source} 搜索,请自行辨识,如有侵权请联系资源方` : "未搜索到资源" }}</div>
<div v-for="suggestion in smart_param.taskSuggestions.data" :key="suggestion.taskname" class="dropdown-item" @click.prevent="selectSuggestion(task, suggestion)" style="cursor: pointer;font-size: 12px;" :title="suggestion.content"> <div v-for="suggestion in smart_param.taskSuggestions.data" :key="suggestion.taskname" class="dropdown-item" @click.prevent="selectSuggestion(task, suggestion)" style="cursor: pointer;font-size: 12px;" :title="suggestion.content">
<span v-html="suggestion.verify ? '✅': '❔'"></span> {{ suggestion.taskname }} <span v-html="suggestion.verify ? '✅': '❔'"></span> {{ suggestion.taskname }}
<small class="text-muted"> <small class="text-muted">
@ -516,8 +516,8 @@
origin_savepath: "", origin_savepath: "",
taskSuggestions: {}, taskSuggestions: {},
showSuggestions: false, showSuggestions: false,
lastSuggestionsTime: 0,
isSearching: false, isSearching: false,
searchTimer: null,
}, },
activeTab: 'tasklist', activeTab: 'tasklist',
configModified: false, configModified: false,
@ -707,7 +707,12 @@
} }
}, },
changeTaskname(index, task) { changeTaskname(index, task) {
this.searchSuggestions(index, task.taskname, 500); if (this.smart_param.searchTimer) {
clearTimeout(this.smart_param.searchTimer);
}
this.smart_param.searchTimer = setTimeout(() => {
this.searchSuggestions(index, task.taskname, 0);
}, 1000);
if (this.smart_param.savepath) if (this.smart_param.savepath)
task.savepath = this.smart_param.savepath.replace('TASKNAME', task.taskname); task.savepath = this.smart_param.savepath.replace('TASKNAME', task.taskname);
}, },
@ -870,22 +875,16 @@
task.runweek = [1, 2, 3, 4, 5, 6, 7]; task.runweek = [1, 2, 3, 4, 5, 6, 7];
} }
}, },
searchSuggestions(index, taskname, limit_msec = 0) { searchSuggestions(index, taskname, deep = 1) {
if (taskname.length == 0) if (taskname.length == 0)
return return;
if (limit_msec > 0) { this.smart_param.isSearching = true;
const now = Date.now();
if (now - this.smart_param.lastSuggestionsTime < limit_msec)
return;
this.smart_param.lastSuggestionsTime = now;
}
this.smart_param.isSearching = true
this.smart_param.index = index; this.smart_param.index = index;
try { try {
axios.get('/task_suggestions', { axios.get('/task_suggestions', {
params: { params: {
q: taskname, q: taskname,
d: limit_msec == 0 ? 1 : 0 d: deep
} }
}).then(response => { }).then(response => {
this.smart_param.taskSuggestions = response.data; this.smart_param.taskSuggestions = response.data;