Add a Publisher abstraction and queued job to publish from the UI

Introduce Publisher/PublisherManager (WordPress + Reddit implementations)
so publishing logic is shared between the CLI, the queue, and future
network integrations. Add a "Publish" button on the Posts page that
dispatches PublishPostJob instead of blocking the request — Reddit's
publisher shells out to the existing Playwright sidecar and can take
tens of seconds, so it can't run synchronously in a web request.

Adds a `target` field (e.g. subreddit) and `publishing` status to Post,
plus a `publish_error` field so failures surface in the UI. Refactors
posts:publish to delegate to WordPressPublisher without changing its
CLI output contract (existing tests pass unchanged).

Also fixes two bugs found along the way: UpdatePostRequest was silently
dropping `published_url` from PATCH requests (never in its validation
rules, despite AI_API.md documenting it), and three Livewire index-page
tests were broken by the earlier auth change (never re-run after adding
the `auth` middleware) since they hit routes via HTTP without a logged-in
user.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
m105
2026-07-21 14:04:45 +03:00
co-authored by Claude Sonnet 5
parent 0cf72b44b7
commit 9278d2e8a0
26 changed files with 735 additions and 76 deletions
+21 -7
View File
@@ -15,17 +15,23 @@ Built with Laravel 13, Livewire, and Tailwind CSS.
- **Social Accounts** — logins for social networks (Twitter, Instagram,
Facebook, Reddit, TikTok, LinkedIn, YouTube, etc.).
- **Posts** — the actual content, each tied to a Site and optionally a
Social Account, moving through `draft -> scheduled -> published/failed`.
Social Account, moving through
`draft -> scheduled -> publishing -> published/failed`.
- A **JSON API** (`/api/sites`, `/api/accounts`, `/api/posts`) plus thin
Python CLI wrappers in `python_scripts/`, so an agent can poll for due
posts (`?due=1`) and drive the publish lifecycle without hand-rolling
HTTP requests.
- Built-in publishing paths:
- **WordPress**: `php artisan posts:publish {post_id}` posts directly to
a site's WordPress REST API and updates the post's status.
- **Reddit**: a standalone Playwright sidecar at
`sidecars/reddit-post/` logs in and creates a post.
- Anything else: publish however fits, then report back via the API.
- A **Publish button** in the UI (Posts page) for any post whose network has
a publisher wired up — queues a background job so slow, flaky publishers
(e.g. Reddit's browser automation) don't block the page.
- Built-in publishers (`app/Support/Publishing/`), one per network, resolved
by `Post.type`:
- **WordPress**: posts directly to a site's WordPress REST API. Also
available synchronously from the CLI: `php artisan posts:publish {post_id}`.
- **Reddit**: drives a standalone Playwright sidecar at
`sidecars/reddit-post/` that logs in and creates a post.
- Anything else: no publisher yet — publish however fits, then report
back via the API.
See `AI_API.md` for the full API reference and publishing contract, and
`python_scripts/README.md` for the CLI wrapper usage.
@@ -80,6 +86,14 @@ This starts the PHP dev server, queue listener, log viewer (Pail), and
Vite dev server together. The app is served at `http://localhost:8000` by
default.
Outside of `composer run dev` (e.g. a plain production deploy), the Publish
button needs its own queue worker running, or queued publishes will just sit
in the `jobs` table:
```bash
php artisan queue:work
```
### Reddit sidecar (optional)
If you plan to publish to Reddit, set up the Playwright sidecar separately: