Tạo Một Discord Bot Phát Nhạc đơn Giản Bằng Node.js, Typescript ...
Bài viết này đã outdated, nếu muốn tạo Discord music bot mới, vui lòng xem bài viết này
Mở đầuChắc hẳn chúng ta đã nghe đến Discord. Đây là một nền tảng giao tiếp được thiết kế hướng tới game thủ, giúp ta có thể gửi tin nhắn, ảnh, file, hoặc trò chuyện qua kênh thoại. Ở trong bài viết này, mình sẽ hướng dẫn các bạn tạo một con bot có thể phát nhạc trong kênh thoại với các chức năng play, pause, resume, skip, stop, clear, nowplaying.
Nội dungTạo bot Discord
Đầu tiên, chúng ta hãy truy cập https://discord.com/developers/applications để tạo một ứng dụng cho Discord. Sau khi tạo ứng dụng xong, vào Bot, click "Add Bot" để tạo bot Click Copy để copy token của bot. Token này giúp bot đăng nhập với Discord.
Tạo server bot Node.js
Mình sử dụng các packages sau:
- discord.js: Đây là package của Discord để bot của bạn có thể login và tương tác với người dùng được.
- ytdl-core: Dùng để get thông tin video và stream video trên Youtube.
- ytpl: Dùng để get thông tin và danh sách video của 1 playlist trên Youtube.
- ytsr: Dùng để tìm kiếm 1 video trên Youtube bằng từ khoá.
- ffmpeg-static: Hoạt động cùng với ytdl-core để stream audio.
- dotenv: Dùng để sử dụng với file .env.
- nodemon: Giúp chúng ta thuận tiện hơn trong quá trình dev.
Cài đặt các packages cần thiết: yarn add discord.js ytdl-core ytpl ytsr ffmpeg-static dotenv hoặc npm i add discord.js ytdl-core ytpl ytsr ffmpeg-static dotenv --save yarn add @types/node @types/ws ts-node nodemon typescript -D hoặc npm i @types/node @types/ws ts-node nodemon typescript --save-dev Tại thời điểm viết bài, phiên bản LTS mới nhất của Node.js là 14.17.0. Nhưng phiên bản này có 1 vài trục trặc với việc pause/resume của ytdl-core nên mình sẽ sử dụng bản 14.15.4. Thêm dòng sau vào file pagekage.json.
"engines": { "node": "14.15.4" }, Tạo file tsconfig.json với nội dung sau: { "compilerOptions": { "module": "commonjs", "esModuleInterop": true, "target": "es6", "noImplicitAny": true, "moduleResolution": "node", "sourceMap": false, "outDir": "dist", "baseUrl": ".", "paths": { "*": [ "node_modules/*" ] }, }, "include": [ "src/**/*" ] }Tạo file nodemon.json với nội dung sau:
{ "watch": ["src"], "ext": "ts,json", "ignore": ["src/**/*.spec.ts"], "exec": "ts-node ./src/index.ts" }Thêm đoạn sau vào package.json.
"main": "dist/index.js", "scripts": { "dev": "nodemon", "build": "tsc", "start": "node dist/index.js", },Tạo file .env ở root folder thêm đoạn sau vào file:
TOKEN = <Token mà bạn đã copy ở trên> Tạo thư mục src và thêm file index.ts: import { config } from "dotenv"; config(); import { Client } from "discord.js"; const client = new Client(); const token = process.env.TOKEN; const prefix = "!"; // Đây là tiền tố trước mỗi lệnh mà ta ra hiệu cho bot từ khung chat. // Lệnh có dạng như sau "!play Nhạc Đen Vâu", "!pause",... client.on("message", (message) => { const args = message.content.substring(prefix.length).split(" "); const content = message.content.substring(prefix.length + args[0].length); if (message.content[0] === "!") { switch (args[0]) { // Tại đây sẽ đặt các case mà bot cần thực hiện như play, pause, resume,.... } } }); client.on("ready", () => { console.log("🏃♀️ Misabot is online! 💨"); }); client.once("reconnecting", () => { console.log("🔗 Reconnecting!"); }); client.once("disconnect", () => { console.log("🛑 Disconnect!"); }); client.login(token);Tạo folder constant trong src chứa file regex.ts. Trong file này có các regex mà ta dùng để check url video hoặc playlist:
export const youtubeVideoRegex = new RegExp( /(?:youtube\.com\/(?:[^\\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\\/\s]{11})/ ); export const youtubePlaylistRegex = new RegExp( /(?!.*\?.*\bv=)https:\/\/www\.youtube\.com\/.*\?.*\blist=.*/ );Tạo folder data trong src có file server.ts như sau:
import { StreamDispatcher } from "discord.js"; import { Resource } from "../services/youtube"; export interface Song { requester: string; resource: Resource; } interface Server { [key: string]: { playing?: { song: Song; startedAt: number; }; queue: Song[]; dispatcher?: StreamDispatcher; }; } export const servers: Server = {}; // Mỗi máy chủ ta tạo trên Discord có 1 Object Server riêng có key là id của máy chủ đó. // Object này sẽ lưu danh sách các bài hát đang chờ được phát "queue". // Bài hát đang phát "playing". // Dispatcher quản lí việc stream từ server bot tới Discord.Tạo foder services trong src có file youtube.ts. Đây là nơi ta tương tác với api Youtube:
import ytsr from "ytsr"; import ytdl from "ytdl-core"; import ytpl from "ytpl"; import { youtubeVideoRegex } from "../constant/regex"; // Tìm video bằng từ khoá và trả về id video nếu tìm thấy hoặc trả về tin nhắn lỗi. const searchVideo = (keyword: string) => { try { return ytsr(keyword, { pages: 1 }) .then((result) => { const filteredRes = result.items.filter((e) => e.type === "video"); if (filteredRes.length === 0) throw "🔎 Can't find video!"; const item = filteredRes[0] as { id: string; }; return item.id; }) .catch((error) => { throw error; }); } catch (e) { throw "❌ Invalid params"; } }; // Cấu trúc của 1 video mà ta sẽ lưu vào server export interface Resource { title: string; length: number; author: string; thumbnail: string; url: string; } // Lấy thông tin của 1 video bằng nội dung truyền vào. URL hoặc từ khoá export const getVideoDetails = async (content: string): Promise<Resource> => { const parsedContent = content.match(youtubeVideoRegex); let id = ""; if (!parsedContent) { id = await searchVideo(content); } else { id = parsedContent[1]; } const url = `https://www.youtube.com/watch?v=${id}`; return ytdl .getInfo(url) .then((result) => { return { title: result.videoDetails.title, length: parseInt(result.videoDetails.lengthSeconds, 10), author: result.videoDetails.author.name, thumbnail: result.videoDetails.thumbnails[ result.videoDetails.thumbnails.length - 1 ].url, url, }; }) .catch(() => { throw "❌ Error"; }); }; interface Playlist { title: string; thumbnail: string; author: string; resources: Resource[]; } // Lấy danh sách video và thông tin 1 playlist export const getPlaylist = async (url: string): Promise<Playlist> => { try { const id = url.split("?")[1].split("=")[1]; const playlist = await ytpl(id); const resources: Resource[] = []; playlist.items.forEach((item) => { resources.push({ title: item.title, thumbnail: item.bestThumbnail.url, author: item.author.name, url: item.shortUrl, length: item.durationSec, }); }); return { title: playlist.title, thumbnail: playlist.bestThumbnail.url, author: playlist.author.name, resources, }; } catch (e) { throw "❌ Invalid playlist!"; } };Tạo folder utils trong src chứa file time.ts:
// Fomat thời gian video từ giây sang dạng mm:ss // Ví dụ. 70s -> 01:10 export const formatTimeRange = (timeRange: number): string => { const mins = Math.floor(timeRange / 60); const seconds = timeRange - hours * 60; return `${mins < 10 ? "0" + mins : mins}:${seconds < 10 ? "0" + seconds : seconds}`; };Tạo folder actions trong src . Tại đây ta sẽ tạo các actions để xử lý các tác vụ như play, pause,... Ta tạo các file với nội dung lần lượt như sau:
- actions/play.ts
- actions/skip.ts
- actions/pause.ts
- actions/nowplaying.ts
Truy cập lại vào app bạn tạo trên Discord tại https://discord.com/developers/applications. Click OAuth2. Tick vào bot và họn các quyền như hình dưới.
Click Copy để copy link mời bot vào máy chủ. Mời bot và máy chủ và dùng thử thôi 😉.
Deploy lên Heroku
Tạo 1 web đơn giản chứa đường dẫn mời bot đến máy chủ và gắn vào bot bằng express (optional). Cái này mình không hướng dẫ ở đây. Bạn nào thích thì có thể làm thêm. Install 1 vài package sau. yarn add express heroku-awake hoặc npm i express heroku-awake --save
heroku-awake giúp server không bị sleep. yarn add @types/express -D hoặc npm i @types/express --save-dev Sửa lại file index.ts như sau
import express from "express"; import herokuAwake from "heroku-awake"; import { Client } from "discord.js"; import play from "./actions/play"; import skip from "./actions/skip"; import nowplaying from "./actions/nowplaying"; import pause from "./actions/pause"; import resume from "./actions/resume"; import stop from "./actions/stop"; import clear from "./actions/clear"; const port = process.env.PORT || 3000; const server = express(); const url = ""; // Đường dẫn của app bạn trên Heroku const bot = (): void => { const client = new Client(); const token = process.env.TOKEN; client.on("message", (message) => { const args = message.content.substring(prefix.length).split(" "); const content = message.content.substring(prefix.length + args[0].length); if (message.content[0] === "!") { switch (args[0]) { case play.name: play.execute(message, content); break; case skip.name: skip.execute(message); break; case nowplaying.name.toString(): nowplaying.execute(message); break; case pause.name: pause.execute(message); break; case resume.name: resume.execute(message); break; case stop.name: stop.execute(message); break; case clear.name: clear.execute(message); break; // More short command case "np": nowplaying.execute(message); break; case "fs": skip.execute(message); break; } } }); client.on("ready", () => { console.log("🏃♀️ Misabot is online! 💨"); }); client.once("reconnecting", () => { console.log("🔗 Reconnecting!"); }); client.once("disconnect", () => { console.log("🛑 Disconnect!"); }); client.login(token); }; server.disable('x-powered-by'); server.listen(port, () => { bot(); herokuAwake(url); console.log(`🚀 Server is running on port ${port} ✨`); });Truy cập https://devcenter.heroku.com/articles/heroku-cli để cài đặt heroku-cli nếu bạn chưa có.
Truy cập tiếp https://dashboard.heroku.com/apps để tạo ứng dụng mới.
Click tab Settings và thêm biến môi trường của bạn vào đây
Chạy lần lượt các câu lệnh sau để deploy ứng dụng của bạn. $ heroku login $ cd my-project/ $ git init $ heroku git:remote -a <tên ứng dụng của bạn> $ git add . $ git commit -am "make it better" $ git push heroku master Tổng kếtTrên đây là cách tạo 1 bot Discord để phát nhạc trong Discord với các chức năng:
- play: phát 1 bài nhạc theo tên hoặc url Youtube, thêm nhạc vào danh sách chờ bằng url playlist.
- pause, resume: Dừng và tiếp tục.
- clear: Xoá danh sách phát đang chờ.
- stop: Dừng phát và rời khỏi kênh thoại.
- skip: Bỏ qua bài hát hiện tại
- nowplaying: Lấy thông tin bài hát đang phát.
Trong code có gì sơ suất mong mọi người thông cảm.
Tham khảoGithub repository Demo on Heroku Note: Tài nguyên trên Heroku khá ít và server đặt tại châu Âu nên bot join nhiều server hoặc internet của các bạn kém thì bot khá lag.😅
Từ khóa » Bot Nhạc Trong Discord
-
Hướng Dẫn Thêm Bot Vào Discord để Phát Nhạc - GEARVN
-
13 Bot Nhạc Discord Hay Nhất Vẫn Hoạt động (thay Thế Groovy ...
-
Cách Thêm Bot Nhạc Vào Discord Còn Hoạt động 2022 - Tino Group
-
9 Bot Tốt Nhất để đưa Nhạc Trên Discord | Diễn đàn Di động
-
7 Bots Nhạc Discord Hay Nhất để Phát Trực Tuyến Bài Hát Trong Máy Chủ
-
Cách Tạo Bot Trong Discord Chi Tiết - Các Bot Tốt Nhất Cho Máy Chủ ...
-
5 Bots Nhạc Discord Hay Nhất Cho Máy Chủ Của Bạn Năm 2022
-
Cách Tạo Bot âm Nhạc Discord Cực Chi Tiết - Affizon
-
Hướng Dẫn Về BOT Âm Nhạc - VozGaming - Read The Docs
-
Các Lệnh Bot Nhạc Trong Discord?
-
Làm Thế Nào để Sử Dụng Rythm Music Bot Trong Discord. Hướng ...
-
Top 8 Cách Thêm Bot Nhạc Vào Discord
-
Top 15 Cách Tạo Bot Nghe Nhạc Trong Discord
-
Cách Phát Nhạc Trong Discord Bằng Bot | Tin Mới - TinMoiZ