Skip to content

Latest commit

 

History

History
116 lines (97 loc) · 5.88 KB

File metadata and controls

116 lines (97 loc) · 5.88 KB

Telegram Integration

Commands

/start is the only command. It opens the main menu in DM. In groups and supergroups it is registered as a Bot API 10.2 ephemeral command: Branchy's DM prompt is visible only to the invoking user. The reply uses Bot API 10.3 ephemeral_message_parameters plus reply_parameters.ephemeral_message_id. An ordinary non-ephemeral group /start gets no public response. Scope registration retries after transient Telegram failures. The private reply is sent before the best-effort presence write so database latency cannot consume the 15-second ephemeral reply window.

All setup happens through inline keyboards. Unrecognized private-chat text nudges the user to send /start. Groups stay quiet.

Groups

Subscription settings are managed in DM. Group delivery works after:

  1. The bot is added to a group or supergroup.
  2. Branchy receives a my_chat_member update and records the group.
  3. The user selects that group in DM.
  4. Branchy verifies the user is a group creator or administrator with getChatMember.

If Telegram cannot verify admin status, Branchy does not save the group destination.

Notifications

GitHub notifications use Telegram Bot API Rich Messages (sendRichMessage) with Rich HTML. Branchy parses GitHub Flavored Markdown, keeps supported headings, lists, tables, quotes, links, code, task lists, and media, then serializes a strict allowlist. Raw GitHub HTML and non-HTTP(S) URLs do not pass through directly: safe formatting tags such as underline, superscript, and subscript are retained, while scripts, Telegram-specific tags (including tg-* tags; their inner text is kept), unsafe attributes, mentions, and non-HTTP(S) URLs are removed.

Each notification is a title-first card: an h2 for the event (#7 Title, N new commits, or the release name), one quiet line for repository, action, branches, and author, then the body and a single trusted in-message button row. There is no divider. Push offers Open compare and Copy SHA only when the payload has a single commit (the full SHA). Pull requests offer Open pull request plus More (type="callback_data" style="link"). Releases offer Open release and show the tag in the quiet line. Classic HTML fallback keeps ordinary links and does not include More. Those buttons are generated by Branchy, not taken from the GitHub body. GFM tables are emitted as bordered, striped, and compact. Short bodies use Rich HTML blockquotes; long flat notes use <blockquote expandable> with inline text and <br> (not nested paragraphs); truncated or structured notes (tables, headings, lists, media) use a collapsible <details> block. Bodies that hit Telegram Rich Message limits stay folded there; cards do not add a separate Read more / Full release notes link. Open pull request / Open release already go to GitHub.

Tapping More on a pull request sends a separate ephemeral Rich Message to the tapping user (ephemeral_message_parameters.receiver_user_id plus callback_query_id). The public card is not replaced. The overlay is a thin header (#N Title, head → base, draft/merged) plus non-zero diff stats and a compact file table (File / + / ) loaded live from GitHub GET /repos/{owner}/{repo}/pulls/{n}/files using the subscription owner's OAuth token, not the tapping user. Description, labels, and reviewers are not repeated. URL buttons are Open and Files. If GitHub has not computed the diff yet, the overlay says so and still offers Files. A failed files fetch still sends the header and snapshot stats, and toasts Could not load the file list. (or GitHub access expired. on 401). Callback data is m: plus the job UUID without hyphens (34 bytes). Lookup is by job id and destination_chat_id; missing, foreign-chat, or retained-and-purged jobs toast This snapshot expired. Anyone who can see the card can open More. Test notifications stay a short card without More.

The first 50 valid HTTP(S) media items remain visible Rich Message blocks, including linked Markdown images and supported raw image, video, and audio tags; later items remain available as links. Rendering also enforces Telegram's body, block, nesting, and 20-column table limits while keeping tags balanced and removing implicit HTML5 table wrappers unsupported by Telegram.

Each outbox job stores a bounded classic HTML fallback. If Telegram rejects the preferred payload with a content, permission, size, or method error, Branchy tries Rich HTML with media replaced by links, then classic HTML, then plain text. Each attempt gets a fresh timeout. Rate limits, server failures, transport errors, and unreachable chats keep their normal retry or auto-pause behavior instead of falling through and risking duplicates. Pending alpha Rich Markdown jobs are sanitized into Rich HTML before delivery. Bot UI (/start, settings, OAuth replies) still uses classic HTML sendMessage / editMessageText.

Message content stays concise and includes:

  • repository
  • event type
  • actor
  • branch
  • title or summary
  • GitHub link
  • optional PR/release body

Subscription Settings

Subscription creation collects event-specific settings before saving:

  • push and pull_request can use all branches, the default branch, or a selected set of branches.
  • pull_request can deliver opened, merged, closed, or any combination of those actions.
  • release can deliver stable releases, pre-releases, or both.

Release-only subscriptions do not ask for branch settings. Existing subscriptions expose branch, pull request, and release controls under Advanced settings; test notifications stay on the individual subscription screen and use the same Rich HTML card chrome as live events. Incomplete Continue, Create, Save, and Done actions, plus pagination edges and the current all/default branch or release radio, stay on screen as Bot API 10.3 disabled buttons. The selected-branch radio stays tappable so the user can open the branch list.