@acedatacloud/skills 2026.628.3 → 2026.628.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/zhihu/scripts/blog.py +26 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acedatacloud/skills",
|
|
3
|
-
"version": "2026.628.
|
|
3
|
+
"version": "2026.628.4",
|
|
4
4
|
"description": "Agent Skills for AceDataCloud AI services — music, image, video generation, LLM chat, web search. Compatible with Claude Code, GitHub Copilot, Gemini CLI, OpenAI Codex, and 30+ AI coding agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-skills",
|
|
@@ -257,9 +257,29 @@ ZH_UPLOADED_IMAGES = "https://zhuanlan.zhihu.com/api/uploaded_images"
|
|
|
257
257
|
ZH_IMAGES = "https://api.zhihu.com/images"
|
|
258
258
|
OSS_ENDPOINT = "https://zhihu-pics-upload.zhimg.com"
|
|
259
259
|
OSS_BUCKET = "zhihu-pics"
|
|
260
|
-
|
|
260
|
+
# A src already on Zhihu's own CDN needs no re-upload. uploaded_images hands back
|
|
261
|
+
# a pic-private.zhihu.com URL for draft-scoped images, so skip those too.
|
|
262
|
+
_ZHIMG_HOSTS = ("zhimg.com", "pic-private.zhihu.com")
|
|
261
263
|
_IMG_SRC_RE = re.compile(r'(<img[^>]*?\ssrc=["\'])([^"\']+)(["\'])', re.IGNORECASE)
|
|
262
264
|
_MD_IMG_RE = re.compile(r'(!\[[^\]]*\]\()(\s*<?)([^)\s>]+)(>?\s*\))')
|
|
265
|
+
# uploaded_images returns a DRAFT-SCOPED signed pic-private URL whose auth_key
|
|
266
|
+
# expires; reduce any Zhihu image URL to the durable public form Zhihu serves
|
|
267
|
+
# after publish (picx.zhimg.com/v2-<hash>.<ext>).
|
|
268
|
+
_ZH_IMG_HASH = re.compile(r'(v2-[0-9a-f]+)(?:~[^."?\']*)?\.(png|jpe?g|gif|webp)', re.IGNORECASE)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _on_zhihu_cdn(src: str) -> bool:
|
|
272
|
+
# Match on the parsed host (not a substring) so an external host that merely
|
|
273
|
+
# contains "zhimg.com" (e.g. my-zhimg.com) isn't wrongly treated as hosted.
|
|
274
|
+
host = (urllib.parse.urlsplit(src).hostname or "") if src else ""
|
|
275
|
+
return any(host == h or host.endswith("." + h) for h in _ZHIMG_HOSTS)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _canonical_zhimg(url):
|
|
279
|
+
if not url:
|
|
280
|
+
return url
|
|
281
|
+
m = _ZH_IMG_HASH.search(url)
|
|
282
|
+
return f"https://picx.zhimg.com/{m.group(1)}.{m.group(2).lower()}" if m else url
|
|
263
283
|
|
|
264
284
|
|
|
265
285
|
def _raw(method, url, jar, *, headers=None, data=None, timeout=60):
|
|
@@ -312,7 +332,7 @@ def _upload_image_url(jar, src: str):
|
|
|
312
332
|
except json.JSONDecodeError:
|
|
313
333
|
return None
|
|
314
334
|
if isinstance(d, dict) and d.get("src"):
|
|
315
|
-
return d["src"]
|
|
335
|
+
return _canonical_zhimg(d["src"])
|
|
316
336
|
return None
|
|
317
337
|
|
|
318
338
|
|
|
@@ -380,13 +400,13 @@ def _upload_image_binary(jar, data: bytes):
|
|
|
380
400
|
upload_token = token_data.get("upload_token") or {}
|
|
381
401
|
if upload_file.get("state") == 1: # already on Zhihu — just resolve its hash
|
|
382
402
|
object_key = _wait_image_ready(jar, upload_file.get("image_id", ""))
|
|
383
|
-
return f"https://pic4.zhimg.com/{object_key}" if object_key else None
|
|
403
|
+
return _canonical_zhimg(f"https://pic4.zhimg.com/{object_key}") if object_key else None
|
|
384
404
|
object_key = upload_file.get("object_key", "")
|
|
385
405
|
if not object_key or not _oss_put(object_key, data, upload_token):
|
|
386
406
|
return None
|
|
387
407
|
if data[:6] in (b"GIF87a", b"GIF89a"):
|
|
388
408
|
object_key += ".gif"
|
|
389
|
-
return f"https://pic4.zhimg.com/{object_key}"
|
|
409
|
+
return _canonical_zhimg(f"https://pic4.zhimg.com/{object_key}")
|
|
390
410
|
|
|
391
411
|
|
|
392
412
|
def _download_image(src: str):
|
|
@@ -400,7 +420,7 @@ def _download_image(src: str):
|
|
|
400
420
|
def count_images(content: str) -> int:
|
|
401
421
|
srcs = {m.group(2) for m in _IMG_SRC_RE.finditer(content or "")}
|
|
402
422
|
srcs |= {m.group(3) for m in _MD_IMG_RE.finditer(content or "")}
|
|
403
|
-
return sum(1 for s in srcs if
|
|
423
|
+
return sum(1 for s in srcs if not _on_zhihu_cdn(s))
|
|
404
424
|
|
|
405
425
|
|
|
406
426
|
def rehost_images(jar, content: str):
|
|
@@ -410,7 +430,7 @@ def rehost_images(jar, content: str):
|
|
|
410
430
|
stats = {"found": 0, "rehosted": 0, "failed": 0}
|
|
411
431
|
|
|
412
432
|
def resolve(src: str) -> str:
|
|
413
|
-
if not src or
|
|
433
|
+
if not src or _on_zhihu_cdn(src):
|
|
414
434
|
return src
|
|
415
435
|
if src in cache:
|
|
416
436
|
return cache[src]
|