반응형
이제 얼추 정리는 끝났다.
유튜브search api도 가져왔고, 그걸 이용하여 노래 재생까지 완료된 상태다.
여기에 명령어를 정리하여 코드를 정리해보자
현재까지 작성했던 내용을 바탕으로 조금 정리해본 코드이다.
const { Client, GatewayIntentBits } = require('discord.js');
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus } = require('@discordjs/voice');
const ytdl = require('ytdl-core');
const { token, youtubeApiKey } = require('./discordConfig.js');
const sodium = require('libsodium-wrappers'); // 추가된 부분
const search = require('youtube-search'); // 유튜브 검색 추가
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
const opts = {
maxResults: 1,
key: youtubeApiKey,
type: 'video'
};
// 준비
client.on('ready', () => console.log(`${client.user.tag} 에 로그인됨`));
let connection;
let voiceChannel;
let player;
let isPlaying = false;
//명령어가 !재생인경우
function prefixPlay(message){
const query = message.content.replace('!재생', '').trim();
if (!query) {
return message.reply('재생할 노래 제목이나 URL을 입력하세요.');
}
voiceChannel = message.member.voice.channel;
if (!voiceChannel) {
return message.reply('채널에 먼저 선 입장 필요');
}
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT') || !permissions.has('SPEAK')) {
return message.reply('권한이 없습니다.');
}
search(query, opts, async (err, results) => {
if (err) return console.error(err);
if (results.length === 0) {
return message.reply('검색 결과가 없습니다.');
}
const playUrl = results[0].link;
if (!isPlaying) {
playNext(voiceChannel, message.guild, playUrl);
}
});
}
// 노래 재생
async function playNext(voiceChannel, guild, playUrl) {
try {
if (!connection) {
connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: message.guild.id,
adapterCreator: message.guild.voiceAdapterCreator,
});
}
const playStream = () => {
const stream = ytdl(playUrl, {
filter: 'audioonly',
fmt: "mp3",
highWaterMark: 1 << 62,
liveBuffer: 1 << 62,
dlChunkSize: 0, //disabling chunking is recommended in discord bot
bitrate: 128,
quality: "lowestaudio"
});
const resource = createAudioResource(stream);
player.play(resource);
}
player = createAudioPlayer();
playStream();
connection.subscribe(player);
player.on(AudioPlayerStatus.Idle, () => {
playStream();
});
} catch (error) {
console.error(error);
}
}
function leaveChannel(message){
if(!connection) return message.channel.send("채널에없음")
connection.destroy()
connection = "" // connection 을 null로 만들어야지 다음 join이 됨...
isPlaying = false;
}
client.on('messageCreate', async message => {
if (message.content.startsWith("!재생")) prefixPlay(message);
else if(message.content === '!컷'){
isPlaying = false;
if (player) {
player.stop();
}
if (connection) {
leaveChannel(message)
}
}
});
client.login(token);
!재생 노래이름 입력시 노래이름을 기준으로 유튜브에 검색되어 해당 링크로 노래가 재생되도록 되어있다.
!컷 입력시 노래봇이 중지되며 퇴장되는데
이유는 모르겠지만 connection.destory() 시에 이미 선언한 connection 이 제대로 없어지지 않아 다음 노래 재생때 노래봇이 채널에 입장하지 못하는 이슈가 있다.
그래서 connection.destroy() 후에 connection=null 로 초기화를 하도록 해두었다.
해당 이슈에 대해서는 아직도 해결을 못하는 중이다.
어쨋든 이렇게 재생과 중지 명령어를 붙여서 코드를 한번 정리했다.
이후에 반복재생, 재생목록도 추가해야겠다.
반응형
'디스코드봇' 카테고리의 다른 글
[JS] 디스코드 노래 봇 6 (1) | 2024.10.17 |
---|---|
[JS] 디스코드 노래 봇 5 (0) | 2024.08.24 |
[JS] 디스코드 노래 봇 3 (0) | 2024.06.30 |
[JS] 디스코드 노래 봇 2 (1) | 2024.06.16 |
[JS] 디스코드 노래 봇 (1) | 2024.06.16 |