discord.js v14로 만든 디스코드 음악봇입니다. 유튜브 검색 API를 사용하여 검색을 진행합니다. discord.js v14로 업그레이드와 npm i create .env file nodemon .env 사용법/help
/play
/skip
/stop
/q
/pause
/unpause
- 이 강좌는 Node.js와 npm이 컴퓨터에 깔려있다는 전제 하에 작성되었습니다. 전에 썼던 디스코드 챗봇 만들기에 이어서 이번에는 자바스크립트를 이용해 음성을 출력할수 있는 봇을 만들어보려 합니다. discord.js의 사용법을 모르는 분들은 여기를 먼저 읽으시면 됩니다.
음성 기능을 이용하기 위해서는 음성관련 처리를 해주는 새로운 모듈이 필요한데요, node-opus 입니다. node-opus 말고 opusscript라는 모듈을 대신 사용할 수 있지만, 처리 효율성으로 봤을때 node-opus가 훨씬 좋습니다. package.json의 dependencies에 추가한 뒤 cmd를 켜서 npm install이라고 명령하거나, npm install node-opus를 쳐 주시면 됩니다. 다만 이 모듈의 경우에는 c로 작성되어 있어서 node-gyp 모듈이 필요합니다. npm install node-opus 설치할때 화면에 로그가 엄청나게 많이 표시될겁니다. 그게 정상이에요.
음성봇도 사용은 단순합니다. 먼저 1:1 채팅인 경우에는 채널이라는 개념이 없기 때문에 특정 채널에 들어가는것이 불가능합니다. 그러므로 개인채팅에서는 사용할 수 없게 return을 합니다. 만약에 개인채팅이 아니라면 /재생 이라고 입력했는지 비교하고, 입력했다면 메시지를 보낸 사람이 보이스채널에 들어가있는지 체크합니다. 만약 들어가있다면 봇은 그 보이스채널에 join()을 해서 들어갑니다. 그리고 보이스채널에 성공적으로 연결되면 특정 파일을 재생합니다. 물론 코드가 있는 폴더에 mp3 파일이 있어야 됩니다. 이제 [node 파일명] 을 해서 실행하세요. 유저가 먼저 보이스채널에 들어간뒤, /재생 을 치면 재생이 됩니다. 지금은 이렇게 단순하지만, discord.js에서 이용할 수 있는 보이스 기능은 이것보다 더 방대합니다. 다른 모듈, 스트림과 함께 사용하면 youtube 영상을 플레이할수도 있습니다. 이런 추가적인 기능들은 나중에 써보도록 하겠습니다. 그럼 전 이만. // Extract the required classes from the discord.js module const { Client, Attachment } = require('discord.js'); // Create an instance of a Discord client const client = new Client(); client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); client.user.setActivity('봇 만들자', { type: 'WATCHING' }) }); client.on('message', msg => { if (msg.content.startsWith('r.help')) { msg.reply('Powered by node.js\nMade by M4ndU'); } if (msg.content.startsWith('r.gif')) { const args = msg.content.split(' ').slice(1); // All arguments behind the command name with the prefix var no = args.join(' '); // Amount of messages which should be deleted if (!no) no = '1'; if (isNaN(no) || no > 14) return msg.reply('only number 1-14'); // Create the attachment using Attachment var path = "./gif/"; path = path.concat(no,".gif"); console.log(path); const attachment = new Attachment(path); // Send the attachment in the message channel with a content msg.channel.send(attachment); } if (msg.content === 'r.play') { // Only try to join the sender's voice channel if they are in one themselves if (msg.member.voiceChannel) { msg.member.voiceChannel.join() .then(connection => { // Connection is an instance of VoiceConnection msg.reply('playing music!'); const dispatcher = connection.playFile('./music.mp3'); dispatcher.on("end", end => {}); }) .catch(console.log); } else { msg.reply('먼저 방에 들어가'); } } if (msg.content === 'r.leave') { // Only try to join the sender's voice channel if they are in one themselves if (msg.member.voiceChannel) { msg.member.voiceChannel.leave(); msg.reply('bye!'); } else { msg.reply('이미 나왔는데..'); } } if (msg.content.toLowerCase().startsWith("r.clear")) { const args = msg.content.split(' ').slice(1); // All arguments behind the command name with the prefix const amount = args.join(' '); // Amount of messages which should be deleted if (!amount) return msg.reply('You haven\'t given an amount of messages which should be deleted!'); // Checks if the `amount` parameter is given if (isNaN(amount)) return msg.reply('The amount parameter isn`t a number!'); // Checks if the `amount` parameter is a number. If not, the command throws an error if (amount > 10) return msg.reply('You can`t delete more than 10 messages at once!'); // Checks if the `amount` integer is bigger than 100 if (amount < 1) return msg.reply('You have to delete at least 1 message!'); // Checks if the `amount` integer is smaller than 1 msg.channel.fetchMessages({ limit: amount }).then(dmsg => { // Fetches the messages msg.channel.bulkDelete(dmsg // Bulk deletes all messages that have been fetched and are not older than 14 days (due to the Discord API) ).catch(console.log);}); } if (msg.content === 'r.whoami') { // Send the user's avatar URL msg.reply(msg.author.avatarURL); } }); client.login('token'); |