메뉴 건너뛰기

목록
2021.10.07 05:46

음악봇

profile
조회 수 106 댓글 2 예스잼 1 노잼 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# In[0]:System
 
# 비동기
import asyncio
import nest_asyncio
 
# 유튜브 영상 다운로더
import youtube_dl
 
# 디스코드봇
import discord
from discord.ext import commands
 
# In[1]:Yotube_dl_Opts
# Suppress noise about console usage from errors
youtube_dl.utils.bug_reports_message = lambda: ''
 
ytdl_format_options = {
    'format''bestaudio/best',
    'outtmpl''%(extractor)s-%(id)s-%(title)s.%(ext)s',
    'restrictfilenames'True,
    'noplaylist'True,
    'nocheckcertificate'True,
    'ignoreerrors'False,
    'logtostderr'False,
    'quiet'True,
    'no_warnings'True,
    'default_search''auto',
    'source_address''0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes
}
 
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, stream=False):
        loop = loop or asyncio.get_event_loop()
        data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
 
        if 'entries' in data:
            # take first item from a playlist
            data = data['entries'][0]
 
        filename = data['url'if stream else ytdl.prepare_filename(data)
        return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
 
# In[2]:Discord_Command
class Music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
    
    # 노래 대기열
    queues={}
    
    # 다음노래가 있는지 확인 후 있으면 재생 없으면 그냥 리턴
    def check_queue(self,ctx,id):
        if Music.queues[id] !=[]:
            voice=ctx.guild.voice_client
            source=Music.queues[id].pop(0)
            voice.play(source, after=lambda x : Music.check_queue(self, ctx, ctx.message.guild.id))
            loop=self.bot.loop
            coroutine=ctx.send(f'Now playing: {source.title}')
            loop.run_until_complete(coroutine)
        return
 
    # 노래가 재생중이면 대기열에 노래를 추가하고, 재생중이 아니라면 바로 재생
    @commands.command()
    async def p(self, ctx, *, url):
        async with ctx.typing():
            # 노래 다운
            source = await YTDLSource.from_url(url, loop=self.bot.loop)    
            
            # 노래가 재생중이라면 대기열에 저장만하고 리턴
            if ctx.voice_client.is_playing():
                guild_id=ctx.message.guild.id
                if guild_id in Music.queues:
                    Music.queues[guild_id].append(source)
                else:
                    Music.queues[guild_id]=[source]
                await ctx.send(f'add queue: {source.title}')
                return
            
            # 재생중이 아니라면 바로 재생
            ctx.voice_client.play(source, after=lambda x : Music.check_queue(self, ctx, ctx.message.guild.id))
            await ctx.send(f'Now playing: {source.title}')
    
    # 현재 재생중인 노래를 끝냄
    @commands.command()
    async def Skip(self, ctx):
        async with ctx.typing():
            if ctx.voice_client.is_playing():
                ctx.voice_client.stop()
                await ctx.send('Skip!')
        
    # !p 가 호출되면 호출한사람이 음성채널에 접속중인지 확인
    @p.before_invoke
    async def ensure_voice(self, ctx):
        if ctx.voice_client is None:
            if ctx.author.voice:
                await ctx.author.voice.channel.connect()
            else:
                await ctx.send("You are not connected to a voice channel.")
                raise commands.CommandError("Author not connected to a voice channel.")
            
            
# In[3]:Main
 
bot = commands.Bot(command_prefix=commands.when_mentioned_or("!"),
                   description='Relatively simple music bot example')
 
@bot.event
async def on_ready():
    print(f'Logged in as {bot.user} (ID: {bot.user.id})')
    print('------')
 
 
bot.add_cog(Music(bot))   
nest_asyncio.apply()
 
# (Token)
bot.run('ODk1MDQ5MTg4ODE4MTc4MTM4.YVy5gw.5kBfd-k17oyqoVkU_WeT8BR4VnU')
 
 
참고자료
 
스크립트 베이스 - https://github.com/Rapptz/discord.py/blob/master/examples/basic_voice.py
 
대기열 - https://youtu.be/wPRFy4gDJ1Y
 
동기함수에서 비동기함수 호출 - https://www.joeltok.com/blog/2021-2/python-async-sync
cs

 

원래는 '노래끝나고' 이거를 after=lambda 가아니라 await.asyncio.sleep(duration) 으로 했었음

처음엔 재생하는거랑 대기열추가만 테스트했으니까 오우 씨발 괜찮네 하고 그대로 갔는데

스킵하는거 추가하면서 재생중인 노래중단하니까, 다음 노래 재생하다가 이전에 실행됬던 함수 뒤에 sleep 끝나는 타이밍에 노래가 끊기는게아니라 잠시 확빨라지는거임

뭐, 3분마다 스킵칠것도아닌데 굳이 손더봐야하나 하고 마무리했다가 그래도 제대로 마무리짓고싶어서 다른건 어떻게하는지 유튜브찾아봣음

 

받아쓰기다하고나니까 잘되는거보고 신기해서 좋아했는데 await ctx.send 넣을라고보니까 받아쓴 check_queue가 동기함수인거임

뭐 그럼 앞에 async 붙여주고 람다뒤에 await 붙여주면 되는거아닌가 싶어서하니까 람다에선 또 비동기함수를 호출못하네

how to use await in lambda.. 검색하니까 아이시팔 다안된데

그러다 혹시몰라서 how to use await in synchronous method 검색하니까 참고자료 맨밑에 포스트 저거나와서 따라하니까 와시팔 되네

 

근데 그렇게 동기함수에서 비동기함수 호출하니까

 

이미지 27.png

 

이런식으로 콘솔창에 에러뜨는데

뭐 ㅎㅎ;; 콘솔창에만뜨는거고 진짜 진짜 진짜 아무지장없는거같으니까 마무리하겠음


List of Articles
번호 제목 글쓴이 날짜 조회 수 추천
공지 수용소닷컴 이용약관 file asuka 2020.05.16 1341 1
1038 삭제된 게시글입니다. 우지챠 2021.01.16 108 0
1037 질문)사이트를 하나 만들어 보려고 함 8 주갤롬 2020.09.07 108 0
1036 Password와 Passphrase의 차이? 3 file 히마와리 2020.06.24 108 0
1035 요거 7 file 토깽이 2022.01.12 107 0
1034 하드디스크 오류 질문 44 file 의찬이 2020.08.14 107 0
» 음악봇 2 file 바보 2021.10.07 106 1
1032 C 포인터 질문좀 3 아트 2021.05.01 106 0
1031 병신도 컴공으로 취업하는 방법좀 알려주셈 4 그리드 2022.01.24 105 0
1030 이거 권한이 없습니다 창뜸 10 file 노동자 2021.10.19 105 0
1029 iOS개발 하지마셈 진심임 3 마루쉐 2021.08.26 105 2
1028 삭제된 게시글입니다. 스마일 2020.07.02 105 0
1027 삭제된 게시글입니다. 노모현 2020.05.27 105 0
1026 4시간 만에 버그 고쳤따.. 마루쉐 2021.01.18 104 1
1025 자바스크립트가 맘에 드는 점 하나 21 다람쥐 2020.07.09 104 0
1024 컴공 게이들한테 질문있음 7 아야나미레이 2022.01.08 103 0
1023 자바스크립트 Promise async await generator 요 4개조합 알면 좋은듯 4 file 머스크멜론 2021.04.09 103 0
1022 모니터 교체시기 4 file サキ 2020.09.10 103 0
1021 삭제된 게시글입니다. 노모현 2020.06.03 103 0
1020 삭제된 게시글입니다. midori 2022.01.09 102 0
1019 우분투 파티션 자동구성시 에러 말랑이 2024.02.17 101 0
목록
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 56 Next
/ 56