Skip to content

Cross-posting: state, idempotency, and Cyrillic issues

4 min read
Maksim Vaisgerberg
APIcross-postingCyrillic alphabetduplicatesidempotencemarkdownpipelineposting automationstatetimeouts
Cross-posting: state, idempotency, and Cyrillic issues

Cross-posting: state, idempotency, and Cyrillic issues

Automating cross-posting articles to social networks is a task that seems simple at first glance, but in practice turns into a complex pipeline with many points of failure. In this article, we’ll break down how state, idempotency, and encoding issues affect the reliability of mass posting, and how to build a workflow without surprises.

Pipeline architecture: splitting into stages

The key idea is to split the process into independent stages: source → content package → media resolution → transport → verification → report. This allows you to localize errors and formalize the responsibility of each stage.

Package, transport, and QC

The package handles materials, transport handles delivery, and QC handles proof of execution. This separation helps avoid chaos when an agent «does everything itself» and it’s impossible to understand where exactly the error occurred.

The Telegram problem: timeouts and duplicates

First incident: the CLI returned gateway timeout after 10000ms, even though the post was already published. Resending led to a duplicate. Conclusion: an unsuccessful transport response is not a reason to repeat an operation with side effects. First, you need to check the fact of publication.

Message format: Markdown vs HTML

The Markdown link visually blended with the text. The solution was to fix the message format as a set of verifiable conditions: short announcement, HTML anchor, paragraph separation.

Browser as fallback: VK, OK, and others

Browser scenarios (noVNC) showed instability: VK anti-bot checks, image upload issues, loss of the preview card in OK. The browser was left only as an emergency path, with the main transport being APIs of scheduled posting services.

API responses: not a guarantee of success

HTTP 201 and scheduled do not prove that the publication will be correct. For each platform, you need a verifiable final state: post ID, status. Otherwise, the run cannot be considered successful.

Images: resolver and validation rules

Problems: WebP is not supported everywhere, Google Drive breaks preview, HEAD requests are misleading. The solution is a separate image resolver with rules: public URL, suitable format, size within limits, MIME check based on actual download.

Cyrillic and U+FFFD: broken characters

Unicode replacement characters (U+FFFD) ended up in the Google Doc, indicating data loss. This cannot be fixed automatically. Therefore, a byte-level check (EF BF BD) and a hard gate were introduced: if encoding corruption is detected, transport does not run.

Cross-posting: state, idempotency, and Cyrillic issues

Rewrites for Zen and Spark: content source

JSON from the API turned out to be a poor source: CTAs and banners got in. The solution was to use the full public HTML followed by cleaning out irrelevant blocks. Structure, volume, and absence of CTAs are checked.

Limiting scope of responsibility: one article per run

Processing multiple articles at once leads to error multiplication. The skill enforces a limit: per automatic run — only one fresh unpublished article.

Final report: rendering from state

The report should be built from facts, not from the model’s memory. Store the run state: article URL, package statuses, media, each channel, blockers. This avoids false claims.

Stop factors: turning errors into rules

Each error became a stop factor: fixed caption format, publication fact check, card check before URL deletion, MIME rules, byte-level check, HTML cleaning, channel state check. This made the process reliable.

Working procedure

  1. Select one new article.
  2. Get HTML and clean out irrelevant content.
  3. Assemble the package: announcement, two rewrites.
  4. Check structure, volume, links.
  5. Run encoding QC.
  6. Resolve and check media.
  7. Generate Google Doc.
  8. Publish to Telegram directly.
  9. Schedule other channels via LiveDune.
  10. Check the state of each platform.
  11. Fail if state is not proven.

Frequently asked questions

How to avoid duplicates on timeouts?

Check the fact of publication before resending. If the post is already published, do not repeat the operation.

Why is WebP not suitable for all platforms?

Some social networks do not support WebP or have size limits. Use conversion to PNG/JPEG with size verification.

How to verify that a publication is actually scheduled?

Use the API to get the post ID and status. Only the presence of a confirmed state counts as success.

Conclusion

Cross-posting is not just an action, but a system with many points of failure. Implementing stop factors, state checks, and limits turns chaos into a manageable process. Start small: split the pipeline, add QC, and ensure that every error becomes a rule.

Maksim Vaisgerberg
Maksim Vaisgerberg
Write

Back to blog