메뉴 건너뛰기

목록
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 1309 1
508 워드프레스랑 XE 스토어 보는중... 1 file 鎌倉 2021.10.24 49 0
507 메서드이름짓기 귀찮아서 7 file 저능아 2021.10.24 63 0
506 파이썬 기본 문법은 떼고 만들기 시작해야될거 같음 3 file 노동자 2021.10.21 82 0
505 시바 리눅스 6 그리드 2021.10.20 62 0
504 막상 해보니 셀레니움으로는 못할거 같기도 하네 17 노동자 2021.10.19 129 0
503 이거 권한이 없습니다 창뜸 10 file 노동자 2021.10.19 105 0
502 허접이라 파이썬 하겠음 2 그리드 2021.10.16 120 0
501 else if 왜쓰는지 이제 이해했음 5 바보 2021.10.15 100 0
500 갑자기 궁금해진거 2 file 바보 2021.10.14 70 0
499 공부에 게을러지고 있음 1 그리드 2021.10.13 74 0
498 클래스밖변수 따로 선언안하면 못쓰는줄알았는데 4 file 바보 2021.10.13 92 0
497 Windows Terminal 이걸 왜 이제야 알았지 4 만년필 2021.10.11 81 0
496 합필갤 다운로더 3 머스크멜론 2021.10.11 99 0
495 vs가 용량 엄청 먹는구나 2 만년필 2021.10.10 75 0
494 이번 연휴엔 닷넷 6.0 하기로 했는데 2 만년필 2021.10.10 72 0
493 코린이 PyQt5 공부하고있어요 7 file 바보 2021.10.09 84 0
492 WEB3가 뭐임 2 그리드 2021.10.08 52 0
» 음악봇 2 file 바보 2021.10.07 106 1
490 하이쉿팔 2 file 바보 2021.10.07 74 0
489 파이썬 깔아봐야지 5 그리드 2021.10.06 77 0
목록
Board Pagination Prev 1 ... 26 27 28 29 30 31 32 33 34 35 ... 56 Next
/ 56