안녕하세요! 김코딩입ㄴ니다
지난 글에서는 유튜브 음악을 재생하는 디스코드 봇을 만들어봤죠. 하지만 한 곡씩만 재생할 수 있어서 아쉬웠을 텐데요. 오늘은 그 한계를 뛰어넘어 음악 큐 시스템과 사용자별 선호 곡 저장 기능을 추가해 더욱 강력한 음악 봇을 만들어보겠습니다!
친구들과 함께 음악 파티를 열 준비되셨나요? 그럼 시작해볼까요?
1. 지난 글 복습: 어디까지 했나요?
지난 포스트에서는 다음 기능을 구현했어요:
!join
명령어: 봇이 음성 채널에 입장!play
명령어: 유튜브 음악 재생!leave
명령어: 봇이 음성 채널에서 나가기youtube_dl
과ffmpeg
를 활용한 유튜브 음원 재생
이제 이 기본 기능에 음악 큐와 데이터 저장 기능을 추가해서 더욱 똑똑한 음악 봇을 만들어볼 거예요!
2. 이번 글의 목표
우리가 추가할 기능은 다음과 같습니다:
음악 큐: 여러 곡을 대기열에 추가하고 순서대로 자동 재생 데이터 저장: 사용자별 선호 곡을 저장하고 불러오기 추가 명령어:
!queue
→ 현재 대기열 확인!skip
→ 현재 재생 중인 곡 건너뛰기!favorite
→ 선호 곡 저장!play_favorite
→ 저장된 선호 곡 재생
3. 준비물 확인
작업을 시작하기 전에 다음을 확인하세요:
youtube_dl
과ffmpeg
가 이미 설치되어 있어야 합니다.json
모듈이 필요하지만, 다행히도 Python 기본 모듈이라 따로 설치할 필요가 없습니다.- 봇이 서버에서 “Connect” 및 “Speak” 권한을 가지고 있어야 합니다.
4. 완성된 코드
아래는 큐와 데이터 저장 기능이 추가된 전체 코드입니다. 하나씩 뜯어보며 설명하겠습니다.
import discord
from discord.ext import commands
import youtube_dl
import asyncio
import json
from collections import deque
# 봇 설정
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
music_queue = deque() # 음악 큐 (FIFO 구조)
favorites = {} # 사용자별 선호 곡 저장
# youtube_dl 설정
ytdl_format_options = {
'format': 'bestaudio/best',
'noplaylist': True,
'quiet': True,
}
ffmpeg_options = {'options': '-vn'}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
@classmethod
async def from_url(cls, url, *, loop=None):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=False))
if 'entries' in data:
data = data['entries'][0]
filename = data['url']
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
# 데이터 로드/저장 함수
def load_favorites():
global favorites
try:
with open('favorites.json', 'r') as f:
favorites = json.load(f)
except FileNotFoundError:
favorites = {}
def save_favorites():
with open('favorites.json', 'w') as f:
json.dump(favorites, f, indent=4)
# 봇 준비
@bot.event
async def on_ready():
load_favorites() # 선호 곡 로드
print(f"{bot.user}가 온라인이에요!")
# 음악 큐 시스템
async def play_next(ctx):
if music_queue:
player = music_queue.popleft()
ctx.voice_client.play(player, after=lambda e: asyncio.run_coroutine_threadsafe(play_next(ctx), bot.loop))
await ctx.send(f"지금 재생 중: {player.title}")
else:
await ctx.send("큐가 비었어요!")
# 명령어: 음악 재생 및 큐 추가
@bot.command()
async def play(ctx, url):
async with ctx.typing():
player = await YTDLSource.from_url(url, loop=bot.loop)
if ctx.voice_client.is_playing():
music_queue.append(player)
await ctx.send(f"큐에 추가됨: {player.title}")
else:
ctx.voice_client.play(player, after=lambda e: asyncio.run_coroutine_threadsafe(play_next(ctx), bot.loop))
await ctx.send(f"지금 재생 중: {player.title}")
# 명령어: 큐 확인
@bot.command()
async def queue(ctx):
if not music_queue:
await ctx.send("큐가 비어 있어요!")
else:
queue_list = "\n".join([f"{i+1}. {song.title}" for i, song in enumerate(music_queue)])
await ctx.send(f"현재 큐:\n{queue_list}")
# 명령어: 선호 곡 저장
@bot.command()
async def favorite(ctx, url):
user_id = str(ctx.author.id)
favorites[user_id] = url
save_favorites()
await ctx.send(f"{ctx.author.name}님의 선호 곡을 저장했어요: {url}")
# 명령어: 선호 곡 재생
@bot.command()
async def play_favorite(ctx):
user_id = str(ctx.author.id)
if user_id in favorites:
await play(ctx, favorites[user_id])
else:
await ctx.send("저장된 선호 곡이 없어요! `!favorite URL`로 추가해보세요.")
# 봇 실행
bot.run("여기에-여러분의-토큰을-붙여넣으세요")

5. 마무리 🎵
이제 디스코드 서버에서 음악 큐와 사용자별 선호 곡 저장 기능을 갖춘 강력한 음악 봇을 즐길 수 있습니다! 다음 단계로는 볼륨 조절, 자동 추천 곡 기능, 유튜브 검색 기능 등을 추가해볼 수 있겠네요. 여러분의 아이디어가 있다면 댓글로 남겨주세요! 😊
[…] 지난 글에서 음악 봇과 날씨 봇을 다뤘다면, 이번에는 디스코드 서버를 더욱 재미있게 만들어줄 퀴즈 봇을 만들어보겠습니다. […]