diff options
| author | salmonik <raisersoft@proton.me> | 2026-01-03 20:43:11 +0100 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-01-03 20:43:11 +0100 |
| commit | b33c4729d3b12fdbbb3f675ca88b44925debd9ae (patch) | |
| tree | 744d98f10341784fc634d4f08415744a189c9848 | |
| parent | simplified the searching algorithm (diff) | |
| download | senator-sperma-b33c4729d3b12fdbbb3f675ca88b44925debd9ae.tar.gz senator-sperma-b33c4729d3b12fdbbb3f675ca88b44925debd9ae.zip | |
fixed compressed play
| -rw-r--r-- | cogs/music/play.py | 77 | ||||
| -rw-r--r-- | cogs/music/play_utils.py | 60 |
2 files changed, 120 insertions, 17 deletions
diff --git a/cogs/music/play.py b/cogs/music/play.py index 74b9e4f..8390ff5 100644 --- a/cogs/music/play.py +++ b/cogs/music/play.py | |||
| @@ -48,15 +48,78 @@ class Play(commands.Cog): | |||
| 48 | else: | 48 | else: |
| 49 | await ctx.respond("Nie znaleziono pliku do odtworzenia", ephemeral=True) | 49 | await ctx.respond("Nie znaleziono pliku do odtworzenia", ephemeral=True) |
| 50 | 50 | ||
| 51 | @discord.slash_command(name="grajcuj_zkompresowane", description="grajcujmy wszyscy w wysokiej jakosci!") | ||
| 52 | async def play_compressed( | ||
| 53 | self, | ||
| 54 | ctx: discord.ApplicationContext, | ||
| 55 | query: str = discord.Option(str, "co zagrać??", required=True), | ||
| 56 | source: str = discord.Option(str, "skąd zagrać??", required=True, | ||
| 57 | choices=["local", "soundcloud", "youtube"]) | ||
| 58 | ): | ||
| 59 | await ctx.defer(ephemeral=True) | ||
| 60 | if source == "local": | ||
| 61 | candidates = await play_utils.PlayUtils(self.bot).search_local(query) | ||
| 62 | if candidates: | ||
| 63 | embed = discord.Embed(title="Wyniki wyszukiwania", description="Wybierz plik do odtworzenia:", | ||
| 64 | color=discord.Color.blue()) | ||
| 65 | view = discord.ui.View(disable_on_timeout=True) | ||
| 66 | for i, candidate in enumerate(candidates, start=1): | ||
| 67 | filename = os.path.basename(candidate) | ||
| 68 | metadata = None | ||
| 69 | if os.path.splitext(filename)[1].lower() in ['.mp3', '.wav', '.opus']: | ||
| 70 | metadata = mutagen.File(candidate) | ||
| 71 | title = metadata.get('title', None) | ||
| 72 | if metadata and title: | ||
| 73 | embed.add_field(name=f"{i}. {title}", value="\u200b", inline=False) | ||
| 74 | else: | ||
| 75 | embed.add_field(name=f"{i}. {filename}", value="\u200b", inline=False) | ||
| 76 | button = discord.ui.Button(label=f"Play {i}") | ||
| 51 | 77 | ||
| 78 | async def button_callback(interaction: discord.Interaction, candidate=candidate): | ||
| 79 | await interaction.response.defer(ephemeral=True) | ||
| 80 | try: | ||
| 81 | await ctx.interaction.delete_original_response() | ||
| 82 | # Compress the file before playing | ||
| 83 | compressed_path = await play_utils.PlayUtils(self.bot).compress(ctx, candidate) | ||
| 84 | if compressed_path: | ||
| 85 | try: | ||
| 86 | await play_utils.PlayUtils(self.bot).play(ctx, compressed_path, delete_after_play=True) | ||
| 87 | except Exception as e: | ||
| 88 | # Clean up the compressed file if play fails | ||
| 89 | if os.path.exists(compressed_path): | ||
| 90 | try: | ||
| 91 | os.remove(compressed_path) | ||
| 92 | logger.info(f"Cleaned up temporary file after play error: {compressed_path}") | ||
| 93 | except Exception as cleanup_error: | ||
| 94 | logger.error(f"Error cleaning up file {compressed_path}: {str(cleanup_error)}") | ||
| 95 | raise e | ||
| 96 | except Exception as e: | ||
| 97 | logger.error(f"Error in play_compressed: {str(e)}", exc_info=True) | ||
| 98 | await ctx.respond(f"Error playing compressed file: {str(e)}", ephemeral=True) | ||
| 52 | 99 | ||
| 53 | @discord.slash_command(name="grajcuj_zkompresowane", description="grajcujmy wszyscy w wysokiej jakosci!") | 100 | button.callback = button_callback |
| 54 | async def play_compressed(self, ctx: discord.ApplicationContext, url: str = discord.Option(str, "co zagrać??", required=True)): | 101 | view.add_item(button) |
| 55 | await ctx.defer() | 102 | await ctx.respond(embed=embed, view=view, ephemeral=True) |
| 56 | url, title = await play_utils.PlayUtils(self.bot).get_url(ctx, url) | 103 | else: |
| 57 | filename = await play_utils.PlayUtils(self.bot).download(ctx, url) | 104 | await ctx.respond("Nie znaleziono pliku do odtworzenia", ephemeral=True) |
| 58 | filename = await play_utils.PlayUtils(self.bot).compress(ctx, filename) | 105 | else: |
| 59 | await play_utils.PlayUtils(self.bot).play(ctx, filename, title) | 106 | # For YouTube/SoundCloud |
| 107 | try: | ||
| 108 | url, title = await play_utils.PlayUtils(self.bot).get_url(ctx, query) | ||
| 109 | if not url: | ||
| 110 | return | ||
| 111 | |||
| 112 | filename = await play_utils.PlayUtils(self.bot).download(ctx, url) | ||
| 113 | if not filename: | ||
| 114 | return | ||
| 115 | |||
| 116 | # Compress the downloaded file | ||
| 117 | compressed_filename = await play_utils.PlayUtils(self.bot).compress(ctx, filename) | ||
| 118 | if compressed_filename: | ||
| 119 | await play_utils.PlayUtils(self.bot).play(ctx, compressed_filename, title) | ||
| 120 | except Exception as e: | ||
| 121 | logger.error(f"Error in play_compressed: {str(e)}") | ||
| 122 | await ctx.respond(f"Error: {str(e)}", ephemeral=True) | ||
| 60 | 123 | ||
| 61 | @discord.slash_command(name="grajcuj_plik", description="grajcuj plik") | 124 | @discord.slash_command(name="grajcuj_plik", description="grajcuj plik") |
| 62 | async def play_file(self, ctx: discord.ApplicationContext, attachment: discord.Attachment = discord.Option(discord.Attachment, "co zagrać??", required=True)): | 125 | async def play_file(self, ctx: discord.ApplicationContext, attachment: discord.Attachment = discord.Option(discord.Attachment, "co zagrać??", required=True)): |
diff --git a/cogs/music/play_utils.py b/cogs/music/play_utils.py index 6fa0edd..b3d81a8 100644 --- a/cogs/music/play_utils.py +++ b/cogs/music/play_utils.py | |||
| @@ -108,30 +108,70 @@ class PlayUtils: | |||
| 108 | async def compress(ctx, filename): | 108 | async def compress(ctx, filename): |
| 109 | if not filename: | 109 | if not filename: |
| 110 | await ctx.respond("dzie wideło", ephemeral=True) | 110 | await ctx.respond("dzie wideło", ephemeral=True) |
| 111 | return | 111 | return None |
| 112 | 112 | ||
| 113 | ffmpeg_command = f"ffmpeg -i {filename} -ac 1 -b:a 500 -acodec libopus {filename}" | 113 | # Create temp directory if it doesn't exist |
| 114 | temp_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'temp', 'compressed') | ||
| 115 | os.makedirs(temp_dir, exist_ok=True) | ||
| 116 | |||
| 117 | # Create a temporary output filename in the temp directory | ||
| 118 | base_name = os.path.basename(filename) | ||
| 119 | output_filename = os.path.join(temp_dir, f"{os.path.splitext(base_name)[0]}_compressed.opus") | ||
| 120 | |||
| 121 | # Ensure the output directory exists | ||
| 122 | os.makedirs(os.path.dirname(output_filename) or '.', exist_ok=True) | ||
| 123 | |||
| 124 | # Use proper quoting for filenames with spaces | ||
| 125 | ffmpeg_command = [ | ||
| 126 | 'ffmpeg', | ||
| 127 | '-y', # Overwrite output file if it exists | ||
| 128 | '-i', filename, | ||
| 129 | '-ac', '1', # Mono audio | ||
| 130 | '-b:a', '500', # 500k bitrate | ||
| 131 | '-acodec', 'libopus', | ||
| 132 | output_filename | ||
| 133 | ] | ||
| 134 | |||
| 114 | try: | 135 | try: |
| 115 | process = await asyncio.create_subprocess_shell( | 136 | logger.info(f"Running FFmpeg command: {' '.join(ffmpeg_command)}") |
| 116 | ffmpeg_command, | 137 | process = await asyncio.create_subprocess_exec( |
| 138 | *ffmpeg_command, | ||
| 117 | stdout=asyncio.subprocess.PIPE, | 139 | stdout=asyncio.subprocess.PIPE, |
| 118 | stderr=asyncio.subprocess.PIPE | 140 | stderr=asyncio.subprocess.PIPE |
| 119 | ) | 141 | ) |
| 142 | |||
| 120 | stdout, stderr = await process.communicate() | 143 | stdout, stderr = await process.communicate() |
| 144 | |||
| 121 | if process.returncode != 0: | 145 | if process.returncode != 0: |
| 122 | logger.error(f"FFmpeg error: {stderr.decode()}") | 146 | error_msg = stderr.decode() |
| 147 | logger.error(f"FFmpeg error ({process.returncode}): {error_msg}") | ||
| 123 | await ctx.respond("eror kompresujync pilk", ephemeral=True) | 148 | await ctx.respond("eror kompresujync pilk", ephemeral=True) |
| 124 | else: | 149 | return None |
| 125 | logger.info(f"Compressed file: {filename}") | 150 | |
| 151 | if not os.path.exists(output_filename): | ||
| 152 | logger.error(f"Output file was not created: {output_filename}") | ||
| 153 | await ctx.respond("eror kompresujync pilk - output file not created", ephemeral=True) | ||
| 154 | return None | ||
| 155 | |||
| 156 | logger.info(f"Successfully compressed file: {output_filename}") | ||
| 157 | return output_filename | ||
| 158 | |||
| 126 | except Exception as e: | 159 | except Exception as e: |
| 127 | logger.error(f"Error compressing file: {e}") | 160 | logger.error(f"Error compressing file: {str(e)}", exc_info=True) |
| 128 | await ctx.respond("eror kompresujync pilk", ephemeral=True) | 161 | await ctx.respond(f"eror kompresujync pilk: {str(e)}", ephemeral=True) |
| 162 | return None | ||
| 129 | 163 | ||
| 130 | @staticmethod | 164 | @staticmethod |
| 131 | async def play(ctx, filepath): | 165 | async def play(ctx, filepath, delete_after_play=False): |
| 132 | # Check if user is in a voice channel | 166 | # Check if user is in a voice channel |
| 133 | if not ctx.author.voice or not ctx.author.voice.channel: | 167 | if not ctx.author.voice or not ctx.author.voice.channel: |
| 134 | await ctx.respond("Musisz być na kanale głosowym, żebym mógł dołączyć!", ephemeral=True) | 168 | await ctx.respond("Musisz być na kanale głosowym, żebym mógł dołączyć!", ephemeral=True) |
| 169 | if delete_after_play and os.path.exists(filepath): | ||
| 170 | try: | ||
| 171 | os.remove(filepath) | ||
| 172 | logger.info(f"Cleaned up temporary file: {filepath}") | ||
| 173 | except Exception as e: | ||
| 174 | logger.error(f"Error cleaning up file {filepath}: {str(e)}") | ||
| 135 | return | 175 | return |
| 136 | 176 | ||
| 137 | logger.info(f"Attempting to play: {filepath}") | 177 | logger.info(f"Attempting to play: {filepath}") |
