aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/music/play.py
blob: cf04ded5487890b8de2b59ab30fcc57e36b8659e (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
import asyncio
import logging

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

logger = logging.getLogger(__name__)

# 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.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',
        }

    async def play_audio(self, ctx, vc, url, title):
        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'
                }

                def after_playing(error):
                    if error:
                        logger.error(f'Player error: {error}')
                    coro = vc.disconnect()
                    fut = asyncio.run_coroutine_threadsafe(coro, self.bot.loop)
                    try:
                        fut.result()
                    except Exception as e:
                        logger.error(f'Error disconnecting: {e}', exc_info=True)

                source = discord.FFmpegPCMAudio(url2, **ffmpeg_options)
                vc.play(source, after=after_playing)
                await ctx.followup.send(f"gra: {title}")
                logger.info(f"Playing: {title}")
        except Exception as e:
            await ctx.followup.send(f"Wystąpił błąd podczas odtwarzania: {str(e)}")
            logger.error(f"Error playing audio: {e}", exc_info=True)

    @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")
            logger.info("User is not in a voice channel")
            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)
            logger.info(f"Could not find a video for search: {search}")
            return

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

        # Play the audio directly
        if vc.is_playing() or vc.is_paused():
            vc.stop()
        await self.play_audio(ctx, vc, url, title)


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