Add OpenClaw skills, platform kit, and template docs
Made-with: Cursor
This commit is contained in:
142
logistics-tracker/scripts/main.py
Normal file
142
logistics-tracker/scripts/main.py
Normal file
@@ -0,0 +1,142 @@
|
||||
import requests
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
|
||||
def get_api_key(key_name):
|
||||
"""从api-key-vault读取Key"""
|
||||
vault_path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..", "..", # 从scripts/退到logistics-tracker/再退到OpenClaw/
|
||||
"api-key-vault", "scripts", "vault.py"
|
||||
)
|
||||
vault_path = os.path.normpath(vault_path)
|
||||
|
||||
result = subprocess.run(
|
||||
["python", vault_path, "get", key_name],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
key = result.stdout.strip()
|
||||
|
||||
if not key or key == "ERROR:KEY_NOT_FOUND":
|
||||
return None
|
||||
return key
|
||||
|
||||
|
||||
def check_entitlement(skill_slug):
|
||||
auth_base = (os.getenv("JIANGCHANG_AUTH_BASE_URL") or "").strip().rstrip("/")
|
||||
if not auth_base:
|
||||
return True, ""
|
||||
|
||||
user_id = (os.getenv("JIANGCHANG_USER_ID") or "").strip()
|
||||
if not user_id:
|
||||
return False, "鉴权失败:缺少用户身份(JIANGCHANG_USER_ID)"
|
||||
|
||||
auth_api_key = (os.getenv("JIANGCHANG_AUTH_API_KEY") or "").strip()
|
||||
timeout = int((os.getenv("JIANGCHANG_AUTH_TIMEOUT_SECONDS") or "5").strip())
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if auth_api_key:
|
||||
headers["Authorization"] = f"Bearer {auth_api_key}"
|
||||
|
||||
payload = {
|
||||
"user_id": user_id,
|
||||
"skill_slug": skill_slug,
|
||||
"trace_id": (os.getenv("JIANGCHANG_TRACE_ID") or "").strip(),
|
||||
"context": {"entry": "main.py"},
|
||||
}
|
||||
try:
|
||||
res = requests.post(
|
||||
f"{auth_base}/api/entitlements/check",
|
||||
json=payload,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
)
|
||||
except requests.RequestException as exc:
|
||||
return False, f"鉴权请求失败:{exc}"
|
||||
|
||||
if res.status_code != 200:
|
||||
return False, f"鉴权服务异常:HTTP {res.status_code}"
|
||||
try:
|
||||
body = res.json()
|
||||
except ValueError:
|
||||
return False, "鉴权服务异常:返回非 JSON"
|
||||
|
||||
code = body.get("code")
|
||||
data = body.get("data") or {}
|
||||
if code != 200:
|
||||
return False, str(body.get("msg") or "鉴权失败")
|
||||
if not data.get("allow", False):
|
||||
return False, str(data.get("reason") or "未购买或已过期")
|
||||
return True, ""
|
||||
|
||||
|
||||
def query_tracking(tracking_number):
|
||||
api_key = get_api_key("17track")
|
||||
if not api_key:
|
||||
return "错误:未找到17track的API Key,请先运行:\npython api-key-vault/scripts/vault.py set 17track 你的Key"
|
||||
|
||||
url = "https://api.17track.net/track/v2.2/gettrackinfo"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"17token": api_key
|
||||
}
|
||||
body = {
|
||||
"data": [{"number": tracking_number}]
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, json=body, headers=headers, timeout=10)
|
||||
result = response.json()
|
||||
|
||||
accepted = result.get("data", {}).get("accepted", [])
|
||||
if not accepted:
|
||||
return f"抱歉,单号 {tracking_number} 查询不到信息,可能还未入网,请稍后再试。"
|
||||
|
||||
track_info = accepted[0].get("track", {})
|
||||
providers = track_info.get("tracking", {}).get("providers", [])
|
||||
|
||||
if not providers or not providers[0].get("events"):
|
||||
return f"📦 单号:{tracking_number}\n该单号已入网,暂无轨迹更新,请稍后再查。"
|
||||
|
||||
events = providers[0]["events"]
|
||||
latest = events[0]
|
||||
|
||||
recent_lines = []
|
||||
for e in events[:3]:
|
||||
time = e.get("time_iso", "")
|
||||
location = e.get("location", "") or "未知"
|
||||
desc = e.get("description", "")
|
||||
recent_lines.append(f" · {time} {location} {desc}")
|
||||
|
||||
recent_text = "\n".join(recent_lines)
|
||||
|
||||
return (
|
||||
f"📦 单号:{tracking_number}\n"
|
||||
f"📍 最新状态:{latest.get('description', '未知')}\n"
|
||||
f"🕐 更新时间:{latest.get('time_iso', '未知')}\n"
|
||||
f"🗺 最新位置:{latest.get('location', '未知')}\n\n"
|
||||
f"最近轨迹:\n{recent_text}"
|
||||
)
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
return "查询超时,请稍后重试。"
|
||||
except Exception as e:
|
||||
return f"查询失败:{str(e)}"
|
||||
|
||||
|
||||
def main(argv=None) -> int:
|
||||
args = argv if argv is not None else sys.argv[1:]
|
||||
if len(args) < 1:
|
||||
print("用法:python main.py <单号>")
|
||||
return 1
|
||||
ok, reason = check_entitlement("logistics-tracker")
|
||||
if not ok:
|
||||
print(f"❌ {reason}")
|
||||
return 1
|
||||
print(query_tracking(args[0]))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user