Releases: Matthew-Selvam/Open-Dispatch
v0.4.0 — Media transcoding · Postgres backend
What's new in v0.4.0
🎨 Media transcoding (Pillow-backed)
Per-platform image resize for 10 platform specs out of the box: `instagram` (square), `instagram_portrait` (4:5), `instagram_reels` (9:16), `twitter` (16:9), `linkedin` (1200x627), `bluesky`, `telegram`, `threads`, `youtube_thumbnail`, `youtube_short_thumbnail`.
- Honors EXIF orientation (phone photos no longer come out sideways)
- Flattens RGBA/LA/P modes to RGB before JPEG encoding
- Centered aspect crop, no distortion
- Never upscales — quality trumps filling the spec
- LANCZOS resampling, progressive JPEG, optimize=True
REST:
```bash
curl -X POST "http://localhost:8000/media/transcode?platform=twitter" \
-H "Content-Type: image/jpeg" --data-binary @photo.jpg --output photo.twitter.jpg
curl http://localhost:8000/media/specs | jq .twitter
```
Python:
```python
from media import transcode_image
transcode_image("photo.jpg", "instagram") # → photo.instagram.jpg
```
🐘 Postgres queue backend
Opt in via `DATABASE_URL` for true ACID + cross-region multi-worker setups.
- Auto-creates schema on first use (table + partial index on queued rows)
- `mark_publishing` uses conditional UPDATE (`WHERE id = %s AND status = 'queued'`) — two workers in different regions can't double-claim
- `mark_failed` uses `attempts = attempts + 1` directly (no read-modify-write race)
- Factory falls back gracefully: `DATABASE_URL` → Postgres, else `REDIS_URL` → Redis, else JSONL
- `pip install open-dispatch[postgres]` for the optional psycopg2 dep
📜 OSS scaffolding
- `LICENSE` — MIT (matches what we'd advertised since day one)
- `CONTRIBUTING.md` — quick setup, project layout map, step-by-step "add a platform adapter" recipe, code style, commit conventions
Stats
- 129 tests passing (up from 102 in v0.3.0)
- 7 platforms supported, 10 image specs
- 3 queue backends (JSONL / Redis / Postgres) sharing one `QueueProtocol`
- 0 net runtime deps added beyond Pillow (Postgres + Redis remain optional extras)
Coming next
- TikTok adapter (still waiting on Content Posting API approval)
- Video transcoding (ffmpeg-backed, future)
- npm publish for the n8n node
v0.3.0 — YouTube Shorts · Redis backend · 102 tests
What's new in v0.3.0
📹 YouTube Shorts adapter
`adapters/youtube.py` — full Data API v3 resumable upload flow:
- OAuth2 refresh token flow (run once, store, never re-auth)
- Auto-appends `#Shorts` to description for correct YouTube classification
- Account-scoped refresh tokens
- Privacy whitelist (public/unlisted/private)
- Format key: `youtube_short` { video_path, title?, description?, tags?, privacy?, caption? }
The AI caption adapter also understands YouTube — emits `{title, description}` shape with 100/5000 char enforcement.
🔴 Redis queue backend
`api/queue.py` — opt-in via `REDIS_URL`:
- Multi-worker safe via guarded `queued → publishing` transition
- Fast `list_due` via ZSET keyed by scheduled_for epoch
- Single `QueueProtocol` interface across both backends — worker code unchanged
```bash
docker compose --profile redis up -d # bundles redis:7-alpine
```
`pip install open-dispatch[redis]` to add the optional dep.
✅ Adapter test coverage
30+ new unit tests in `tests/test_adapters.py` + `tests/test_redis_queue.py` — mock-based, no network, no real creds. Every platform exercised across missing-creds / empty-payload / happy-path / HTTP-error paths.
Stats
- 102 tests passing (up from 60 in v0.2.0)
- 7 platforms supported: Twitter / X, Bluesky, Telegram, Instagram, LinkedIn, Threads, YouTube Shorts
- 49 source files, 0 new runtime dependencies (Redis is optional)
Coming next
- TikTok adapter (still waiting on Content Posting API approval)
- Postgres queue (for cross-region multi-worker)
- Media transcoding (per-platform image/video resize)
v0.2.0 — Web UI · Threads · AI captions · n8n node
What's new in v0.2.0
Four major roadmap items shipped:
🖥️ Web UI
Dark terminal-themed dashboard powered by HTMX + Jinja2 — no JS build step, vendored htmx.min.js (51KB).
GET /— queue dashboard with status filters and 5s auto-refreshGET /compose— post composer with platform checkboxes (configured-creds indicator), schedule, webhook, and ✦ Adapt with AI preview buttonGET /queue/{id}— row detail with retry, ContentUnit JSON viewer
The JSON API stays back-compat via content negotiation: `Accept: application/json` → dict, `Accept: text/html` → HTML page.
🧵 Threads adapter
Meta Threads Graph API integration — text, image, video posts. Account-scoped creds. Configurable settle delay for media (Meta recommends ~30s between container creation and publish).
✨ AI caption adapter
One source caption → 6 platform-native posts, respecting char limits and style conventions.
```bash
curl -X POST http://localhost:8000/ai/adapt -H "Content-Type: application/json" -d '{
"text": "Open-Dispatch v0.2 ships: web UI, Threads, AI caption rewriter.",
"platforms": ["twitter", "bluesky", "linkedin", "instagram", "threads"]
}'
```
Provider priority: Ollama (local) → OpenRouter (cloud) → heuristic (no LLM). The heuristic fallback means the endpoint never 500s on missing creds.
🔌 n8n community node
`n8n-nodes-open-dispatch` — single node with 5 operations: Dispatch, Adapt Caption with AI, Get Queue Row, Retry Queue Row, List Queue.
```bash
cd n8n-node && npm install --ignore-scripts && npm run build
```
Stats
- 60 tests passing (web UI: 9, AI adapter: 24, schema/queue/api: 25, Threads: 2)
- 6 platforms supported: Twitter / X, Bluesky, Telegram, Instagram, LinkedIn, Threads
- 0 production dependencies added beyond the minimum
Coming next
- TikTok adapter (waiting on Content Posting API approval)
- YouTube Shorts adapter
- Redis + RQ queue backend (multi-worker production setups)
- Media transcoding (per-platform image/video resize)