91 lines
2.3 KiB
Python
91 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Any, Protocol
|
|
|
|
|
|
@dataclass
|
|
class PublishResult:
|
|
mode: str
|
|
status: str
|
|
slug: str
|
|
blog_url: str
|
|
public_ok: bool = False
|
|
error: str | None = None
|
|
|
|
|
|
class BlogClient(Protocol):
|
|
def create_post(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
...
|
|
|
|
def publish_post(self, slug: str) -> None:
|
|
...
|
|
|
|
|
|
def dry_run_publish(slug: str, base_url: str) -> PublishResult:
|
|
return PublishResult(
|
|
mode="dry-run",
|
|
status="ok",
|
|
slug=slug,
|
|
blog_url=f"{base_url.rstrip('/')}/posts/{slug}",
|
|
public_ok=True,
|
|
)
|
|
|
|
|
|
def publish_markdown(
|
|
*,
|
|
title: str,
|
|
markdown: str,
|
|
tags: list[str],
|
|
slug: str,
|
|
base_url: str,
|
|
mode: str,
|
|
markdown_report: dict[str, Any],
|
|
client: BlogClient | None,
|
|
) -> PublishResult:
|
|
blocking_errors = markdown_report.get("blocking_errors", []) or []
|
|
blog_url = f"{base_url.rstrip('/')}/posts/{slug}"
|
|
if blocking_errors:
|
|
return PublishResult(
|
|
mode=mode,
|
|
status="blocked",
|
|
slug=slug,
|
|
blog_url=blog_url,
|
|
public_ok=False,
|
|
error=";".join(blocking_errors),
|
|
)
|
|
if mode == "dry-run":
|
|
return dry_run_publish(slug, base_url)
|
|
if client is None:
|
|
return PublishResult(
|
|
mode=mode,
|
|
status="failed",
|
|
slug=slug,
|
|
blog_url=blog_url,
|
|
public_ok=False,
|
|
error="missing_blog_client",
|
|
)
|
|
|
|
payload = {"title": title, "content": markdown, "tags": tags, "slug": slug}
|
|
try:
|
|
create_resp = client.create_post(payload)
|
|
created_slug = create_resp.get("slug") or slug
|
|
if mode == "publish":
|
|
client.publish_post(created_slug)
|
|
return PublishResult(
|
|
mode=mode,
|
|
status="ok",
|
|
slug=created_slug,
|
|
blog_url=f"{base_url.rstrip('/')}/posts/{created_slug}",
|
|
public_ok=mode == "publish",
|
|
)
|
|
except Exception as exc:
|
|
return PublishResult(
|
|
mode=mode,
|
|
status="failed",
|
|
slug=slug,
|
|
blog_url=blog_url,
|
|
public_ok=False,
|
|
error=f"{type(exc).__name__}: {exc}",
|
|
)
|