read_wine_bot

command module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 23 Imported by: 0

README

Go 1.27 PostgreSQL 18

🍷 read_wine_bot

@read_wine_bot is a Telegram bot that runs giveaways on channel posts. It was built for the @read_wine channel and works in any channel that adds it as an admin.

[!WARNING] The hosted @read_wine_bot has no guarantees. It can stop, lose data or change at any time. For your own channel, host it yourself with your own bot token.

What Giveaways on Telegram channel posts, with an admin review before the bot publishes the results
Who Channel owners, their admins and giveaway partners
Languages 🇺🇦 Ukrainian (default) and 🇬🇧 English, picked per user with /language
Stack Go 1.27, PostgreSQL 18, one static binary for Windows, macOS and Linux

✨ What it does

  • 🎟️ Join button. Adds a join button under a channel post and collects participants.
  • 🎲 Random draw. Draws winners at random when the giveaway ends.
  • 🔍 Review before publishing. Channel admins see which channels each winner is subscribed to, and can replace a winner. Then they publish the results under the post, or close the giveaway without results.

🔄 How a giveaway works

flowchart LR
    A["📨 Admin forwards a post<br/>to the bot"] --> B["⚙️ Setup<br/>end time, winners, button text"]
    B --> C["🎟️ Join button<br/>appears under the post"]
    C --> D["👆 Subscribers tap<br/>to join"]
    D --> E["⏰ End time:<br/>random draw"]
    E --> F["🔍 Admins review<br/>and replace winners"]
    F --> G["📣 Publish results<br/>under the post"]
    F --> H["🤫 Or close<br/>without publishing"]

👥 Who uses the bot

Who What they do What they grant
👑 Channel owner Adds the bot to the channel as an admin. The giveaway permissions below.
🛠️ Channel admin Creates, edits and reviews giveaways in a private chat with the bot. Nothing. Telegram tells the bot who the channel's admins are.
🤝 Giveaway partner Runs a giveaway together with a channel owner. Winners must also subscribe to the partner's channel. The partner permissions below.
🎉 Participant Taps the join button under the giveaway post. Nothing.

🔐 Permissions to grant

[!IMPORTANT] Grant only the permissions listed here and disable every other toggle. The bot never asks for more.

📢 Channel that runs giveaways

Open t.me/read_wine_bot?startchannel&admin=post_messages+edit_messages and select your channel. Telegram then adds the bot as an admin with the two permissions below already enabled. For your own bot, put its username in the link.

You can also go to Administrators → Add Admin → @read_wine_bot in the channel. Telegram enables the same two permissions there by default. Make sure that these permissions are enabled:

Permission Why the bot needs it
✅ Manage messages → Post messages Publishes the giveaway results as a reply to the giveaway post.
✅ Manage messages → Edit messages of others Adds the join button under your post. Removes the button when the giveaway ends.

When an admin starts a giveaway, the bot checks both permissions. If one permission is missing, the bot stops the setup.

As an admin, the bot can also check winner subscriptions. Telegram does not give them to bots that are not admins.

🚫 Permissions to keep disabled (the bot does not use them)
  • Manage messages → Delete messages of others
  • Change channel info
  • Send welcome messages
  • Manage stories
  • Add members
  • Manage live streams
  • Manage direct messages
  • Add new admins
  • Ban users
🤝 Giveaway partner

A partner's channel needs no permissions at all. Open t.me/read_wine_bot?startchannel&admin=manage_chat and select your channel. Telegram requires at least one permission in this link. The link asks for manage_chat, which every admin has anyway. Then make sure that every other toggle is disabled. Telegram answers "is this user subscribed?" only to a channel's admins. That status is the only thing the bot needs from you.

With no permissions, the bot cannot post, edit, delete or ban anything in your channel. It also cannot run giveaways there, because giveaways need the Edit messages of others permission.

[!NOTE] Your channel appears in the results review of every giveaway the bot runs, in every channel. The review lists each winner's subscriptions to it. Admins of other channels see these subscriptions.

To end a partnership, remove the bot from your admins. The bot then stops checking your channel immediately.

🗄️ What the bot stores

The bot keeps its data in its own PostgreSQL database:

Data What is kept
👤 Users the bot sees Telegram ID, first and last name, username, Telegram app language, Premium flag, and whether the account is a bot. When any of these change, the bot saves a new revision and keeps the old ones.
🎁 Giveaways The channel post, end time, number of winners, button text, participants, winners and replaced winners.
📺 Channels Which channels the bot is an admin of. The bot does not store titles and usernames. It reads them from Telegram when it shows them.

🚀 Run your own

You need:

  • 🐘 a PostgreSQL database (tested with PostgreSQL 18). The bot creates its tables on the first start.
  • 🔑 a bot token from @BotFather.

Then, on Windows, macOS or Linux:

  1. Download the zip for your system from Releases. The name holds the system (windows, macos or linux) and the processor (amd64 for Intel and AMD, arm64 for ARM and Apple Silicon).
  2. Extract the zip to a folder.
  3. In that folder, copy .env.example to .env.
  4. In .env, set the values that .env.example describes.
  5. Open a terminal in that folder and run the bot: .\read_wine_bot.exe on Windows, ./read_wine_bot on macOS and Linux.

[!IMPORTANT] Start the bot from the folder that holds .env. It reads .env from the current directory and its parents, not from next to the binary. You can also use environment variables. They override the values in the file.

Before it starts, the bot checks every setting, the database and the token. If a check fails, the bot stops with an error that names the problem.

[!TIP] If the system blocks the downloaded binary, unblock it once: Unblock-File .\read_wine_bot.exe in PowerShell on Windows, xattr -d com.apple.quarantine read_wine_bot on macOS.

🐹 With go install

If you have Go 1.27 or newer, you can install the bot with one command instead of the download:

go install github.com/alexander-danilenko/read_wine_bot@latest

Go puts the binary in $(go env GOPATH)/bin. This method does not install .env.example. Create .env with the keys from .env.example, then run read_wine_bot from the folder that holds .env.

File What is in it
CLAUDE.md Developer notes, commands and conventions, for humans and coding agents
GLOSSARY.md Domain terms, for example giveaway, winner draw, results review and reroll
docs/adr/ Architecture decisions and the reasons for them
docs/telegram-ux.md Rules for everything the user sees in Telegram

📄 License

MIT

Documentation

Overview

Command bot runs the Telegram bot for the @read_wine channel.

Directories

Path Synopsis
internal
channel
Package channel keeps the log of the channel's audience: every subscribe, unsubscribe and removal, and the time of every channel post.
Package channel keeps the log of the channel's audience: every subscribe, unsubscribe and removal, and the time of every channel post.
command
Package command answers the bot's slash commands in a private chat and lists them in Telegram's command menu.
Package command answers the bot's slash commands in a private chat and lists them in Telegram's command menu.
config
Package config loads the bot's settings from environment variables and .env files.
Package config loads the bot's settings from environment variables and .env files.
cron
Package cron runs the bot's regular tasks.
Package cron runs the bot's regular tasks.
db
Package db opens the bot's PostgreSQL database and brings its tables up to date.
Package db opens the bot's PostgreSQL database and brings its tables up to date.
giveaway
Package giveaway runs giveaways on channel posts.
Package giveaway runs giveaways on channel posts.
i18n
Package i18n holds the bot's user-facing texts, one JSON file per language in locales/.
Package i18n holds the bot's user-facing texts, one JSON file per language in locales/.
keyboard
Package keyboard keeps at most one message with inline buttons in each user's private chat: a new one replaces the previous, so the chat never fills with buttons that no longer work.
Package keyboard keeps at most one message with inline buttons in each user's private chat: a new one replaces the previous, so the chat never fills with buttons that no longer work.
language
Package language lets a user pick the bot's language from the menu and saves the choice.
Package language lets a user pick the bot's language from the menu and saves the choice.
user
Package user stores what the bot remembers about each Telegram user.
Package user stores what the bot remembers about each Telegram user.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL