메뉴 건너뛰기

목록
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 1312 1
1111 gitlab쓰지 마셈 15 다람쥐 2020.06.11 671 0
1110 Selenium alert_is_present 작동 원리 2 우지챠 2021.01.04 623 1
1109 Microsoft Visual Studio 2022를 사용하여 첫 번째 C++ Windows Form 만들기 9 file 저능아 2023.01.15 380 1
1108 성님들도 서버호스팅 하나 받으셈 14 file 머스크멜론 2021.02.24 330 0
1107 해피해킹 프로2 type-s 사용기 8 file 다람쥐 2020.05.24 330 2
1106 정보) 수용서의 기본소양 1편, 짤검색에 대해서 araboji. 8 file 하루각하 2021.01.06 251 6
1105 RAID5 순차쓰기 성능이 너무 낮음... 1 아메 2021.12.29 247 0
1104 오늘 한 프로젝트: 그래픽 광량 표현 12 file 우지챠 2021.01.05 245 8
1103 좆본 IT 취업 가이드 ~ 간략판 ~ 9 抱き枕 2020.07.22 243 6
1102 삭제된 게시글입니다. 노모현 2020.06.03 243 0
1101 키 마우스 매핑 프로그램 만들었음 10 file '`' 2022.08.30 206 6
1100 스프링에서 파일업로드 개발하는데 왤케 에러나냐 8 阿米娅 2020.08.12 197 0
1099 시발 리눅스 SSH서버 공개키로그인이 왜안되나 했는데 5 file 히마와리 2020.06.21 196 0
1098 콤퓨타 ㅍㅌㅊ? 11 file 문향 2020.05.19 191 -1
1097 대학생 때 세웠던 목표를 이뤘음 7 file 마루쉐 2021.09.14 188 10
1096 삭제된 게시글입니다. 스마일 2020.06.12 182 0
1095 본인 노트북 자랑해봄 4 file ハンター 2020.05.20 181 0
1094 삭제된 게시글입니다. 노모현 2020.05.30 173 0
1093 오늘자 리팩터링 9 file 마루쉐 2021.01.03 171 5
목록
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 56 Next
/ 56