aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/music/play.py
blob: b47de03e9a329895678038775fe01a859542c6ad (plain) (blame)
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
143
144
145
146
147
import asyncio

import discord
import yt_dlp
from discord.ext import commands
from youtubesearchpython import VideosSearch

# Suppress noise about console usage from yt-dlp
yt_dlp.utils.bug_reports_message = lambda: ''


class Play(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.queues = {}
        self.ydl_opts = {
            'format': 'bestaudio/best',
            'postprocessors': [{
                'key': 'FFmpegExtractAudio',
                'preferredcodec': 'mp3',
                'preferredquality': '192',
            }],
            'noplaylist': True,
            'quiet': True,
            'no_warnings': True,
            'default_search': 'auto',
            'source_address': '0.0.0.0',
        }

    def get_queue(self, guild_id):
        return self.queues.setdefault(guild_id, [])

    async def play_next(self, ctx, vc, guild_id):
        queue = self.get_queue(guild_id)
        if queue:
            title, url = queue[0]

            def after_playing():
                if queue:
                    queue.pop(0)
                if queue:
                    next_title, next_url = queue[0]
                    if not vc.is_playing() and not vc.is_paused():
                        asyncio.run_coroutine_threadsafe(
                            self.play_audio(ctx, vc, next_url, next_title),
                            self.bot.loop
                        )
                else:
                    asyncio.run_coroutine_threadsafe(
                        vc.disconnect(),
                        self.bot.loop
                    )

            if not vc.is_playing() and not vc.is_paused():
                await self.play_audio(ctx, vc, url, title, after=after_playing)

    async def play_audio(self, ctx, vc, url, title, after=None):
        try:
            with yt_dlp.YoutubeDL(self.ydl_opts) as ydl:
                info = await self.bot.loop.run_in_executor(
                    None,
                    lambda: ydl.extract_info(url, download=False)
                )
                if 'entries' in info:
                    info = info['entries'][0]

                url2 = info['url']

                ffmpeg_options = {
                    'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
                    'options': '-vn'
                }

                source = discord.FFmpegPCMAudio(url2, **ffmpeg_options)
                vc.play(source, after=after)
                await ctx.followup.send(f"gra: {title}")
        except Exception as e:
            await ctx.followup.send(f"Wystąpił błąd podczas odtwarzania: {str(e)}")
            # Try to play next in the queue if there's an error
            if after:
                after(None)

    @commands.slash_command(name="grajcuj", description="grajcuj melodyje")
    async def play(self, ctx, *, search: str):
        await ctx.defer()

        if not (ctx.author.voice and ctx.author.voice.channel):
            await ctx.followup.send("nie jesteś w kanale głosowym")
            return

        channel = ctx.author.voice.channel
        vc = ctx.voice_client or await channel.connect()

        if vc.channel != channel:
            await vc.move_to(channel)

        # Search for the video
        videos_search = VideosSearch(search, limit=1)
        result = videos_search.result()

        if not result['result']:
            await ctx.followup.send("nie znaleziono wideo dla twojego wyszukiwania.", ephemeral=True)
            return

        video = result['result'][0]
        title = video['title']
        url = video['link']

        # Add to queue
        queue = self.get_queue(ctx.guild.id)
        queue.append((title, url))

        # If nothing is playing, start playing
        if not vc.is_playing() and not vc.is_paused():
            await self.play_next(ctx, vc, ctx.guild.id)
        else:
            await ctx.followup.send(f"dodano do kolejki: {title}")

    @commands.slash_command(name="stop", description="zatrzymaj odtwarzanie i wyczyść kolejkę")
    async def stop(self, ctx):
        if ctx.voice_client:
            queue = self.get_queue(ctx.guild.id)
            queue.clear()
            await ctx.voice_client.disconnect()
            await ctx.respond("Zatrzymano odtwarzanie i wyczyszczono kolejkę")
        else:
            await ctx.respond("Nie jestem połączony z kanałem głosowym")

    @commands.slash_command(name="pauza", description="wstrzymaj odtwarzanie")
    async def pause(self, ctx):
        if ctx.voice_client and ctx.voice_client.is_playing():
            ctx.voice_client.pause()
            await ctx.respond("Wstrzymano odtwarzanie")
        else:
            await ctx.respond("Nic nie jest teraz odtwarzane")

    @commands.slash_command(name="wznow", description="wznów odtwarzanie")
    async def resume(self, ctx):
        if ctx.voice_client and ctx.voice_client.is_paused():
            ctx.voice_client.resume()
            await ctx.respond("Wznowiono odtwarzanie")
        else:
            await ctx.respond("Nic nie jest teraz wstrzymane")


def setup(bot):
    bot.add_cog(Play(bot))