방명록
- 파이썬으로 디스코드 음악봇 제작기 - 22021년 12월 22일 15시 13분 43초에 업로드 된 글입니다.작성자: RACENI
- 기능(아래의 기능은 개발이 진행되면서 추가 혹은 변경, 제거가 될 수 있습니다.)
- 유튜브 영상의 음성 출력
- 추가한 리스트 목록 확인
- 플레이리스트(추가한 노래 리스트) 저장 및 불러오기
- 리스트 목록 개별 제거
- loop 기능
- leave 기능
- skip 기능
- pause 기능
- resume 기능
- save 기능(2에 추가)
- open 기능(2에 추가)
파이썬으로 디스코드 음악 봇 제작기는 3까지 진행될 것 같습니다.
이번 2에서는 플레이리스트 기능과 각종 기타 기능을 추가하는 가벼운 작업(?)이 되겠습니다.
추후에 있을 제작기 3에 완성된 소스코드를 올리도록 하겠습니다! 이번 회차까지는 부분 별로 코드를 업로드하겠습니다.
감사합니다.
- 파이썬으로 디스코드 음악 봇 제작기
- 파이썬으로 디스코드 음악봇 제작기 - 1: https://saracenletter.tistory.com/317
- 간략한 구현 과정
- 플레이리스트 제작
- 각종 기능(일시정지, 다시시작, 넘기기 등)
- 파이썬으로 구현된 코드
- 좀 더 봇같은 대화를 위해 Embed 사용을 위해 함수를 만들어줬습니다.
def set_Embed(title = '', description = ''): #embed = discord.Embed(title="메인 제목", description="설명", color=0x62c1cc) return discord.Embed(title=title, description=description)
- 플레이리스트 적용을 위해서 전역변수 i(int형)를 추가했습니다.
- Loop 기능 적용을 위해서 전역변수 loop(bool형), playlist(list형)을 추가했습니다.
- 바뀐 song_start함수와 play함수 코드를 보여드리겠습니다.
async def song_start(voice, i): try: if not voice.is_playing() and not voice.is_paused(): ydl_opts = {'format': 'bestaudio'} FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'} with youtube_dl.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(f'https://www.youtube.com{playlist[i][1]}', download=False) URL = info['formats'][0]['url'] voice.play(discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS)) #voice.play(discord.FFmpegPCMAudio(executable = './ffmpeg-4.4-full_build-shared/bin/ffmpeg.exe', source='./song.mp3')) while voice.is_playing() or voice.is_paused(): await asyncio.sleep(0.1) except: return @bot.command(aliases = ['play', 'p', 'ㅔ']) async def Play(ctx,*, keyword): try: results = YoutubeSearch(keyword, max_results=1).to_dict() global playlist playlist.append([results[0]['title'], results[0]['url_suffix']]) # 플레이리스트에 노래 추가 await ctx.send(embed=set_Embed(title='노래 추가',description=f"{results[0]['title']}")) channel = ctx.author.voice.channel if bot.voice_clients == []: await channel.connect() #await ctx.send("connected to the voice channel, " + str(bot.voice_clients[0].channel)) voice = bot.voice_clients[0] if not voice.is_playing() and not voice.is_paused(): global i i = 0 while True: await song_start(voice, i) if loop: if i < len(playlist) - 1: i = i + 1 else: i = 0 continue elif i < len(playlist) - 1: i = i + 1 continue playlist = [[]] break #await voice.disconnect() except: await ctx.send("Play Error")
- 저장한 플레이리스트를 파일로 저장하고 불러오는 기능을 통해 영구 보존할 수 있게끔 했습니다.
@bot.command(aliases = ['save']) async def Save(ctx, * , arg): with open(f'{arg}.txt','w',encoding='UTF-8') as f: global playlist f.write(str(playlist)) @bot.command(aliases = ['open']) async def Open(ctx, * , arg): try: with open(f'./{arg}.txt','r',encoding='UTF-8') as f: global playlist playlist = eval(f.read()) global i await ctx.send(f"플레이리스트 추가 완료\n{arg}") channel = ctx.author.voice.channel if bot.voice_clients == []: await channel.connect() voice = bot.voice_clients[0] if voice.is_playing() or voice.is_paused(): i = -1 bot.voice_clients[0].stop() else: i = 0 while True: await song_start(voice, i) if loop: if i < len(playlist) - 1: i = i + 1 else: i = 0 continue elif i < len(playlist) - 1: i = i + 1 continue playlist = [[]] break except: await ctx.send("Open Error")
- remove와 q 명령어를 통해 플레이리스트에 있는 노래를 제거하거나 볼 수 있게끔 했습니다.
@bot.command(aliases = ['q', 'ㅂ']) async def Que(ctx): try: queText = '' for title in range(len(playlist)): try: queText = f'{queText}\n' + f'{title + 1}. {playlist[title][0]}' except: del playlist[title] await ctx.send(embed=set_Embed(title='플레이리스트',description=f"{queText}")) except: pass @bot.command(aliases = ['remove']) async def Remove(ctx, arg): try: global playlist remove_song = playlist[int(arg)- 1][0] del(playlist[int(arg)- 1]) global i i = i - 1 if (i + 1) == int(arg) - 1: bot.voice_clients[0].stop() await ctx.send(embed=set_Embed(title='노래 삭제',description=f"{remove_song}")) except: await ctx.send('노래 제거중 오류 발생!')
- 루프 사용은 loop 변수를 true/false로만 변경해주고 처리는 play함수에서 진행하게끔 했습니다.
@bot.command(aliases = ['loop', 'l', 'ㅣ']) async def Loop(ctx): try: global loop loop = True if loop == False else False # true false 서로 변경 await ctx.send(f"현재 LOOP 상태: {loop}") except: await ctx.send("Loop Error")
- 기타 기능들입니다.
@bot.command(aliases = ['leave']) async def Leave(ctx): try: await bot.voice_clients[0].disconnect() except: await ctx.send('Leave Error') @bot.command(aliases = ['skip', 's']) async def Skip(ctx): try: bot.voice_clients[0].stop() except: await ctx.send("Skip Error") @bot.command(aliases = ['pause']) async def Pause(ctx): try: bot.voice_clients[0].pause() except: await ctx.send("Pause Error") @bot.command(aliases = ['resume']) async def Resume(ctx): try: bot.voice_clients[0].resume() except: await ctx.send("Resume Error")
- 좀 더 봇같은 대화를 위해 Embed 사용을 위해 함수를 만들어줬습니다.
복잡한 코드가 없어서 주석을 안 넣었습니다.
(최종본에는 들어갈지도,,,)일단 남은 문제점은 여러 채널에서 사용하려하면 오류가 나는 것입니다. 하나의 thread만 사용해서 그런 것 같은데, 천천히 찾아보면서 고치려고 합니다. 해당 문제가 고쳐지면 소스코드 정리해서 최종본을 업로드할 계획입니다.
코드에 궁금한 점이 있으면 댓글로 물어봐주시면 좋겠습니다!
날이 많이 쌀쌀해졌는데, 감기 조심하시구 재밌는 프로그래밍 하시길 바랍니다~
감사합니다~!!!
(구독도 ^^7)'CODING > Python' 카테고리의 다른 글
파이썬으로 디스코드 음악봇 제작기 - 1 (0) 2021.09.08 [파이썬:Python]달팽이배열 (0) 2020.07.04 [파이썬:Python]타자게임 (0) 2019.06.13 다음글이 없습니다.이전글이 없습니다.댓글 - 기능(아래의 기능은 개발이 진행되면서 추가 혹은 변경, 제거가 될 수 있습니다.)