Awesome
G Reader
<img align="right" height=200 src="/cover.png" alt="G Reader" />G Reader is a simple RSS feed reader bot for Telegram. Check it out here: @GReaderBot.
G Reader was originally made a couple of years ago1. A mini web app to easily manage feed subscriptions was added as part of October 2023 contest. This readme contains helpful information to get you started with your own Telegram web app. A guide to bring up G Reader with Docker is below.
Overview
G Reader consists of five components:
-
Telegram bot
Written in TypeScript. Communicates with Telegram using telegraf.js. Responds to user commands, reports new subscriptions to the crawler, periodically checks the database for feed updates and publishes them.
-
Feed crawler
Monitors the database for outdated feeds and crawls them. Can also proactively try to fetch a feed in response to web request.
-
Postgres database
Stores users, feeds, subscriptions, and feed update schedule.
-
Telegram mini web app
Implemented in vanilla JavaScript. Shows info about current subscriptions, allows unsubscribing, filtering.
-
Web app backend
Implemented with node.js and express.js.
Mini app
Opening the web app. Telegram supports different ways of opening web apps: keyboard button, menu button, via inline mode, attachment menu, from a direct link. G Reader uses an inline button (aka inline keyboard button), which is a button attached to a chat message. Note that behavior for apps launched from the menu button will be largely the same.
Inline button is created here. User-specific token is fetched from the database and will be used for authorization. Note that wep app buttons are not available in groups or channels, and trying to send one will fail with BUTTON_TYPE_INVALID
.
The button is then attached to responses to help, list, and unsubscribe commands. All commands are declared in index.ts.
Web app frontend. G Reader web app has a simple three file structure: index.html, app.js, and main.css.
HTML links the web app script that is provided by Telegram. It binds a custom object to window.Telegram
and provides the user, current theme, and UI controls. Additionally we disallow search engine indexing with robots.txt
and meta tag.
The app script loads info from the server and displays it, handles button events, and filters subscriptions. This is all normal web stuff. One thing of note here: we attempt to show user profile picture next to G Reader logo but it isn't available for web apps launched from inline button. This code will work when app is launched from attachment menu so I kept it for illustrational purposes.
CSS uses dynamic theme variables. They match the current app theme to provide a native experience.
Backend is a straightforward express.js app. It uses the token from earlier to identify the current user and provide requested data. This authorization method is sufficient for this app but can be improved if needed in following ways:
- Expire old authorization tokens
- Verify user info provided in
window.Telegram.WebApp
as described in the docs. This would be necessary for apps launched for attachment menu or with direct link, when we are unable to provide custom data as URL parameters.
Note that web app button can't be forwarded from private chat with bot so authorization token is safe.
Quick start
Follow these steps to run a custom instance. Remember to modify urls of your web app. Please do not name your project "G Reader" to avoid confusion.
-
Install
docker
anddocker-compose
. -
Clone this repository.
-
Launch Postgres and restore backup:
docker compose up -d postgres ./scripts/load-backup.sh backup.sql
or create tables:
docker compose up -d postgres ./scripts/create-tables.sh
-
Set environment variables in
.env.docker
:cp .env.example .env.docker vim .env.docker
Get
BOT_TOKEN
from @BotFather.OWNER_ID
refers to your Telegram user ID. The bot will respond to admin commands from that account. -
Launch
docker compose up -d docker compose ps docker compose logs -f
License
MIT. Feel free to launch your own instance but please DO NOT name it "G Reader" to avoid confusion.
Contributions
PRs are welcome.
Footnotes
-
Release announcement on my blog: https://nikstar.me/post/greader/ ↩