Skip to content

Latest commit

 

History

26 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎵 Playlist Bot

A Telegram bot that builds a music playlist from a few of your favorite tracks. Send it 1–5 songs, and it returns a curated playlist of similar tracks powered by the Last.fm API.

Try it: @bremcm_playlist_bot»

Built in Go as a hands-on backend/DevOps project: clean architecture, concurrency, a persistent database, containerization, CI, and a live deployment on a VPS.


What it does

  • Send tracks in Artist — Title format, one per message (1 to 5 tracks).
  • The bot fetches similar tracks for each seed from Last.fm and ranks them: a track similar to several of your seeds ranks higher.
  • The playlist size scales with how many tracks you send: 1→10, 2→15, 3→20, 4–5→30.
  • Typo correction: minor misspellings are auto-corrected via Last.fm search (e.g. Madona — FroznMadonna — Frozen).
  • Suggestions: for bigger mismatches, the bot offers options as inline buttons ("did you mean…?").
  • Honest feedback: if Last.fm has no similar tracks for a song, you're told right away, not after the fact.
  • Duplicate seeds and unrecognizable input are filtered out.
  • /history shows your past requests, stored in PostgreSQL.

Tech stack

  • Language: Go
  • Bot API: Telegram (long polling)
  • Data source: Last.fm API (track.getsimilar, track.search)
  • Database: PostgreSQL (request history), schema embedded via //go:embed
  • Containerization: Docker (multi-stage build, ~9 MB final image), Docker Compose
  • CI: GitHub Actions (build + tests with the race detector)
  • Deployment: VPS running Ubuntu, containers auto-restart on reboot

Architecture

The project is split into small, single-responsibility packages. The core logic (recommender) is fully decoupled from the outside world and depends only on interfaces it declares itself — so it can be tested without any network access.

cmd/bot            entry point: wires everything together
internal/
  models           shared domain types (Track, Candidate)
  lastfm           Last.fm HTTP client (GetSimilar, Search)
  recommender      ranking logic — pure, tested, no I/O
  telegram         bot handlers, dialog state, inline buttons
  session          per-user in-memory state (accumulated tracks)
  storage          PostgreSQL access (request history)

Key design choices:

  • Interfaces declared by the consumer. For example, recommender defines the SimilarFetcher interface it needs; the Last.fm client happens to satisfy it. Dependencies are wired together only in main.
  • Pure ranking core. The ranking function takes data in and returns data out — no HTTP, no database — which makes it trivial to unit-test.
  • Concurrency-safe state. Shared state is guarded with mutexes; correctness was verified with Go's race detector (go test -race).

Running locally

You'll need Docker and Docker Compose installed.

  1. Create a .env file in the project root:

    LASTFM_API_KEY=your_lastfm_api_key
    TELEGRAM_BOT_TOKEN=your_telegram_bot_token
    DATABASE_URL=postgres://playlist:playlist@db:5432/playlist?sslmode=disable
    
  2. Start everything:

    docker compose up --build

    This launches PostgreSQL and the bot together. The database schema is applied automatically on startup.

  3. Open Telegram, find your bot, and send /start.


Running tests

go test -race ./...

Deployment

The bot runs in Docker on a VPS. Because the app is fully containerized, deployment is the same command as local:

git pull
docker compose up -d --build

restart: unless-stopped in the compose file, combined with Docker starting on boot, means the bot survives crashes and server reboots.


Commands

Command Description
/start Show instructions
/done Build the playlist from your tracks
/history Show your past requests

License

MIT

About

Telegram bot for your music

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages