fix(rsocials): list-and-match fallback to recover postizPostId after create

Postiz's POST /public/v1/posts response shape doesn't reliably include the
new post's id (varies by version). When parsing fails, query listPosts in a
narrow window right after create and match by integration+content to recover
the real id. Without this, reconcile can't find queued posts back in Postiz.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-04-17 11:08:47 -04:00
parent 6a335e4dba
commit 06b84bf2d7
1 changed files with 18 additions and 2 deletions

View File

@ -885,12 +885,28 @@ async function sendCampaignNodeToPostiz(
try {
const result = await createPost(config, payload);
// Postiz returns either { id } or an array — be defensive.
const postizPostId = (result as any)?.id
// Postiz returns either { id } or an array — be defensive on parse.
let postizPostId: string = (result as any)?.id
|| (Array.isArray(result) && (result[0] as any)?.id)
|| (result as any)?.posts?.[0]?.id
|| '';
// Fallback: Postiz's create response shape varies by version and often
// doesn't include the new post id. Query listPosts in a narrow window,
// then find by integration + content to recover the real id.
if (!postizPostId) {
try {
const windowStart = new Date(Date.now() - 60_000);
const windowEnd = new Date(Date.now() + 365 * 86400_000);
const listed = await listPosts(config, windowStart, windowEnd);
const match = listed.find(p =>
p.integration?.id === integrations[0].id &&
(p.content || '').trim() === payload.content.trim()
);
if (match) postizPostId = match.id;
} catch { /* leave id empty, reconcile will treat as lost */ }
}
_syncServer!.changeDoc<SocialsDoc>(docId, `postiz send ${nodeId}`, (d) => {
const f = d.campaignFlows?.[flowId];
if (!f) return;