Skip to content

End-to-end Telegram-to-WordPress flow

The repository ships a complete Docker Compose example under docker/.

Use the MkDocs page Deploy → Telegram to WordPress with Docker or open:

docker/TELEGRAM_WORDPRESS_TUTORIAL.md

That tutorial is the canonical hands-on deployment guide. It starts with Telegram long polling, brings up MariaDB and WordPress, creates a WordPress application password, verifies the REST API, sends a real #blog message, and then switches the same deployment to an HTTPS webhook.

Why the Docker bundle is the canonical example

The repository has two container layouts:

Layout Scope
docker/ Call Baxter + Telegram projection + WordPress plugin + MariaDB + WordPress + optional Caddy
infra/ Call Baxter + Telegram projection + Caddy only

The minimal infra/ image does not install cb-wordpress-plugin and does not run WordPress. It is appropriate when WordPress is external or the bridge is not needed, but it cannot demonstrate the bundled end-to-end flow by itself.

Runtime path

Telegram webhook or getUpdates poller
  -> call-baxter Telegram plugin
  -> optional tg-agent-cli projection in /srv/data/tg.db
  -> telegram.message.new / telegram.message.edited
  -> call-baxter rule match
  -> wordpress.mirror_telegram_message
  -> WordPress REST API
  -> publication mapping in /srv/data/wp-publications.db

Minimal plugin configuration

plugins:
  - call_baxter.plugins.system
  - module: call_baxter.plugins.telegram
    config:
      bot_token: ${TGCLI_BOT_TOKEN}
      projection_database_url: /srv/data/tg.db
      projection_media_base_dir: /srv/data/tg-media
  - module: cb_wordpress_plugin.plugin
    config:
      base_url: ${WP_BASE_URL}
      username: ${WP_USERNAME}
      app_password: ${WP_APP_PASSWORD}
      publish_status: ${WP_PUBLISH_STATUS:-draft}
      required_hashtag: ${WP_REQUIRED_HASHTAG:-}
      categories: ${WP_CATEGORIES:-}
      tags: ${WP_TAGS:-}
      state_db_path: /srv/data/wp-publications.db
      media_group_wait_seconds: 45

rules_dir: /srv/rules.d

Set WP_REQUIRED_HASHTAG to a hashtag such as #blog to require it. Leave it unset or set it to an empty value to accept messages without a required hashtag. Set WP_CATEGORIES or WP_TAGS to comma-separated WordPress term IDs such as 4,9 when you want fallback categories or tags independent of message hashtags.

New-message rule

One rule handles both ordinary messages and Telegram media-group fragments:

id: mirror-telegram-message
enabled: true
match:
  source: telegram
  kind: telegram.message.new
actions:
  - kind: wordpress.mirror_telegram_message
    args:
      update: "{{ event.attrs.raw_update }}"

The action reads required_hashtag, state_db_path, and media_group_wait_seconds from plugin configuration.

Do not duplicate the new-message rule for media groups

When media_group_wait_seconds is greater than zero, wordpress.mirror_telegram_message automatically stages messages carrying a Telegram media_group_id. A second broad telegram.message.new rule would execute the action twice for the same update.

Edit rule

id: mirror-telegram-edit
enabled: true
match:
  source: telegram
  kind: telegram.message.edited
actions:
  - kind: wordpress.mirror_telegram_message
    args:
      update: "{{ event.attrs.raw_update }}"

The publication mapping lets an edited Telegram message update its existing WordPress post.

Media-group flush rule

id: flush-media-groups
enabled: true
match:
  source: system
  kind: system.heartbeat
actions:
  - kind: wordpress.flush_due_media_groups
    args:
      state_db_path: /srv/data/wp-publications.db

A heartbeat schedule emits the system event that triggers this rule.

First test message

#blog First Call Baxter post

This draft travelled from Telegram through Call Baxter into WordPress.

Expected behavior:

  1. the required #blog hashtag passes publication policy;
  2. the title parser removes leading hashtags and uses First Call Baxter post;
  3. the remaining paragraph becomes the post body;
  4. the default example creates a draft;
  5. editing the original Telegram message updates that draft instead of creating another post.

Verification layers

A complete deployment should be checked at four boundaries:

Boundary Check
Telegram transport polling schedule or getWebhookInfo
Call Baxter health, events, action results, loaded rules
Projection/mapping tg.db and wp-publications.db
WordPress authenticated REST request and resulting post

The Docker tutorial provides exact commands for each check, plus webhook registration, backups, upgrades, and a troubleshooting decision tree.