← back to Dw Slideshow Gen
postiz: multi-channel draft staging (--channel all|a,b), pickIntegrations, single upload fanned to N channels
95bb63bc3564a405e2abb763baa20fcad52d1675 · 2026-06-29 10:50:08 -0700 · Steve Abrams
Files touched
Diff
commit 95bb63bc3564a405e2abb763baa20fcad52d1675
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jun 29 10:50:08 2026 -0700
postiz: multi-channel draft staging (--channel all|a,b), pickIntegrations, single upload fanned to N channels
---
index.js | 7 ++++---
lib/post.js | 22 ++++++++++++----------
2 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/index.js b/index.js
index 3610110..a1e7da4 100644
--- a/index.js
+++ b/index.js
@@ -104,12 +104,13 @@ if (cmd === 'post') {
console.error(` [post] ${pkg.spec_id}: local draft package (${pkg.slides} slides) -> ${pkg.zipPath || pkg.pkgDir} ($0, no network)`)
if (!a.postiz) continue
const r = await stageToPostiz(dir, process.env, { confirm: a.confirm, channel: a.channel, schedule: a.schedule })
+ const chNames = (r.channels || []).map(c => `${c.identifier}(${c.name})`).join(', ')
if (r.gated) console.error(` [post] ${pkg.spec_id}: Postiz skipped — ${r.reason}`)
else if (r.error) console.error(` [post] ${pkg.spec_id}: Postiz error — ${r.error}`)
else if (r.dryRun) {
- console.error(` [post] ${pkg.spec_id}: DRY-RUN ${r.type} → ${r.channel.identifier} (${r.channel.name}), ${r.images} images. Add --confirm to stage. Body:`)
- console.error(' ' + JSON.stringify(r.body).replace(/\n/g, ' ').slice(0, 600))
- } else if (r.staged) console.error(` [post] ${pkg.spec_id}: Postiz ${r.type} STAGED → ${r.channel.identifier} (${r.channel.name}) postId=${r.postId} — review/publish at platform.postiz.com`)
+ console.error(` [post] ${pkg.spec_id}: DRY-RUN ${r.type} → ${chNames}, ${r.images} images. Add --confirm to stage. Body:`)
+ console.error(' ' + JSON.stringify(r.body).replace(/\n/g, ' ').slice(0, 700))
+ } else if (r.staged) console.error(` [post] ${pkg.spec_id}: Postiz ${r.type} STAGED → ${chNames} postIds=${(r.postIds || []).join(',')} — review/publish at platform.postiz.com`)
}
console.error([
'',
diff --git a/lib/post.js b/lib/post.js
index af45846..840385c 100644
--- a/lib/post.js
+++ b/lib/post.js
@@ -73,29 +73,31 @@ export async function stageToPostiz(renderDir, env, opts = {}) {
const dateISO = opts.schedule || new Date().toISOString()
const client = new Postiz(apiKey)
- // pick channel (read-only)
- let integration
+ // pick channel(s) (read-only). --channel all|a,b -> multiple
+ let chosen
try {
const list = await client.integrations()
- integration = pickIntegration(list, opts.channel)
+ chosen = pickIntegrations(list, opts.channel)
} catch (e) { return { staged: false, error: `integrations: ${e.message}` } }
- if (!integration) return { staged: false, gated: true, reason: 'no connected channels — connect TikTok in Postiz first' }
+ if (!chosen.length) return { staged: false, gated: true, reason: 'no connected channels — connect a channel in Postiz first' }
+ const ids = chosen.map(c => c.id)
+ // schedule needs per-provider settings, so it only supports ONE channel here; draft is multi.
const mkBody = media => opts.schedule
- ? buildScheduleBody({ integrationId: integration.id, identifier: integration.identifier, content, media, dateISO, tiktok: opts.tiktok })
- : buildDraftBody({ integrationId: integration.id, content, media, dateISO })
+ ? buildScheduleBody({ integrationId: ids[0], identifier: chosen[0].identifier, content, media, dateISO, tiktok: opts.tiktok })
+ : buildDraftBodyMulti({ integrationIds: ids, content, media, dateISO })
// dry-run: show the body with placeholder media, no upload, no post
if (!opts.confirm) {
const placeholder = m.png_paths.map((p, i) => ({ id: `<upload_${i + 1}>`, path: `https://uploads.postiz.com/${path.basename(p)}` }))
- return { staged: false, dryRun: true, channel: integration, type: opts.schedule ? 'schedule' : 'draft',
+ return { staged: false, dryRun: true, channels: chosen, type: opts.schedule ? 'schedule' : 'draft',
images: m.png_paths.length, body: mkBody(placeholder) }
}
- // live: upload each PNG, then create the post
+ // live: upload each PNG once (shared across channels), then create the post
const media = []
for (const p of m.png_paths) media.push(await client.upload(p))
const created = await client.createPost(mkBody(media))
- const postId = Array.isArray(created) ? created[0]?.postId || created[0]?.id : created.id || created.postId
- return { staged: true, type: opts.schedule ? 'schedule' : 'draft', channel: integration, postId, raw: created }
+ const ids2 = (Array.isArray(created) ? created : [created]).map(x => x?.postId || x?.id).filter(Boolean)
+ return { staged: true, type: opts.schedule ? 'schedule' : 'draft', channels: chosen, postIds: ids2, raw: created }
}
← 5481d94 auto-save: 2026-06-29T10:48:32 (4 files) — lib/post.js lib/p
·
back to Dw Slideshow Gen
·
postiz: per-provider settings in draft body (hosted API requ 0b44dfb →