Publish emlog via gitea-publish skill
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python3
|
||||
"""emlog REST API 客户端 — 发布文章/查询/分类/草稿/微语。
|
||||
|
||||
用法示例:
|
||||
python3 emlog.py post --title "标题" --content "正文" --sort-id 14 --tags "a,b"
|
||||
python3 emlog.py post --title "标题" --content-file /tmp/a.md --sort-id 14
|
||||
python3 emlog.py sorts
|
||||
python3 emlog.py list --sort-id 14 --count 10
|
||||
python3 emlog.py detail --id 123
|
||||
python3 emlog.py drafts
|
||||
python3 emlog.py note --text "微语内容"
|
||||
|
||||
鉴权:
|
||||
默认免签名(api_key);加 --sign 走签名鉴权 md5(req_time + api_key)
|
||||
环境变量:
|
||||
EMLOG_BASE_URL 默认 https://blog.apescale.com
|
||||
EMLOG_API_KEY API 秘钥
|
||||
"""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
BASE_URL = os.environ.get("EMLOG_BASE_URL", "https://blog.apescale.com")
|
||||
API_KEY = os.environ.get("EMLOG_API_KEY", "")
|
||||
|
||||
|
||||
def request(rest_api, params, method="POST"):
|
||||
url = f"{BASE_URL}/?rest-api={rest_api}"
|
||||
data = urllib.parse.urlencode(params).encode("utf-8")
|
||||
req = urllib.request.Request(url, data=data, method=method)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
return json.loads(resp.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as e:
|
||||
body = e.read().decode("utf-8", "ignore")
|
||||
try:
|
||||
return json.loads(body)
|
||||
except Exception:
|
||||
return {"code": 1, "msg": f"HTTP {e.code}: {body}"}
|
||||
except Exception as e:
|
||||
return {"code": 1, "msg": str(e)}
|
||||
|
||||
|
||||
def build_auth_params(args):
|
||||
p = {}
|
||||
if args.sign:
|
||||
t = str(int(time.time()))
|
||||
p["req_time"] = t
|
||||
p["req_sign"] = hashlib.md5((t + args.api_key).encode()).hexdigest()
|
||||
else:
|
||||
p["api_key"] = args.api_key
|
||||
return p
|
||||
|
||||
|
||||
def cmd_post(args):
|
||||
content = args.content
|
||||
if args.content_file:
|
||||
with open(args.content_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
params = {
|
||||
"title": args.title,
|
||||
"content": content,
|
||||
"sort_id": args.sort_id,
|
||||
"tags": args.tags,
|
||||
"draft": args.draft,
|
||||
"excerpt": args.excerpt,
|
||||
"alias": args.alias,
|
||||
"top": args.top,
|
||||
"allow_remark": args.allow_remark,
|
||||
}
|
||||
params = {k: v for k, v in params.items() if v not in (None, "")}
|
||||
params.update(build_auth_params(args))
|
||||
if args.id:
|
||||
# 更新已有文章:emlog 使用 article_update 接口(id 必填)
|
||||
params = {"id": args.id, **params}
|
||||
return request("article_update", params)
|
||||
return request("article_post", params)
|
||||
|
||||
|
||||
def cmd_list(args):
|
||||
params = {"count": args.count}
|
||||
if args.sort_id is not None:
|
||||
params["sort_id"] = args.sort_id
|
||||
if args.keyword:
|
||||
params["keyword"] = args.keyword
|
||||
if args.tag:
|
||||
params["tag"] = args.tag
|
||||
return request("article_list", params, method="GET")
|
||||
|
||||
|
||||
def cmd_sorts(args):
|
||||
return request("sort_list", {}, method="GET")
|
||||
|
||||
|
||||
def cmd_detail(args):
|
||||
return request("article_detail", {"id": args.id}, method="GET")
|
||||
|
||||
|
||||
def cmd_drafts(args):
|
||||
params = {}
|
||||
if args.count:
|
||||
params["count"] = args.count
|
||||
params.update(build_auth_params(args))
|
||||
return request("draft_list", params)
|
||||
|
||||
|
||||
def cmd_note(args):
|
||||
params = {"t": args.text}
|
||||
params.update(build_auth_params(args))
|
||||
return request("note_post", params)
|
||||
|
||||
|
||||
def main():
|
||||
global BASE_URL, API_KEY
|
||||
parser = argparse.ArgumentParser(description="emlog REST API 客户端")
|
||||
parser.add_argument("--base-url", default=BASE_URL)
|
||||
parser.add_argument("--api-key", default=API_KEY)
|
||||
parser.add_argument("--sign", action="store_true", help="使用签名鉴权")
|
||||
sub = parser.add_subparsers(dest="cmd", required=True)
|
||||
|
||||
p = sub.add_parser("post", help="发布/更新文章")
|
||||
p.add_argument("--id", default=None, help="文章 ID(更新已有文章时传入)")
|
||||
p.add_argument("--title", required=True)
|
||||
p.add_argument("--content", default="")
|
||||
p.add_argument("--content-file", default=None)
|
||||
p.add_argument("--sort-id", default=None)
|
||||
p.add_argument("--tags", default="")
|
||||
p.add_argument("--draft", default="n")
|
||||
p.add_argument("--excerpt", default="")
|
||||
p.add_argument("--alias", default="")
|
||||
p.add_argument("--top", default="n")
|
||||
p.add_argument("--allow-remark", default="n")
|
||||
p.set_defaults(func=cmd_post)
|
||||
|
||||
p = sub.add_parser("list", help="文章列表")
|
||||
p.add_argument("--sort-id", type=int, default=None)
|
||||
p.add_argument("--count", type=int, default=10)
|
||||
p.add_argument("--keyword", default="")
|
||||
p.add_argument("--tag", default="")
|
||||
p.set_defaults(func=cmd_list)
|
||||
|
||||
p = sub.add_parser("sorts", help="分类列表")
|
||||
p.set_defaults(func=cmd_sorts)
|
||||
|
||||
p = sub.add_parser("detail", help="文章详情")
|
||||
p.add_argument("--id", required=True)
|
||||
p.set_defaults(func=cmd_detail)
|
||||
|
||||
p = sub.add_parser("drafts", help="草稿列表")
|
||||
p.add_argument("--count", type=int, default=None)
|
||||
p.set_defaults(func=cmd_drafts)
|
||||
|
||||
p = sub.add_parser("note", help="发布微语")
|
||||
p.add_argument("--text", required=True)
|
||||
p.set_defaults(func=cmd_note)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.base_url = args.base_url or BASE_URL
|
||||
args.api_key = args.api_key or API_KEY
|
||||
BASE_URL, API_KEY = args.base_url, args.api_key
|
||||
|
||||
result = args.func(args)
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
if result.get("code") != 0:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user