GEO Task Worker v2 免安装版 (含嵌入式 Python + 全部依赖)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

108 lines
4.2 KiB

import json
import re
from datetime import datetime, timezone, timedelta
from typing import Any
TZ_CN = timezone(timedelta(hours=8))
def _now_collect_time() -> str:
return datetime.now(TZ_CN).strftime("%Y-%m-%d %H:%M:%S")
def format_collected_at(value: Any = None) -> str:
if value is None or (isinstance(value, str) and not value.strip()):
return _now_collect_time()
if isinstance(value, datetime):
dt = value
if dt.tzinfo is not None:
dt = dt.astimezone(TZ_CN)
return dt.strftime("%Y-%m-%d %H:%M:%S")
s = str(value).strip()
if re.fullmatch(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}", s):
return s
if re.fullmatch(r"\d{4}-\d{2}-\d{2}", s):
return f"{s} 00:00:00"
try:
dt = datetime.fromisoformat(s.replace("Z", "+00:00"))
if dt.tzinfo is not None:
dt = dt.astimezone(TZ_CN)
return dt.strftime("%Y-%m-%d %H:%M:%S")
except Exception:
pass
m = re.match(r"^(\d{4})[/-](\d{1,2})[/-](\d{1,2})[ T](\d{1,2}):(\d{1,2})(?::(\d{1,2}))?", s)
if m:
y, mo, d, h, mi, sec = m.groups()
return f"{int(y):04d}-{int(mo):02d}-{int(d):02d} {int(h):02d}:{int(mi):02d}:{int(sec or 0):02d}"
print(f" [WARN] collectedAt 无法解析 {s!r}, 使用当前时间")
return _now_collect_time()
def build_submit_payload(task: dict, parsed: dict, location: str = "") -> dict:
result = parsed.get("result") or {}
sources = parsed.get("sources") or []
answer = (result.get("answer") or "").strip()
think = (result.get("thinking_process") or "").strip() or None
related = result.get("related_questions") or []
if isinstance(related, list):
extended = "\n".join(str(x) for x in related if x) or None
else:
extended = str(related) if related else None
search_links = []
for i, sr in enumerate(sources, 1):
url = sr.get("source_url") or ""
if not url:
continue
search_links.append({
"url": url, "index": i,
"title": sr.get("source_title") or "",
"source": sr.get("source_name") or "",
"snippet": sr.get("snippet") or sr.get("body") or None,
"site_name": sr.get("source_name") or "",
"site_icon": sr.get("source_icon") or "",
"published_time": sr.get("source_publish_date") or "",
})
adopted = [{"url": u, "title": ""} for u in (result.get("cited_links") or []) if u]
shared = []
share_link = result.get("share_link") or ""
if share_link:
shared.append({"url": share_link, "title": ""})
meta_infos = []
for img in (result.get("image_links") or []):
if img:
meta_infos.append({
"source_type": "image", "url": img, "title": "", "summary": "",
"website_name": "", "icon": "",
"value": json.dumps({"images": [{"full_size_url": [img]}], "videos": []}, ensure_ascii=False),
})
for vid in (result.get("video_links") or []):
if vid:
meta_infos.append({
"source_type": "video", "url": vid, "title": "", "summary": "",
"website_name": "", "icon": "",
"value": json.dumps({"images": [], "videos": [{"url": vid}]}, ensure_ascii=False),
})
deep = int(task.get("deepThinking") if task.get("deepThinking") is not None
else parsed.get("deep_thinking") or 0)
web = int(task.get("webSearch") if task.get("webSearch") is not None
else (1 if parsed.get("is_online") else 0))
task_id = str(task.get("id") or "").strip()
dispatch_id = str(task.get("dispatchId") or "").strip()
collected_at = format_collected_at(
parsed.get("collect_time") or (parsed.get("result") or {}).get("collect_time")
or task.get("collectedAt")
)
return {
"id": task_id, "dispatchId": dispatch_id, "collectedAt": collected_at,
"answer": answer, "thinkText": think,
"deepThinking": 1 if deep else 0, "webSearch": 1 if web else 0,
"model": task.get("model") or "", "location": location or "",
"extendedQuestion": extended, "searchLinks": search_links,
"adoptedLinks": adopted, "sharedLinks": shared,
"metaInfos": meta_infos, "productLinkList": [],
}