# -*- coding: utf-8 -*- r'''通过 Halo API 把文章写进去(第二版:先登录拿 cookie)。 == 第一版为什么不行 == 我直接用 `Authorization: Basic` 打 console API,结果 **302**(跳登录页)。 Halo 2.x 的 console API(`/apis/api.console.halo.run/...`)**不认 Basic**, 它要的是: * **会话 cookie**(网页登录后拿到的那个),或者 * **Personal Access Token**(`Authorization: Bearer xxx`) 而 `users/-` 返回 200 是**假的** —— 那个端点匿名也放行(返回空)。 == 这一版怎么做 == 走**网页表单登录**拿会话 cookie: POST /login (form-urlencoded: username, password) -> Set-Cookie: SESSION=xxx 然后带着这个 cookie 调 console API 建文章。 == 文章内容怎么给 == Halo 建文章的接口要 `PostRequest`: {"post": {...Post 资源...}, "content": {"raw": "Markdown 源码", "content": "渲染后的 HTML", "rawType": "markdown"}} **`content` 和 `raw` 都要给**: * `content`(HTML)是前台直接渲染的 * `raw`(Markdown)是编辑器里显示/可再编辑的 只给一个的话,要么前台是空的,要么编辑器打开是乱码。 == 顺手 == `md_to_html` 是**针对这份固定正文**写的简易转换,不是通用解析器 —— 不引第三方库,行为可控。支持的语法就是我正文里用到的那些。 ''' from __future__ import annotations import base64 import http.cookiejar import json import re import sys import urllib.error import urllib.parse import urllib.request from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "_build")) from lssh import run # noqa: E402 PWFILE = ROOT / "_build" / ".halo_password" BASE = "http://127.0.0.1:3001" USER = "xmz7891" def main() -> int: print("=" * 62) print(" Halo:表单登录 -> 发文章") print("=" * 62) print() pw = PWFILE.read_text(encoding="utf-8").strip() # ---------------------------------------------------------------- 登录 print("── 1. 表单登录拿 cookie ──") out = run(r''' rm -f /tmp/halo_cookie.txt echo " 试 POST /login:" curl -s -c /tmp/halo_cookie.txt -o /tmp/halo_login_out.txt -w " HTTP %{http_code} 跳转-> %{redirect_url}\n" \ --max-time 15 -X POST http://127.0.0.1:3001/login \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "username=__U__" \ --data-urlencode "password=__PW__" echo " 拿到的 cookie:" grep -v '^#' /tmp/halo_cookie.txt 2>/dev/null | awk '{print " "$6" = "substr($7,1,20)"..."}' || echo " (没有 cookie)" echo echo " 用 cookie 打 console API:" curl -s -b /tmp/halo_cookie.txt -o /dev/null -w " posts -> HTTP %{http_code}\n" \ --max-time 10 "http://127.0.0.1:3001/apis/api.console.halo.run/v1alpha1/posts?page=0&size=5" '''.replace("__PW__", pw).replace("__U__", USER), timeout=240, quiet=True) print(out[1] if isinstance(out, tuple) else out) print() print("── 2. 如果 cookie 有效,列出现在的文章 ──") out = run(r''' curl -s -b /tmp/halo_cookie.txt --max-time 10 \ "http://127.0.0.1:3001/apis/api.console.halo.run/v1alpha1/posts?page=0&size=20" \ > /tmp/halo_posts.json 2>/dev/null head -c 600 /tmp/halo_posts.json echo ''', timeout=200, quiet=True) print(out[1] if isinstance(out, tuple) else out) return 0 if __name__ == "__main__": sys.exit(main())