Skip to content
Open

v1 #39

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ jobs:
- run: npm install -g npm@latest
- run: pnpm install --frozen-lockfile
- run: pnpm run build
- run: pnpm publish --access=public --provenance --no-git-checks
- run: |
VERSION="${{ github.ref_name }}"
if echo "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
pnpm publish --access=public --provenance --no-git-checks
else
TAG=$(echo "$VERSION" | sed 's/^v[0-9]*\.[0-9]*\.[0-9]*-//' | sed 's/\..*//')
pnpm publish --access=public --provenance --no-git-checks --tag "$TAG"
fi

changelog:
runs-on: ubuntu-latest
Expand All @@ -41,6 +48,11 @@ jobs:
with:
node-version: lts/*
registry-url: https://registry.npmjs.org/
- run: npx changelogithub
- run: |
if echo "${{ github.ref_name }}" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
npx changelogithub
else
npx changelogithub --prerelease
fi
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
29 changes: 29 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# Agent Guidelines

## Project Overview

`@grom.js/effect-tg` is a library for building Telegram bots on top of [Effect](https://effect.website), targeting the Telegram Bot API. See `README.md` for user-facing docs and usage examples.

- `src/*.ts` — public API. Each file is exported as a namespace from `src/index.ts`.
- `src/internal/` — implementation details backing the public modules (not exported directly).
- `src/internal/botApi.gen.ts` — generated Bot API method/type definitions. Never hand-edit; regenerate with `pnpm gen:bot-api` (see `scripts/gen-bot-api.ts`).
- `test/` — Vitest suites (`*.test.ts`) and type-level tests (`*.test-d.ts`).

### Commands

- `pnpm test` — run tests
- `pnpm typecheck` — project-wide type check
- `pnpm lint` / `pnpm lint:fix` — ESLint
- `pnpm build` — emit `dist/`
- `pnpm gen:bot-api` — regenerate `src/internal/botApi.gen.ts` from the Bot API spec
- `pnpm knip` — check for unused files/exports/dependencies

## Verifying Changes

Run the following checks to verify your changes:

```sh
pnpm run typecheck
pnpm run lint
pnpm run knip
pnpm run test
```

## Telegram Terminology

### Topic vs. Thread
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
72 changes: 55 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# effect-tg

[![Effectful](https://img.shields.io/badge/Yes.-%23fff?style=flat&logo=effect&logoColor=%23000&logoSize=auto&label=Effect%3F&labelColor=%23fff&color=%23000)](https://effect.website/)
[![Bot API](https://img.shields.io/badge/v10.0-%23fff?style=flat&logo=telegram&logoColor=%2325A3E1&logoSize=auto&label=Bot%20API&labelColor=%23fff&color=%2325A3E1)](https://core.telegram.org/bots/api)
[![Bot API](https://img.shields.io/badge/v10.3-%23fff?style=flat&logo=telegram&logoColor=%2325A3E1&logoSize=auto&label=Bot%20API&labelColor=%23fff&color=%2325A3E1)](https://core.telegram.org/bots/api)
[![npm](https://img.shields.io/npm/v/%40grom.js%2Feffect-tg?style=flat&logo=npm&logoColor=%23BB443E&logoSize=auto&label=Latest&labelColor=%23fff&color=%23BB443E)](https://www.npmjs.com/package/@grom.js/effect-tg)
[![codecov](https://img.shields.io/codecov/c/github/grom-dev/effect-tg?style=flat&logo=codecov&logoColor=%23f07&label=Coverage&labelColor=%23fff&color=%23f07)](https://codecov.io/gh/grom-dev/effect-tg)

Expand Down Expand Up @@ -256,22 +256,23 @@ const program = Effect.gen(function* () {

`Content` module provides constructors for creating objects that represent the content of a message. `Send.sendMessage` uses the content type to choose the appropriate Bot API method automatically.

| Constructor | Bot API method | Description |
| ---------------------- | --------------- | ---------------------- |
| `Content.text` | `sendMessage` | Text |
| `Content.photo` | `sendPhoto` | Photo |
| `Content.video` | `sendVideo` | Video |
| `Content.animation` | `sendAnimation` | GIF or video w/o sound |
| `Content.audio` | `sendAudio` | Audio file |
| `Content.voice` | `sendVoice` | Voice note |
| `Content.videoNote` | `sendVideoNote` | Round video note |
| `Content.document` | `sendDocument` | File of any type |
| `Content.sticker` | `sendSticker` | Sticker |
| `Content.location` | `sendLocation` | Static location |
| `Content.liveLocation` | `sendLocation` | Live location |
| `Content.venue` | `sendVenue` | Venue with address |
| `Content.contact` | `sendContact` | Phone contact |
| `Content.dice` | `sendDice` | Random dice |
| Constructor | Bot API method | Description |
| ---------------------- | ------------------- | ----------------------- |
| `Content.text` | `sendMessage` | Text |
| `Content.richText` | `sendRichMessage` | Rich formatted message |
| `Content.photo` | `sendPhoto` | Photo |
| `Content.video` | `sendVideo` | Video |
| `Content.animation` | `sendAnimation` | GIF or video w/o sound |
| `Content.audio` | `sendAudio` | Audio file |
| `Content.voice` | `sendVoice` | Voice note |
| `Content.videoNote` | `sendVideoNote` | Round video note |
| `Content.document` | `sendDocument` | File of any type |
| `Content.sticker` | `sendSticker` | Sticker |
| `Content.location` | `sendLocation` | Static location |
| `Content.liveLocation` | `sendLocation` | Live location |
| `Content.venue` | `sendVenue` | Venue with address |
| `Content.contact` | `sendContact` | Phone contact |
| `Content.dice` | `sendDice` | Random dice |

#### Dialog

Expand Down Expand Up @@ -531,3 +532,40 @@ const publish = Send.message(Content.text(summary)).pipe(
Send.to(Dialog.channel(3011378744)),
)
```

### Rich text formatting

`RichText` module provides utilities for creating [rich formatted messages](https://core.telegram.org/bots/api#rich-messages) — richer than regular formatted text, supporting headings, lists, tables, block quotes, buttons, embedded media, and more. Rich text is sent with `Content.richText`, which uses the `sendRichMessage` Bot API method.

Just like `Text`, `RichText` supports Markdown and HTML, parsed by Telegram itself according to the [rich message formatting options](https://core.telegram.org/bots/api#rich-message-formatting-options). It additionally supports building a tree of blocks directly from Bot API types with `RichText.blocks`.

**Example:** Formatting rich text with `RichText` module.

```ts
import { Content, Dialog, RichText, Send } from '@grom.js/effect-tg'

// Markdown
RichText.markdown('# Release notes\n\n- Faster startup\n- Fewer crashes')

// HTML
RichText.html('<h1>Release notes</h1><ul><li>Faster startup</li><li>Fewer crashes</li></ul>')

// A tree of blocks, built directly from Bot API types
RichText.blocks([
{ type: 'heading', text: 'Release notes', size: 1 },
{
type: 'list',
items: [
{ blocks: [{ type: 'paragraph', text: 'Faster startup' }] },
{ blocks: [{ type: 'paragraph', text: 'Fewer crashes' }] },
],
},
])

const publishNotes = Send.sendMessage({
content: Content.richText(
RichText.markdown('# Release notes\n\n- Faster startup\n- Fewer crashes'),
),
dialog: Dialog.channel(3011378744),
})
```
34 changes: 16 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "@grom.js/effect-tg",
"type": "module",
"version": "0.17.1",
"packageManager": "pnpm@10.25.0",
"version": "1.0.0-beta.4",
"packageManager": "pnpm@11.25.0",
"description": "Effectful library for crafting Telegram bots.",
"author": {
"name": "Vladislav Deryabkin",
Expand Down Expand Up @@ -44,26 +44,24 @@
"release": "bumpp"
},
"peerDependencies": {
"@effect/platform": "^0.96.0",
"@grom.js/tgx": "^1.0.0",
"effect": "^3.0.0"
"effect": "^4.0.0-rc.112"
},
"devDependencies": {
"@antfu/eslint-config": "7.7.3",
"@effect/language-service": "0.85.1",
"@effect/platform": "0.96.1",
"@grom.js/bot-api-spec": "0.10.1",
"@antfu/eslint-config": "9.3.0",
"@effect/language-service": "0.87.2",
"@grom.js/bot-api-spec": "0.12.0",
"@grom.js/tgx": "1.4.3",
"@types/node": "22.19.18",
"@vitest/coverage-v8": "4.1.5",
"bumpp": "11.1.0",
"effect": "3.21.2",
"eslint": "9.39.4",
"@types/node": "26.4.0",
"@vitest/coverage-v8": "4.1.11",
"bumpp": "12.2.2",
"effect": "4.0.0-rc.112",
"eslint": "10.9.1",
"eslint-plugin-format": "2.0.1",
"knip": "6.12.1",
"taze": "19.11.0",
"ts-morph": "27.0.2",
"typescript": "5.9.3",
"vitest": "4.1.5"
"knip": "6.32.3",
"taze": "21.1.0",
"ts-morph": "28.0.0",
"typescript": "6.0.3",
"vitest": "4.1.11"
}
}
Loading
Loading