Discord.py로 음악 봇 업그레이드 #4: 음악 큐와 데이터 저장 추가하기

안녕하세요! 김코딩입ㄴ니다

지난 글에서는 유튜브 음악을 재생하는 디스코드 봇을 만들어봤죠. 하지만 한 곡씩만 재생할 수 있어서 아쉬웠을 텐데요. 오늘은 그 한계를 뛰어넘어 음악 큐 시스템사용자별 선호 곡 저장 기능을 추가해 더욱 강력한 음악 봇을 만들어보겠습니다!

친구들과 함께 음악 파티를 열 준비되셨나요? 그럼 시작해볼까요?


1. 지난 글 복습: 어디까지 했나요?

지난 포스트에서는 다음 기능을 구현했어요:

  • !join 명령어: 봇이 음성 채널에 입장
  • !play 명령어: 유튜브 음악 재생
  • !leave 명령어: 봇이 음성 채널에서 나가기
  • youtube_dlffmpeg를 활용한 유튜브 음원 재생

이제 이 기본 기능에 음악 큐데이터 저장 기능을 추가해서 더욱 똑똑한 음악 봇을 만들어볼 거예요!


2. 이번 글의 목표

우리가 추가할 기능은 다음과 같습니다:

음악 큐: 여러 곡을 대기열에 추가하고 순서대로 자동 재생 데이터 저장: 사용자별 선호 곡을 저장하고 불러오기 추가 명령어:

  • !queue → 현재 대기열 확인
  • !skip → 현재 재생 중인 곡 건너뛰기
  • !favorite → 선호 곡 저장
  • !play_favorite → 저장된 선호 곡 재생

3. 준비물 확인

작업을 시작하기 전에 다음을 확인하세요:

  • youtube_dlffmpeg가 이미 설치되어 있어야 합니다.
  • 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. 마무리 🎵

이제 디스코드 서버에서 음악 큐사용자별 선호 곡 저장 기능을 갖춘 강력한 음악 봇을 즐길 수 있습니다! 다음 단계로는 볼륨 조절, 자동 추천 곡 기능, 유튜브 검색 기능 등을 추가해볼 수 있겠네요. 여러분의 아이디어가 있다면 댓글로 남겨주세요! 😊

One comment

Leave a Reply

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다