{"id":44665621,"url":"https://github.com/eeegoloauq/music-bot","last_synced_at":"2026-04-26T02:00:30.765Z","repository":{"id":339291233,"uuid":"1159663346","full_name":"eeegoloauq/music-bot","owner":"eeegoloauq","description":"Telegram bot for Navidrome — download albums from Tidal via Monochrome, organize music, share now playing . ","archived":false,"fork":false,"pushed_at":"2026-04-19T14:42:53.000Z","size":1520,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-19T16:31:17.576Z","etag":null,"topics":["flac","music-downloader","navidrome","python","telegram-bot","tidal"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eeegoloauq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-17T02:11:32.000Z","updated_at":"2026-04-19T14:42:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eeegoloauq/music-bot","commit_stats":null,"previous_names":["eeegoloauq/music-bot"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/eeegoloauq/music-bot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeegoloauq%2Fmusic-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeegoloauq%2Fmusic-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeegoloauq%2Fmusic-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeegoloauq%2Fmusic-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eeegoloauq","download_url":"https://codeload.github.com/eeegoloauq/music-bot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeegoloauq%2Fmusic-bot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32283294,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"online","status_checked_at":"2026-04-26T02:00:05.962Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flac","music-downloader","navidrome","python","telegram-bot","tidal"],"created_at":"2026-02-15T00:22:08.845Z","updated_at":"2026-04-26T02:00:30.755Z","avatar_url":"https://github.com/eeegoloauq.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Music Bot\n\n[![GitHub Release](https://img.shields.io/github/v/release/eeegoloauq/music-bot)](https://github.com/eeegoloauq/music-bot/releases)\n[![GHCR](https://img.shields.io/badge/ghcr.io-music--bot-blue)](https://github.com/eeegoloauq/music-bot/pkgs/container/music-bot)\n\nTelegram bot that builds and maintains a [Navidrome](https://www.navidrome.org/) music library — paste a music link from any major platform, the bot resolves it via [Deezer](https://www.deezer.com/)'s open API, downloads the audio from [Soulseek](https://www.slsknet.org/) peers via [slskd](https://github.com/slskd/slskd), tags the files with canonical metadata, and drops them into your library.\n\n\u003ch2 align=\"center\"\u003eSearch to download\u003c/h2\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\".github/screenshots/search.jpg\" width=\"440\" alt=\"Inline search\"\u003e\n\u003c/p\u003e\n\n\u003ch2 align=\"center\"\u003eDownload into your library\u003c/h2\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\".github/screenshots/download.jpg\" width=\"440\" alt=\"Album download\"\u003e\n\u003c/p\u003e\n\n\u003ch2 align=\"center\"\u003eShare what you're listening to\u003c/h2\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\".github/screenshots/share.jpg\" width=\"440\" alt=\"Share now playing\"\u003e\n\u003c/p\u003e\n\n## Features\n\n- **Album \u0026 track downloads** — paste a Tidal, Spotify, Apple Music, Deezer, YouTube Music, SoundCloud, Amazon Music, or Shazam link, get FLAC files with full metadata into your library\n- **mp3 fallback** — when no peer offers FLAC, the bot offers mp3 ≥ 320 kbps via inline keyboard (opt-in, no silent quality downgrade)\n- **Genres from two sources** — Deezer's structured genres + Last.fm community tags merged into the GENRE field for fine-grained Navidrome facets (\"witch house\", \"future garage\", \"drumless\")\n- **Library re-tagger** — `/retag` walks the whole library and refreshes tags from current Deezer + Last.fm metadata in place; surgical writes preserve embedded pictures and don't rewrite audio data\n- **Inline mode** — type `@yourbotname` in any chat:\n  - `song name` — search Deezer for albums and tracks\n  - `np` — sends the currently playing track as audio\n  - `s` — share link for current track with cover art\n  - `l` — lyrics for current track\n  - `lib name` — search your Navidrome library\n  - `del name` — remove an album from your library\n- **Auto-share** — share link with cover art appended to download results\n- **Force re-download** — add `re` after the link\n- **Private** — only users listed in `ALLOWED_USERS` can interact\n\n## Setup\n\n### Docker compose\n\nThe bot runs alongside slskd (Soulseek daemon) which it talks to over its REST API. Sample compose:\n\n```yaml\nservices:\n  slskd:\n    image: slskd/slskd:latest\n    container_name: slskd\n    restart: unless-stopped\n    environment:\n      SLSKD_SLSK_USERNAME: \"${SOULSEEK_USERNAME}\"\n      SLSKD_SLSK_PASSWORD: \"${SOULSEEK_PASSWORD}\"\n      SLSKD_NO_AUTH: \"true\"\n    volumes:\n      - ./slskd-config:/app\n      - /media/music/.slskd-downloads:/downloads\n      - /media/music:/shared:ro\n    ports:\n      - \"127.0.0.1:5030:5030\"\n      - \"50300:50300\"\n\n  music-bot:\n    image: ghcr.io/eeegoloauq/music-bot:latest\n    container_name: music-bot\n    restart: unless-stopped\n    env_file: .env\n    environment:\n      SLSKD_HOST: \"http://slskd:5030\"\n      SLSKD_DOWNLOAD_DIR: \"/music/.slskd-downloads\"\n    volumes:\n      - /media/music:/music\n    extra_hosts:\n      - \"host.docker.internal:host-gateway\"\n    depends_on:\n      - slskd\n```\n\nslskd's web UI sits on `127.0.0.1:5030` (no auth — internal docker network only). The peer port `50300` needs to be reachable for incoming connections.\n\n### .env\n\n```env\nTG_TOKEN=your_telegram_bot_token\nNAVIDROME_URL=http://host.docker.internal:4533\nNAVIDROME_USER=admin\nNAVIDROME_PASS=your_password\nALLOWED_USERS=123456789\n\nSOULSEEK_USERNAME=your_slsk_username\nSOULSEEK_PASSWORD=your_slsk_password\n```\n\nIf Navidrome is in the same compose stack, use `NAVIDROME_URL=http://navidrome:4533`. The `.env` is loaded by Python directly — special characters like `$` work without escaping.\n\n### Without Docker\n\n```bash\npip install -r requirements.txt\ncp .env.example .env  # fill in values\n# also need slskd running and reachable; see https://github.com/slskd/slskd\npython src/bot.py\n```\n\n## Configuration\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `TG_TOKEN` | yes | | Telegram bot token (from @BotFather) |\n| `NAVIDROME_URL` | yes | `http://localhost:4533` | Navidrome internal URL |\n| `NAVIDROME_USER` | yes | | Navidrome username |\n| `NAVIDROME_PASS` | yes | | Navidrome password |\n| `ALLOWED_USERS` | yes | | Comma-separated Telegram user IDs |\n| `SOULSEEK_USERNAME` | yes | | Soulseek account username |\n| `SOULSEEK_PASSWORD` | yes | | Soulseek account password |\n| `MUSIC_DIR` | | `/music` | Music library path inside the bot container |\n| `STREAM_BITRATE` | | `320` | MP3 bitrate Navidrome transcodes to for the inline `np` audio (kbps) |\n| `NAVIDROME_PUBLIC_URL` | | | Public Navidrome URL for share links. Sharing disabled if not set. |\n| `LASTFM_API_KEY` | | | Last.fm API key — when set, community tags get merged into album genres. Free at https://www.last.fm/api/account/create |\n| `MAX_BIT_DEPTH` | | `24` | Soulseek peer files exceeding this bit depth are filtered out. `16` for redbook-only deployments. |\n| `MAX_SAMPLE_RATE_HZ` | | `96000` | Same idea for sample rate. `44100` pairs with `MAX_BIT_DEPTH=16` for CD-quality only. |\n| `MAX_FILE_BYTES` | | `2147483648` | Hard upper bound on a single peer file (default 2 GiB). `0` disables the cap. |\n| `SLSKD_HOST` | | `http://slskd:5030` | slskd REST API URL |\n| `SLSKD_DOWNLOAD_DIR` | | `/music/.slskd-downloads` | Where slskd writes completed downloads (mounted into both containers) |\n| `SLSKD_API_KEY` | | `anonymous` | Pass-through value when slskd has `SLSKD_NO_AUTH=true`; any non-empty string works |\n\n### Proxy\n\nEvery aiohttp session uses `trust_env=True`, so `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` from the environment are respected. If a specific upstream throttles your proxy IP (Odesli, Deezer CDN, lrclib are common offenders), add the host to `NO_PROXY` so that one endpoint goes direct while everything else keeps using the proxy.\n\n```env\nHTTP_PROXY=http://your-proxy:1080\nHTTPS_PROXY=http://your-proxy:1080\nNO_PROXY=localhost,127.0.0.1,host.docker.internal,slskd,api.deezer.com,api.song.link,lrclib.net\n```\n\n### Sharing\n\nFor `s` (share) and auto-share to work, set `NAVIDROME_PUBLIC_URL` and enable sharing in Navidrome (`ND_ENABLESHARING=true`). The bot reuses the share if you've already created one for the album.\n\n## Usage\n\n### Downloads\n\nSend a music link in chat. The bot resolves it through Deezer, finds matching peers on Soulseek, downloads, tags, and triggers a Navidrome rescan.\n\n- Single track or full album link — auto-detected\n- Multiple links in one message — all queued\n- `re` after a link — force re-download (existing files preserved as `.bak` in case the new download fails)\n- If no peer has FLAC, the bot offers an mp3 ≥ 320 kbps fallback as an inline keyboard prompt\n\n### Inline mode\n\n| Query | Action |\n|---|---|\n| `@bot song name` | Search Deezer for albums and tracks |\n| `@bot np` | Now playing as audio (transcoded to mp3 at `STREAM_BITRATE`) |\n| `@bot s` | Share link for current track |\n| `@bot l` | Lyrics for current track |\n| `@bot lib name` | Search your Navidrome library |\n| `@bot del name` | Delete an album from your library |\n\n### Commands\n\n- `/help` — full feature list\n- `/scan` — trigger a Navidrome library rescan\n- `/stats` — library statistics (artists, albums, tracks, total size)\n- `/retag` — refresh tags on every album in the library from current Deezer + Last.fm metadata (dry-run pass first, then `/retag confirm` to apply, or `/retag stop` to drop the pending session)\n\n## Tags\n\nMetadata is written to every downloaded file:\n\n- **FLAC** — Vorbis Comments\n- **M4A** — iTunes-style atoms with `----:com.apple.iTunes:` freeform fields for non-standard tags\n- **MP3** — ID3v2.4 frames\n\nFields covered: artist, albumartist, album, title, track / disc number, total tracks / discs, date / year / originaldate / releasedate (the four-field quartet keeps Navidrome from splitting FLAC and M4A copies of the same album into separate entries), copyright, ISRC, UPC, label, releasetype, BPM, multi-value GENRE (Deezer + Last.fm), ReplayGain track + album gain (from Deezer's gain field), embedded cover art, and lyrics from [lrclib.net](https://lrclib.net).\n\nThe download path uses force-mode tagging (peer-supplied tags get wiped and replaced with canonical Deezer-derived values) but preserves a small allow-list — `composer`, `lyricist`, `performer`, and any peer comment is appended to the bot's identifier in the comment field. Re-tagging via `/retag` is fully surgical: it only updates fields that differ from canonical, so embedded pictures and any unmanaged tag stay intact.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feeegoloauq%2Fmusic-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feeegoloauq%2Fmusic-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feeegoloauq%2Fmusic-bot/lists"}