diff options
| -rw-r--r-- | cogs/compression.py | 11 | ||||
| -rw-r--r-- | cogs/downloader.py | 129 |
2 files changed, 86 insertions, 54 deletions
diff --git a/cogs/compression.py b/cogs/compression.py index 2ee36bb..db47d46 100644 --- a/cogs/compression.py +++ b/cogs/compression.py | |||
| @@ -24,6 +24,17 @@ class Compression(commands.Cog): | |||
| 24 | def __init__(self, bot): | 24 | def __init__(self, bot): |
| 25 | self.bot = bot | 25 | self.bot = bot |
| 26 | 26 | ||
| 27 | @commands.message_command( | ||
| 28 | name="kompresja", | ||
| 29 | description="skompresuj wideło albo dźwienk :)", | ||
| 30 | ) | ||
| 31 | async def message_compression(self, ctx, message: discord.Message): | ||
| 32 | if message.attachments: | ||
| 33 | for attachment in message.attachments: | ||
| 34 | await self.compression(ctx, attachment) | ||
| 35 | else: | ||
| 36 | await ctx.respond("Brak załączników w wiadomości", ephemeral=True) | ||
| 37 | |||
| 27 | @commands.slash_command( | 38 | @commands.slash_command( |
| 28 | name="kompresja", | 39 | name="kompresja", |
| 29 | description="skompresuj wideło albo dźwienk :)", | 40 | description="skompresuj wideło albo dźwienk :)", |
diff --git a/cogs/downloader.py b/cogs/downloader.py index e678575..251a9af 100644 --- a/cogs/downloader.py +++ b/cogs/downloader.py | |||
| @@ -3,6 +3,7 @@ import tempfile | |||
| 3 | import logging | 3 | import logging |
| 4 | import requests | 4 | import requests |
| 5 | import discord | 5 | import discord |
| 6 | import re | ||
| 6 | import yt_dlp | 7 | import yt_dlp |
| 7 | from discord.ext import commands | 8 | from discord.ext import commands |
| 8 | from dotenv import load_dotenv | 9 | from dotenv import load_dotenv |
| @@ -17,6 +18,23 @@ class Downloader(commands.Cog): | |||
| 17 | def __init__(self, bot): | 18 | def __init__(self, bot): |
| 18 | self.bot = bot | 19 | self.bot = bot |
| 19 | 20 | ||
| 21 | URL_PATTERN = re.compile( | ||
| 22 | r'https://(?:[A-Za-z0-9-]+\.)*[A-Za-z0-9-]{1,63}\.[A-Za-z]{2,63}/\S*' | ||
| 23 | ) | ||
| 24 | |||
| 25 | @commands.message_command( | ||
| 26 | name="download", | ||
| 27 | description="Download and convert video/audio from internet" | ||
| 28 | ) | ||
| 29 | async def message_download(self, ctx, message: discord.Message): | ||
| 30 | # check if message has a valid url | ||
| 31 | url = [m.group(0) for m in self.URL_PATTERN.finditer(message.content)] | ||
| 32 | if url: | ||
| 33 | for url in url: | ||
| 34 | await self.download(ctx, url, "mp4") | ||
| 35 | else: | ||
| 36 | await ctx.respond("Brak załączników w wiadomości", ephemeral=True) | ||
| 37 | |||
| 20 | @commands.slash_command( | 38 | @commands.slash_command( |
| 21 | name="download", | 39 | name="download", |
| 22 | description="Download and convert video/audio from internet" | 40 | description="Download and convert video/audio from internet" |
| @@ -35,13 +53,9 @@ class Downloader(commands.Cog): | |||
| 35 | logger.info(f"Downloading {url} as {fformat}") | 53 | logger.info(f"Downloading {url} as {fformat}") |
| 36 | 54 | ||
| 37 | with tempfile.TemporaryDirectory() as temp_dir: | 55 | with tempfile.TemporaryDirectory() as temp_dir: |
| 38 | base_filename = os.path.join(temp_dir, 'output') | 56 | # Configure yt-dlp to use the original filename |
| 39 | input_file = f"{base_filename}.%(ext)s" | ||
| 40 | output_file = f"{base_filename}.{fformat}" | ||
| 41 | |||
| 42 | # Configure yt-dlp | ||
| 43 | ydl_opts = { | 57 | ydl_opts = { |
| 44 | 'outtmpl': input_file, | 58 | 'outtmpl': os.path.join(temp_dir, '%(title)s.%(ext)s'), |
| 45 | 'format': 'bestaudio/best' if fformat in ['mp3', 'wav', 'm4a'] else 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', | 59 | 'format': 'bestaudio/best' if fformat in ['mp3', 'wav', 'm4a'] else 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', |
| 46 | 'merge_output_format': 'mp4', | 60 | 'merge_output_format': 'mp4', |
| 47 | 'postprocessors': [], | 61 | 'postprocessors': [], |
| @@ -63,57 +77,64 @@ class Downloader(commands.Cog): | |||
| 63 | with yt_dlp.YoutubeDL(ydl_opts) as ydl: | 77 | with yt_dlp.YoutubeDL(ydl_opts) as ydl: |
| 64 | ydl.download([url]) | 78 | ydl.download([url]) |
| 65 | 79 | ||
| 66 | # Find the downloaded file (yt-dlp might add a number if filename exists) | 80 | # Find the downloaded file (should be the only file in the temp directory) |
| 67 | actual_file = None | 81 | files = [f for f in os.listdir(temp_dir) if os.path.isfile(os.path.join(temp_dir, f))] |
| 68 | for file in os.listdir(temp_dir): | 82 | if not files: |
| 69 | if file.startswith('output') and file.endswith(fformat): | 83 | raise Exception(f"No file was downloaded") |
| 70 | actual_file = os.path.join(temp_dir, file) | 84 | |
| 71 | break | 85 | actual_file = os.path.join(temp_dir, files[0]) |
| 72 | 86 | if not os.path.exists(actual_file): | |
| 73 | if not actual_file or not os.path.exists(actual_file): | 87 | raise Exception(f"Downloaded file not found: {actual_file}") |
| 74 | raise Exception(f"{fformat} ze mno wygroł...") | ||
| 75 | 88 | ||
| 76 | # Check file size and handle accordingly | 89 | try: |
| 77 | file_size = os.path.getsize(actual_file) | 90 | # Get file info |
| 78 | if file_size < 10 * 1024 * 1024: # Under 10MB | 91 | filename = f"output.{fformat}" |
| 79 | file = discord.File(actual_file, filename=f"output.{fformat}") | 92 | |
| 80 | await ctx.followup.send("pobran", file=file) | 93 | # Upload to Copyparty |
| 81 | else: # 10MB or larger - upload to Pixeldrain | 94 | with open(actual_file, 'rb') as f: |
| 82 | try: | 95 | files = { |
| 83 | # Get file info | 96 | 'f': (filename, f, 'application/octet-stream') |
| 84 | filename = f"output.{fformat}" | 97 | } |
| 85 | file_size_mb = file_size / (1024 * 1024) | 98 | headers = { |
| 86 | 99 | 'Cookie': f'cppwd={os.getenv("COPYPARTY_PASSWORD")}' | |
| 87 | # Upload to Litterbox Catbox | 100 | } |
| 88 | with open(actual_file, 'rb') as f: | 101 | params = { |
| 89 | files = { | 102 | 'j': '1', # Return JSON response |
| 90 | 'reqtype': (None, 'fileupload'), | 103 | 'ck': 'b2' # Use blake2b checksum |
| 91 | 'time': (None, '24h'), | 104 | } |
| 92 | 'fileToUpload': (filename, f, 'application/octet-stream') | 105 | |
| 93 | } | 106 | # Ensure the URL ends with a single slash |
| 94 | 107 | base_url = "https://catbox.2137697.xyz/sperma/" | |
| 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 | 108 | ||
| 102 | if response.status_code == 200 and response.text.startswith('http'): | 109 | response = requests.post( |
| 103 | dl_url = response.text.strip() | 110 | base_url, |
| 104 | await ctx.followup.send( | 111 | files=files, |
| 105 | f"wysyłon\n" | 112 | headers=headers, |
| 106 | f"pobrań: {dl_url}\n" | 113 | params=params |
| 107 | ) | 114 | ) |
| 108 | else: | 115 | |
| 109 | error_msg = response.text if response.text else 'Unknown error' | 116 | if response.status_code == 200 or response.status_code == 201: |
| 110 | await ctx.followup.send(f"nie udało się wysłać pliku: {error_msg}") | 117 | try: |
| 111 | 118 | result = response.json() | |
| 112 | except Exception as upload_error: | 119 | if 'fileurl' in result: |
| 113 | await ctx.followup.send(f"litterbox mnie nienawidzi :cccc\n {str(upload_error)}") | 120 | dl_url = result['fileurl'] |
| 114 | logger.error(f"litterbox upload error: {upload_error}", exc_info=True) | 121 | await ctx.followup.send( |
| 122 | f"wysyłon\n" | ||
| 123 | f"{dl_url}\n" | ||
| 124 | ) | ||
| 125 | else: | ||
| 126 | await ctx.followup.send(f"Odpowiedź serwera nie zawiera wymaganych danych: {result}") | ||
| 127 | except ValueError: | ||
| 128 | await ctx.followup.send(f"Nieprawidłowa odpowiedź z serwera: {response.text}") | ||
| 129 | else: | ||
| 130 | error_msg = response.text if response.text else 'Unknown error' | ||
| 131 | await ctx.followup.send(f"nie udało się wysłać pliku (HTTP {response.status_code}): {error_msg}") | ||
| 132 | |||
| 133 | except Exception as upload_error: | ||
| 134 | await ctx.followup.send(f"copyparty mnie nienawidzi :cccc\n {str(upload_error)}") | ||
| 135 | logger.error(f"copyparty upload error: {upload_error}", exc_info=True) | ||
| 115 | 136 | ||
| 116 | logger.info(f"File processed: {actual_file} ({file_size} bytes)") | 137 | logger.info(f"File processed: {actual_file}") |
| 117 | 138 | ||
| 118 | except Exception as e: | 139 | except Exception as e: |
| 119 | await ctx.followup.send(f":(\n{str(e)}") | 140 | await ctx.followup.send(f":(\n{str(e)}") |
