diff options
Diffstat (limited to 'cogs/downloader.py')
| -rw-r--r-- | cogs/downloader.py | 101 |
1 files changed, 83 insertions, 18 deletions
diff --git a/cogs/downloader.py b/cogs/downloader.py index 7b338e9..e678575 100644 --- a/cogs/downloader.py +++ b/cogs/downloader.py | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | import os | 1 | import os |
| 2 | import tempfile | 2 | import tempfile |
| 3 | import logging | 3 | import logging |
| 4 | 4 | import requests | |
| 5 | import discord | 5 | import discord |
| 6 | import yt_dlp | 6 | import yt_dlp |
| 7 | from discord.ext import commands | 7 | from discord.ext import commands |
| @@ -19,37 +19,102 @@ class Downloader(commands.Cog): | |||
| 19 | 19 | ||
| 20 | @commands.slash_command( | 20 | @commands.slash_command( |
| 21 | name="download", | 21 | name="download", |
| 22 | description="download video from internet", | 22 | description="Download and convert video/audio from internet" |
| 23 | ) | 23 | ) |
| 24 | async def download( | 24 | async def download( |
| 25 | self, | 25 | self, |
| 26 | ctx: discord.ApplicationContext, | 26 | ctx: discord.ApplicationContext, |
| 27 | url: discord.Option(str, "url", required=True) | 27 | url: discord.Option(str, "URL of the video to download", required=True), |
| 28 | fformat: discord.Option(str, "Output format (mp4, mp3, wav, etc.)", | ||
| 29 | required=False, | ||
| 30 | default="mp4") | ||
| 28 | ): | 31 | ): |
| 32 | """Download and convert media from a URL to the specified format""" | ||
| 29 | await ctx.defer() | 33 | await ctx.defer() |
| 30 | try: | 34 | try: |
| 31 | logger.info(f"Downloading {url}") | 35 | logger.info(f"Downloading {url} as {fformat}") |
| 32 | # Create a temporary directory | 36 | |
| 33 | with tempfile.TemporaryDirectory() as temp_dir: | 37 | with tempfile.TemporaryDirectory() as temp_dir: |
| 34 | # Configure yt-dlp to use the temp directory | 38 | base_filename = os.path.join(temp_dir, 'output') |
| 35 | outtmpl = os.path.join(temp_dir, '%(title)s.%(ext)s') | 39 | input_file = f"{base_filename}.%(ext)s" |
| 40 | output_file = f"{base_filename}.{fformat}" | ||
| 41 | |||
| 42 | # Configure yt-dlp | ||
| 36 | ydl_opts = { | 43 | ydl_opts = { |
| 37 | 'outtmpl': outtmpl, | 44 | 'outtmpl': input_file, |
| 45 | 'format': 'bestaudio/best' if fformat in ['mp3', 'wav', 'm4a'] else 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', | ||
| 38 | 'merge_output_format': 'mp4', | 46 | 'merge_output_format': 'mp4', |
| 47 | 'postprocessors': [], | ||
| 39 | } | 48 | } |
| 49 | |||
| 50 | # Add post-processing for audio formats | ||
| 51 | if fformat in ['mp3', 'wav', 'm4a']: | ||
| 52 | ydl_opts['postprocessors'].append({ | ||
| 53 | 'key': 'FFmpegExtractAudio', | ||
| 54 | 'preferredcodec': fformat, | ||
| 55 | 'preferredquality': '192', | ||
| 56 | }) | ||
| 57 | elif fformat != 'mp4': # For other video formats | ||
| 58 | ydl_opts['postprocessors'].append({ | ||
| 59 | 'key': 'FFmpegVideoConvertor', | ||
| 60 | 'preferedformat': fformat, | ||
| 61 | }) | ||
| 40 | 62 | ||
| 41 | with yt_dlp.YoutubeDL(ydl_opts) as ydl: | 63 | with yt_dlp.YoutubeDL(ydl_opts) as ydl: |
| 42 | info = ydl.extract_info(url, download=True) | 64 | ydl.download([url]) |
| 43 | actual_filename = ydl.prepare_filename(info) | 65 | |
| 44 | 66 | # Find the downloaded file (yt-dlp might add a number if filename exists) | |
| 45 | try: | 67 | actual_file = None |
| 46 | file = discord.File(actual_filename) | 68 | for file in os.listdir(temp_dir): |
| 47 | await ctx.followup.send("Pobran", file=file) | 69 | if file.startswith('output') and file.endswith(fformat): |
| 48 | logger.info(f"File downloaded: {actual_filename}") | 70 | actual_file = os.path.join(temp_dir, file) |
| 49 | except Exception as e: | 71 | break |
| 50 | await ctx.followup.send(f":(\n{str(e)}") | 72 | |
| 51 | logger.error(f"Error in download command: {e}", exc_info=True) | 73 | if not actual_file or not os.path.exists(actual_file): |
| 74 | raise Exception(f"{fformat} ze mno wygroł...") | ||
| 52 | 75 | ||
| 76 | # Check file size and handle accordingly | ||
| 77 | file_size = os.path.getsize(actual_file) | ||
| 78 | if file_size < 10 * 1024 * 1024: # Under 10MB | ||
| 79 | file = discord.File(actual_file, filename=f"output.{fformat}") | ||
| 80 | await ctx.followup.send("pobran", file=file) | ||
| 81 | else: # 10MB or larger - upload to Pixeldrain | ||
| 82 | try: | ||
| 83 | # Get file info | ||
| 84 | filename = f"output.{fformat}" | ||
| 85 | file_size_mb = file_size / (1024 * 1024) | ||
| 86 | |||
| 87 | # Upload to Litterbox Catbox | ||
| 88 | with open(actual_file, 'rb') as f: | ||
| 89 | files = { | ||
| 90 | 'reqtype': (None, 'fileupload'), | ||
| 91 | 'time': (None, '24h'), | ||
| 92 | 'fileToUpload': (filename, f, 'application/octet-stream') | ||
| 93 | } | ||
| 94 | |||
| 95 | await ctx.followup.send(f"plik jest {file_size_mb:.1f} megabajtów... wysyłanie do gorzowa...") | ||
| 96 | |||
| 97 | response = requests.post( | ||
| 98 | 'https://litterbox.catbox.moe/resources/internals/api.php', | ||
| 99 | files=files | ||
| 100 | ) | ||
| 101 | |||
| 102 | if response.status_code == 200 and response.text.startswith('http'): | ||
| 103 | dl_url = response.text.strip() | ||
| 104 | await ctx.followup.send( | ||
| 105 | f"wysyłon\n" | ||
| 106 | f"pobrań: {dl_url}\n" | ||
| 107 | ) | ||
| 108 | else: | ||
| 109 | error_msg = response.text if response.text else 'Unknown error' | ||
| 110 | await ctx.followup.send(f"nie udało się wysłać pliku: {error_msg}") | ||
| 111 | |||
| 112 | except Exception as upload_error: | ||
| 113 | await ctx.followup.send(f"litterbox mnie nienawidzi :cccc\n {str(upload_error)}") | ||
| 114 | logger.error(f"litterbox upload error: {upload_error}", exc_info=True) | ||
| 115 | |||
| 116 | logger.info(f"File processed: {actual_file} ({file_size} bytes)") | ||
| 117 | |||
| 53 | except Exception as e: | 118 | except Exception as e: |
| 54 | await ctx.followup.send(f":(\n{str(e)}") | 119 | await ctx.followup.send(f":(\n{str(e)}") |
| 55 | logger.error(f"Error in download command: {e}", exc_info=True) | 120 | logger.error(f"Error in download command: {e}", exc_info=True) |
