Skip to content

About

Run your personal Telegram account on autopilot after hours - auto-replies to DMs outside your working hours, mutes the sender, and unmutes everyone when you're back. Controlled by an admin-only bot. Single Go binary, one container, no cgo.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

11 Commits

Folders and files

Repository files navigation

tg-afterhours

A single Go binary that runs your personal Telegram account (MTProto user client) and an admin control bot in one process. When someone DMs you outside your working hours (default 09:30–19:00 local), it auto-replies, mutes the sender, and logs the event. At the start of working hours (and on startup) it unmutes everyone again. You toggle the whole feature on/off from a private bot.

  • User client — gotgproto (over gotd/td), acts as you.
  • Control bot — telego (Bot API), answers only to your admin user ID.
  • Storage — one small SQLite table (pure Go, no cgo).

1. Prerequisites

Pick one of:

  • Docker + Docker Compose (recommended), or
  • Go 1.25+ to build/run locally.

2. Get your credentials

You need four things. Put them in .env (step 4).

a) Telegram API ID & hash (for the user client)

  1. Go to https://my.telegram.org and log in with your phone number.
  2. Open API development tools.
  3. Create an app (any title/short-name). Copy api_id and api_hash.

b) Your phone number

The phone number of the account you want to automate, in international format, e.g. +15551234567.

c) Bot token (for the control bot)

  1. In Telegram, open @BotFather.
  2. Send /newbot, follow the prompts, and copy the bot token (123456:ABC...).
  3. Open a chat with your new bot and press Start so it can message you.

d) Your admin user ID

  1. Message @userinfobot (or @myidbot) in Telegram.
  2. Copy your numeric user ID. This is the only account the control bot obeys.

3. Download

git clone https://github.com/yiromo/tg-afterhours.git
cd tg-afterhours

4. Configure

Copy the example and fill it in:

cp .env.example .env

Edit .env:

API_ID=123456
API_HASH=your_api_hash
PHONE=+15551234567
BOT_TOKEN=123456:ABC-your-bot-token
ADMIN_ID=7258936037          # your numeric user ID from step 2d
TIMEZONE=Europe/Moscow       # IANA name — required for correct local-time
WORK_START=09:30
WORK_END=19:00
REPLY_TEXT=I'm currently outside my working hours and will get back to you during the day.

TIMEZONE matters. Working hours are evaluated in this timezone. Use an IANA name (Europe/Moscow, America/New_York, …), not an offset.


5. First run — log in to Telegram

The user client must authenticate once. This is interactive (Telegram sends a login code to your account), so the first run needs a terminal.

With Docker

docker compose run --rm afterhours

You'll be prompted for:

  • the login code Telegram sends you (in the Telegram app), and
  • your 2FA password if you have one enabled.

After a successful login the session is saved to ./data/session.db. Press Ctrl+C once you see it running, then start it detached:

docker compose up -d

Subsequent restarts reuse the saved session — no code needed.

Without Docker (local Go)

go run ./cmd/app

Set DB_PATH and SESSION_PATH to local paths first if you don't want them under /data, e.g.:

DB_PATH=./data/afterhours.db SESSION_PATH=./data/session.db go run ./cmd/app

(Environment variables can come from your shell; the binary itself doesn't read .env — Docker Compose loads it for you.)


6. Use the control bot

Open the chat with your bot (the one from step 2c) and send:

Command Action
/start or /admin Show the menu
/on Enable auto-reply
/off Disable auto-reply
/analytics or /stats List recent senders who were auto-replied & muted
/schedule Show the working-hours window for each weekday
/set <day> <HH:MM> <HH:MM> Set a day's working hours, e.g. /set mon 09:30 19:00
/set <day> off Mark a day off (auto-reply applies all day)
/settext <text> Set the auto-reply text (send with no argument to view the current one)
/resettext Restore the default auto-reply text (REPLY_TEXT)
/setlimit <n> Max auto-replies per sender per day (default 3; no argument shows the current value)
/ignore <@username | phone | id> Exempt a sender from auto-reply & muting
/unignore <@username | phone | id> Remove the exemption

Days are mon–sun. Every day starts from the .env window (WORK_START/WORK_END); per-day changes made with /set are saved to the database and survive restarts.

Auto-reply text. The message sent to people defaults to REPLY_TEXT from .env. Change it at runtime with /settext <text> (it's saved to the database and survives restarts) and revert to the env default with /resettext.

Ignore list. Senders you /ignore never get an auto-reply or mute. The argument can be @username, a phone (+77001234567), or a numeric user id; usernames/phones are resolved to a stable user id when added (they must be resolvable at that moment). The /start//admin menu has an Ignored list button that shows current entries with a tap-to-remove button each.

Auto-ignore people you message. When you send a DM to someone, they're automatically added to the ignore list and unmuted — you're clearly active in that chat, so they won't get the after-hours auto-reply and you'll keep seeing their messages. Remove them later with /unignore or the menu if you want the rules to apply again.

The bot ignores everyone except ADMIN_ID. Auto-reply is ON by default when the process starts.


7. How it behaves

  • A DM arrives outside WORK_START–WORK_END and the feature is ON → you reply (up to the per-day limit, default 3, per sender), the sender is muted, and a row is logged. Once a sender hits the daily cap they stay muted but get no further replies until the next day.
  • Inside working hours → nothing happens; a background check (every minute, and on startup) unmutes anyone still muted.
  • Only the minimum is stored per sender: user_id, username, message_text, muted_at, muted. No message history or media.

8. Build & test (development)

go build ./...                          # build
go test ./...                           # run tests
CGO_ENABLED=0 go build -o app ./cmd/app # static binary (matches the Docker build)

The binary is static (no cgo); both SQLite uses are pure Go. See CLAUDE.md for architecture details.


Persistence

Everything lives under ./data (mounted to /data in the container):

  • session.db — MTProto login session (keep it; deleting it forces re-login).
  • afterhours.db — the mute registry / analytics table.

About

Run your personal Telegram account on autopilot after hours - auto-replies to DMs outside your working hours, mutes the sender, and unmutes everyone when you're back. Controlled by an admin-only bot. Single Go binary, one container, no cgo.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages