[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-tgmusic-a-feature-rich-discord-music-bot":3},{"id":4,"title":5,"slug":6,"excerpt":7,"contentType":8,"content":9,"metadata":10,"status":20,"createdAt":21,"updatedAt":22,"startDate":23,"endDate":19,"isOngoing":11,"featuredImage":24,"projectLinks":25,"contributors":27,"experienceCategory":19,"location":19,"locationType":19,"tags":28,"linkedSkills":44,"roles":64,"isPublished":13,"contentLinks":65,"body":-1,"markdown":-1,"html":-1},"dcaeaed0-3e38-4b70-ad3a-f1ea34dc7cc6","TGMusic: A Feature-Rich Discord Music Bot","tgmusic-a-feature-rich-discord-music-bot","An early Node.js project creating a Discord bot for high-quality music playback, featuring YouTube integration, persistent per-server settings via MongoDB, and lyrics fetching.","PROJECT","## Overview\n\nTGMusic is a feature-rich Discord bot I developed to enhance community engagement through a shared, high-quality audio experience. As one of my foundational projects in backend development, it provided a practical application for learning Node.js, asynchronous programming, and API integration. The bot allows users to seamlessly play music from YouTube, manage a server-wide queue, and customize their listening experience with a variety of commands.\n\nDesigned for gaming communities and social servers, TGMusic transforms a standard voice channel into an interactive music hub. It features persistent, per-server settings stored in a MongoDB database, allowing administrators to define custom command prefixes and manage bot permissions. This project was instrumental in developing my understanding of state management in a multi-tenant environment and building responsive, event-driven applications.\n\n## Key Features\n\n- **High-Quality Music Playback:** Leverages `ytdl-core` to stream audio directly from YouTube, ensuring low latency and high-fidelity playback without requiring file downloads. The bot includes a robust queueing system for continuous, shared listening sessions.\n- **Interactive Playback & Queue Management:** Users have full control over the music with commands to play, pause, resume, skip, and stop. The queue can be viewed at any time, and users can remove specific songs, providing a flexible and user-friendly experience.\n- **Lyrics Integration:** Integrates with the KSoft.si API to fetch and display song lyrics directly in the chat, allowing users to follow along with the currently playing track.\n- **Per-Server Customization:** Guild administrators can configure the bot's behavior for their specific server. Settings such as the command prefix and permissions for volume control or song skipping are stored persistently in a MongoDB collection, ensuring a tailored experience for each community.\n- **Built-in Moderation Tools:** Beyond music, the bot includes basic administrative commands like `kick`, `ban`, and `purge`, providing server moderators with essential tools to manage their community.\n\n## Technologies & Implementation\n\nThe bot is built entirely on Node.js, utilizing its event-driven, non-blocking I\u002FO model to efficiently handle numerous simultaneous server connections and Discord API events.\n\n-   **Backend:** The core application is a Node.js server. I chose **Discord.js**, a powerful Node.js module, to interact with the Discord Gateway and REST API, simplifying event handling for messages, voice state changes, and guild management.\n-   **Database:** **MongoDB** was selected for its flexible, schema-less nature, which was perfect for storing guild-specific configurations. Each server's settings are stored as a single document, identified by the `guildID`, making lookups fast and simple.\n-   **Audio Streaming:** Audio is handled by **`ytdl-core`**, which directly fetches and pipes YouTube audio streams to Discord's voice connections. This approach minimizes memory usage and latency compared to downloading files first.\n-   **External APIs:** In addition to the Discord API, the bot integrates with the **KSoft.si API** for lyrics and uses **`youtube-search`** to find videos from user queries.\n\n```mermaid\ngraph TD\n    A[\"Discord User\"] -- \"!play song name\" --> B[\"Discord API\"]\n    B -- \"Message Event\" --> C[\"TGMusic Bot (Node.js)\"]\n    C -- \"Search Query\" --> D[\"YouTube API\"]\n    D -- \"Video URL\" --> C\n    C -- \"Fetch Audio Stream\" --> E[\"ytdl-core\"]\n    E -- \"Audio Stream\" --> C\n    C -- \"Joins VC & Plays Audio\" --> B\n    B -- \"Bot plays music\" --> A\n    \n    subgraph \"Persistent Storage\"\n        F[\"MongoDB Database\"]\n    end\n\n    subgraph \"External Services\"\n        D\n        G[\"KSoft.si API\"]\n    end\n    \n    C -- \"Read\u002FWrite Guild Settings\" --> F\n    C -- \"!lyrics\" --> G\n```\n\n## Challenges & Solutions\n\nThe primary technical challenge was managing state across hundreds of independent Discord servers (guilds). Each guild required its own isolated queue, voice connection, and settings. A global state would cause conflicts, where actions in one server could disrupt playback in another.\n\nTo solve this, I implemented a two-part state management system. For transient, in-memory state like the song queue and the current voice connection, I used a JavaScript `Map` object with the `guild.id` as the key. This provided an efficient, O(1) lookup to retrieve the correct state for any incoming command. For persistent configurations, I used MongoDB, creating a `guilds` collection where each document was uniquely identified by the `guildID`. This architecture ensured complete isolation between servers, creating a stable and scalable multi-tenant application.\n\n## Results & Impact\n\nAs an early personal project, TGMusic was a critical learning experience that solidified my skills in backend development and system architecture. It served as a practical introduction to asynchronous programming with `async`\u002F`await`, managing real-time WebSocket connections via the Discord API, and integrating a database to create a stateful application. The principles of state isolation and event-driven design I learned from this project have been directly applicable to the more complex, scalable systems I've built since.\n\n{TODO: Add screenshot of the bot's 'now playing' embed message in Discord}\n\n## Links\n\n- [View on GitHub](https:\u002F\u002Fgithub.com\u002Ftgmstudios\u002FTGMusic)",{"isOngoing":11,"startDate":12,"aiGenerated":13,"generatedAt":14,"contributors":15,"projectLinks":16},false,"2020-11-01",true,"2025-11-16T23:42:07.590Z",[],{"other":17,"github":18,"devpost":19},[],"https:\u002F\u002Fgithub.com\u002Ftgmstudios\u002FTGMusic",null,"PUBLISHED","2025-11-16T23:42:12.563Z","2026-01-23T23:41:39.600Z","2018-11-01T00:00:00.000Z","https:\u002F\u002Fapi.foligo.tech\u002Fapi\u002Fmedia\u002F8c3714b3-4d50-4239-b2fc-75a403eec4bf\u002Ffile",{"other":26,"github":18,"devpost":19},[],[],[29,33,37,40],{"id":30,"name":31,"category":32},"d4024410-8348-4413-b427-02ec6ca07f07","Discord Bot","Feature",{"id":34,"name":35,"category":36},"ff0c9f0c-ab48-46c7-84ae-8389fc2e1b13","Music","Domain",{"id":38,"name":39,"category":32},"5f15ab2c-465d-4278-a092-df1e03b58997","Community Tools",{"id":41,"name":42,"category":43},"1b3d51c8-1f7b-4394-bb33-483836485001","Backend Development","Technical",[45,49,53,57,61],{"id":46,"name":47,"category":48},"2b1fd9f7-641f-4606-8ca4-aeb8ba29eeda","JavaScript","Programming Language",{"id":50,"name":51,"category":52},"153dbaa9-b2f5-4f68-9046-0957dde01a10","Node.js","Backend Framework",{"id":54,"name":55,"category":56},"5d3bacda-f2ca-40ab-a6df-9540d4ff3c5e","REST API","API",{"id":58,"name":59,"category":60},"45addd44-0845-486a-869d-0b498e8d74c4","MongoDB","Database",{"id":62,"name":63,"category":56},"b154ea40-3f7a-4f84-a2fe-f749b71dc518","Discord API",[],[66,73],{"id":67,"sourceId":68,"targetId":4,"sourceType":8,"targetType":69,"linkType":70,"createdAt":71,"updatedAt":71,"linkedContent":72},"8fb7b638-20f7-45b3-9f44-01bfe30f6a71","d0ef36a9-c9a2-4fec-8834-ad777058a622","content","related","2025-11-27T08:04:18.498Z",{"id":4,"title":5,"slug":6,"excerpt":7,"contentType":8},{"id":74,"sourceId":68,"targetId":4,"sourceType":8,"targetType":69,"linkType":75,"createdAt":76,"updatedAt":76,"linkedContent":77},"71eb810c-6330-4861-a5e4-6ec4d0c68a99","sequential","2025-11-17T03:58:50.157Z",{"id":4,"title":5,"slug":6,"excerpt":7,"contentType":8}]