Skip to content

feat(api): add webhook and telegram actions - #143

Open
arminfauland wants to merge 1 commit into
Disane87:mainfrom
arminfauland:feat/webhook-and-telegram-actions
Open

feat(api): add webhook and telegram actions#143
arminfauland wants to merge 1 commit into
Disane87:mainfrom
arminfauland:feat/webhook-and-telegram-actions

Conversation

@arminfauland

Copy link
Copy Markdown

What this adds

Scrape Dojo currently has no way to reach the outside world during a run. The notify action sends to an open browser tab, which works while you are watching the UI — but a scheduled scrape at 07:00 has nobody watching. There is also no generic HTTP action at all, so there is no workaround either.

This adds two actions and the shared helper behind them:

webhook Send an HTTP request to any URL. Methods, headers, JSON or raw bodies, timeout, retries with exponential backoff.
telegram Send a Telegram message via a bot. A thin layer over the same helper.
_helpers/http-request.helper.ts Shared request logic, so both behave identically.

Decisions worth reviewing

Only transient failures are retried — network errors, timeouts, and 408/429/500/502/503/504. A 400 or 404 is not retried, because repeating a malformed request does not make it valid.

Credentials stay out of the log. Header values are never logged, query strings are stripped, and the Telegram bot token in the URL path is masked as bot•••. Two tests assert this explicitly.

Failures are non-fatal by default. A missed notification should not discard an otherwise successful scrape. failOnError: true opts into the stricter behaviour. I am happy to flip the default if you would rather have it the other way round.

Telegram answers 200 with ok: false for rejected messages — malformed MarkdownV2 is the usual cause. That is treated as a failure rather than silently swallowed.

Messages over 4096 characters are truncated, since Telegram rejects them outright. A warning goes to the log when it happens.

Testing

  • 30 new tests across the three files
  • Full API suite: 1446 tests / 87 files, all passing
  • nx lint api clean

Documentation

apps/docs in EN and DE, plus both overview tables. Includes a short "how to get a bot token" section for telegram, since that is the first hurdle for self-hosters.

The README does not list actions, so nothing to change there. config/scrapes.schema.json types action as a free-form string rather than an enum, so no schema change is needed either — and pnpm create:schema currently fails on 472 pre-existing type errors in spec files on main, which I have deliberately left alone.

Why this shape

I built the generic webhook action first and made telegram a thin layer on top, rather than writing a Telegram-specific action. That way the useful part stands on its own even if you would rather not carry a vendor-specific action — feel free to drop telegram.action.ts and keep the rest.

Follow-up I would like to offer

The case that actually motivated this is waitForOtp: when Amazon asks for a verification code, the prompt only appears in the UI and the action times out after 120 seconds. For an unattended run that means it fails silently. A follow-up PR could forward notifications and OTP requests to an outbound channel via environment variables, so the OTP prompt reaches the user wherever they are — without any config change per scrape. Happy to open that separately if the idea appeals.

Scrape Dojo could not talk to the outside world during a run. The `notify`
action reaches an open browser tab only, which is fine while you are watching
the UI but useless for scheduled scrapes — nobody sees a modal at 07:00.

Adds two actions and a shared helper:

- `webhook` — send an HTTP request to any URL. Methods, headers, JSON or raw
  bodies, timeout, retries with exponential backoff.
- `telegram` — send a Telegram message via a bot. A thin layer over the same
  helper, so retries and timeouts behave identically.
- `_helpers/http-request.helper.ts` — the shared request logic.

Details worth knowing:

- Only transient failures are retried (network errors, timeouts, 408/429/5xx).
  A 400 or 404 is not retried — repeating a malformed request does not make it
  valid.
- Credentials are kept out of the log. Header values are never logged, query
  strings are stripped, and the Telegram bot token in the URL path is masked
  as `bot•••`. Two tests assert this.
- Failures are non-fatal by default: a missed notification should not throw
  away an otherwise successful scrape. `failOnError: true` opts into the
  stricter behaviour.
- Telegram answers HTTP 200 with `ok: false` for rejected messages, e.g. on
  malformed MarkdownV2. That is treated as a failure rather than silently
  swallowed.
- Messages longer than 4096 characters are truncated, since Telegram rejects
  them outright.

Includes 30 tests and documentation in EN and DE.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LixHBPkhb8h5oDdMqSG4se
@arminfauland arminfauland changed the title feat(actions): add webhook and telegram actions feat(api): add webhook and telegram actions Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant