aboutsummaryrefslogtreecommitdiffstats
path: root/cogs
diff options
context:
space:
mode:
authorSamlon <stankiewiczgracjan2019@gmail.com>2025-07-25 19:36:56 +0200
committerSamlon <stankiewiczgracjan2019@gmail.com>2025-07-25 19:36:56 +0200
commit507f03e716478fce3ee9b9c3f3f5964c34b5b2dd (patch)
treeb0390fdd5fd2e58d823819ead939cc48c1c03050 /cogs
parentcode-style issues (diff)
downloadsenator-sperma-507f03e716478fce3ee9b9c3f3f5964c34b5b2dd.tar.gz
senator-sperma-507f03e716478fce3ee9b9c3f3f5964c34b5b2dd.zip
play.py fix
Diffstat (limited to 'cogs')
-rw-r--r--cogs/downloader.py58
-rw-r--r--cogs/music/play.py84
-rw-r--r--cogs/music/play_compressed.py25
3 files changed, 38 insertions, 129 deletions
diff --git a/cogs/downloader.py b/cogs/downloader.py
index c35373f..5fb3d1c 100644
--- a/cogs/downloader.py
+++ b/cogs/downloader.py
@@ -1,34 +1,19 @@
1import base64
2import os 1import os
3import os.path
4import tempfile 2import tempfile
3from pathlib import Path
5 4
6import discord 5import discord
7import requests
8import yt_dlp 6import yt_dlp
9from discord.ext import commands 7from discord.ext import commands
10from dotenv import load_dotenv 8from dotenv import load_dotenv
11 9
12# Load environment variables 10# Load environment variables
13load_dotenv() 11load_dotenv()
14PIXELDRAIN_API_KEY = os.getenv('PIXELDRAIN_API_KEY')
15
16
17def _get_auth_headers():
18 """Generate authentication headers for Pixeldrain API"""
19 if not PIXELDRAIN_API_KEY:
20 raise Exception("Pixeldrain API key not found in environment variables")
21
22 auth_string = f":{PIXELDRAIN_API_KEY}"
23 auth_bytes = auth_string.encode('ascii')
24 base64_auth = base64.b64encode(auth_bytes).decode('ascii')
25 return {"Authorization": f"Basic {base64_auth}"}
26 12
27 13
28class Downloader(commands.Cog): 14class Downloader(commands.Cog):
29 def __init__(self, bot): 15 def __init__(self, bot):
30 self.bot = bot 16 self.bot = bot
31 self.pixeldrain_url = "https://pixeldrain.com/api/file"
32 17
33 @commands.slash_command( 18 @commands.slash_command(
34 name="download", 19 name="download",
@@ -54,47 +39,14 @@ class Downloader(commands.Cog):
54 info = ydl.extract_info(url, download=True) 39 info = ydl.extract_info(url, download=True)
55 actual_filename = ydl.prepare_filename(info) 40 actual_filename = ydl.prepare_filename(info)
56 41
57 await ctx.followup.send("Video downloaded successfully, Uploading to pixeldrain...")
58 # upload to pixeldrain
59 try: 42 try:
60 with open(actual_filename, 'rb') as f: 43 file = discord.File(actual_filename)
61 files = {'file': f} 44 await ctx.followup.send("Pobran", file=file)
62 response = requests.post(
63 self.pixeldrain_url,
64 files=files,
65 headers={
66 "Authorization": f"Basic {base64.b64encode((':' + PIXELDRAIN_API_KEY).encode()).decode()}"}
67 )
68
69 try:
70 response_data = response.json()
71 print("Pixeldrain response:", response_data) # Debug log
72
73 if response.status_code == 201: # 201 means successful upload
74 file_id = response_data.get('id')
75 if file_id:
76 file_link = f"https://pixeldrain.com/u/{file_id}"
77 await ctx.followup.send(f"oto twoje videło\n {file_link}")
78 else:
79 await ctx.followup.send(
80 f"⚠️ Upload successful but no file ID returned. Response: {response_data}")
81 else:
82 error_msg = response_data.get('error', 'Unknown error')
83 if response.status_code == 401:
84 error_msg = "Invalid API key. Please check your PIXELDRAIN_API_KEY in .env file."
85 await ctx.followup.send(f"❌ Upload failed (Status {response.status_code}): {error_msg}")
86 except ValueError as e:
87 # If the response is not JSON
88 error_msg = f"Failed to parse server response: {str(e)}"
89 if response.text:
90 error_msg += f"\nResponse: {response.text[:200]}"
91 await ctx.followup.send(f"❌ {error_msg}")
92 except Exception as e: 45 except Exception as e:
93 await ctx.followup.send(f"Error: {str(e)}") 46 await ctx.followup.send(f":(\n{str(e)}")
94 # No need for explicit cleanup as a tempfile.TemporaryDirectory handles it automatically
95 47
96 except Exception as e: 48 except Exception as e:
97 await ctx.followup.send(f"Error: {str(e)}") 49 await ctx.followup.send(f":(\n{str(e)}")
98 50
99 51
100def setup(bot): 52def setup(bot):
diff --git a/cogs/music/play.py b/cogs/music/play.py
index b47de03..5d82127 100644
--- a/cogs/music/play.py
+++ b/cogs/music/play.py
@@ -12,7 +12,6 @@ yt_dlp.utils.bug_reports_message = lambda: ''
12class Play(commands.Cog): 12class Play(commands.Cog):
13 def __init__(self, bot): 13 def __init__(self, bot):
14 self.bot = bot 14 self.bot = bot
15 self.queues = {}
16 self.ydl_opts = { 15 self.ydl_opts = {
17 'format': 'bestaudio/best', 16 'format': 'bestaudio/best',
18 'postprocessors': [{ 17 'postprocessors': [{
@@ -27,34 +26,7 @@ class Play(commands.Cog):
27 'source_address': '0.0.0.0', 26 'source_address': '0.0.0.0',
28 } 27 }
29 28
30 def get_queue(self, guild_id): 29 async def play_audio(self, ctx, vc, url, title):
31 return self.queues.setdefault(guild_id, [])
32
33 async def play_next(self, ctx, vc, guild_id):
34 queue = self.get_queue(guild_id)
35 if queue:
36 title, url = queue[0]
37
38 def after_playing():
39 if queue:
40 queue.pop(0)
41 if queue:
42 next_title, next_url = queue[0]
43 if not vc.is_playing() and not vc.is_paused():
44 asyncio.run_coroutine_threadsafe(
45 self.play_audio(ctx, vc, next_url, next_title),
46 self.bot.loop
47 )
48 else:
49 asyncio.run_coroutine_threadsafe(
50 vc.disconnect(),
51 self.bot.loop
52 )
53
54 if not vc.is_playing() and not vc.is_paused():
55 await self.play_audio(ctx, vc, url, title, after=after_playing)
56
57 async def play_audio(self, ctx, vc, url, title, after=None):
58 try: 30 try:
59 with yt_dlp.YoutubeDL(self.ydl_opts) as ydl: 31 with yt_dlp.YoutubeDL(self.ydl_opts) as ydl:
60 info = await self.bot.loop.run_in_executor( 32 info = await self.bot.loop.run_in_executor(
@@ -71,14 +43,21 @@ class Play(commands.Cog):
71 'options': '-vn' 43 'options': '-vn'
72 } 44 }
73 45
46 def after_playing(error):
47 if error:
48 print(f'Player error: {error}')
49 coro = vc.disconnect()
50 fut = asyncio.run_coroutine_threadsafe(coro, self.bot.loop)
51 try:
52 fut.result()
53 except Exception as e:
54 print(f'Error disconnecting: {e}')
55
74 source = discord.FFmpegPCMAudio(url2, **ffmpeg_options) 56 source = discord.FFmpegPCMAudio(url2, **ffmpeg_options)
75 vc.play(source, after=after) 57 vc.play(source, after=after_playing)
76 await ctx.followup.send(f"gra: {title}") 58 await ctx.followup.send(f"gra: {title}")
77 except Exception as e: 59 except Exception as e:
78 await ctx.followup.send(f"Wystąpił błąd podczas odtwarzania: {str(e)}") 60 await ctx.followup.send(f"Wystąpił błąd podczas odtwarzania: {str(e)}")
79 # Try to play next in the queue if there's an error
80 if after:
81 after(None)
82 61
83 @commands.slash_command(name="grajcuj", description="grajcuj melodyje") 62 @commands.slash_command(name="grajcuj", description="grajcuj melodyje")
84 async def play(self, ctx, *, search: str): 63 async def play(self, ctx, *, search: str):
@@ -106,41 +85,10 @@ class Play(commands.Cog):
106 title = video['title'] 85 title = video['title']
107 url = video['link'] 86 url = video['link']
108 87
109 # Add to queue 88 # Play the audio directly
110 queue = self.get_queue(ctx.guild.id) 89 if vc.is_playing() or vc.is_paused():
111 queue.append((title, url)) 90 vc.stop()
112 91 await self.play_audio(ctx, vc, url, title)
113 # If nothing is playing, start playing
114 if not vc.is_playing() and not vc.is_paused():
115 await self.play_next(ctx, vc, ctx.guild.id)
116 else:
117 await ctx.followup.send(f"dodano do kolejki: {title}")
118
119 @commands.slash_command(name="stop", description="zatrzymaj odtwarzanie i wyczyść kolejkę")
120 async def stop(self, ctx):
121 if ctx.voice_client:
122 queue = self.get_queue(ctx.guild.id)
123 queue.clear()
124 await ctx.voice_client.disconnect()
125 await ctx.respond("Zatrzymano odtwarzanie i wyczyszczono kolejkę")
126 else:
127 await ctx.respond("Nie jestem połączony z kanałem głosowym")
128
129 @commands.slash_command(name="pauza", description="wstrzymaj odtwarzanie")
130 async def pause(self, ctx):
131 if ctx.voice_client and ctx.voice_client.is_playing():
132 ctx.voice_client.pause()
133 await ctx.respond("Wstrzymano odtwarzanie")
134 else:
135 await ctx.respond("Nic nie jest teraz odtwarzane")
136
137 @commands.slash_command(name="wznow", description="wznów odtwarzanie")
138 async def resume(self, ctx):
139 if ctx.voice_client and ctx.voice_client.is_paused():
140 ctx.voice_client.resume()
141 await ctx.respond("Wznowiono odtwarzanie")
142 else:
143 await ctx.respond("Nic nie jest teraz wstrzymane")
144 92
145 93
146def setup(bot): 94def setup(bot):
diff --git a/cogs/music/play_compressed.py b/cogs/music/play_compressed.py
index f14d75b..0d4901c 100644
--- a/cogs/music/play_compressed.py
+++ b/cogs/music/play_compressed.py
@@ -25,8 +25,8 @@ class GrajcujZkompresowane(commands.Cog):
25 @staticmethod 25 @staticmethod
26 def compress_audio(input_path): 26 def compress_audio(input_path):
27 base, ext = os.path.splitext(input_path) 27 base, ext = os.path.splitext(input_path)
28 output_path = f"{base}_compressed{ext}" 28 output_path = f"{base}_compressed.opus"
29 ffmpeg_command = f"ffmpeg -i {input_path} -ar 8000 -ac 1 -b:a 500 -acodec libmp3lame -q:a 9 {output_path}" 29 ffmpeg_command = f"ffmpeg -i {input_path} -ac 1 -b:a 500 -acodec libopus {output_path}"
30 subprocess.run(ffmpeg_command, check=True, shell=True) 30 subprocess.run(ffmpeg_command, check=True, shell=True)
31 return output_path 31 return output_path
32 32
@@ -57,7 +57,7 @@ class GrajcujZkompresowane(commands.Cog):
57 url = video['link'] 57 url = video['link']
58 filename = f"{video_id}.mp3" 58 filename = f"{video_id}.mp3"
59 file_path = os.path.join(music_dir, filename) 59 file_path = os.path.join(music_dir, filename)
60 compressed_file_path = os.path.join(music_dir, f"{video_id}_compressed.mp3") 60 compressed_file_path = os.path.join(music_dir, f"{video_id}_compressed.opus")
61 if os.path.exists(compressed_file_path): 61 if os.path.exists(compressed_file_path):
62 found_file = compressed_file_path 62 found_file = compressed_file_path
63 found_title = title 63 found_title = title
@@ -82,11 +82,20 @@ class GrajcujZkompresowane(commands.Cog):
82 found_file = compressed_file_path 82 found_file = compressed_file_path
83 found_title = title 83 found_title = title
84 title = found_title 84 title = found_title
85 if not vc.is_playing(): 85 def after_playing(error):
86 vc.play(discord.FFmpegPCMAudio(found_file)) 86 if error:
87 await ctx.followup.send(f"gra (zkompresowane): {title}") 87 print(f'Player error: {error}')
88 else: 88 coro = vc.disconnect()
89 await ctx.followup.send(f"dodano do koleyjki (zkompresowane): {title}") 89 fut = asyncio.run_coroutine_threadsafe(coro, self.bot.loop)
90 try:
91 fut.result()
92 except Exception as e:
93 print(f'Error disconnecting: {e}')
94
95 if vc.is_playing() or vc.is_paused():
96 vc.stop()
97 vc.play(discord.FFmpegPCMAudio(found_file), after=after_playing)
98 await ctx.followup.send(f"gra (zkompresowane): {title}")
90 99
91 100
92def setup(bot): 101def setup(bot):