aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/downloader.py
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-04-29 14:47:32 +0200
committersalmonik <raisersoft@proton.me>2026-04-29 14:47:32 +0200
commit8a4352ebb5e15ff4be82a9b4e111c1535aab349e (patch)
tree2c4d5b4b65bdc8308b35c411cffa7f17b1bfeb4d /cogs/downloader.py
parentfix: fallback to plaintext if no json is provided for assistant.py (diff)
parentproper context for settings (diff)
downloadsenator-sperma-8a4352ebb5e15ff4be82a9b4e111c1535aab349e.tar.gz
senator-sperma-8a4352ebb5e15ff4be82a9b4e111c1535aab349e.zip
Merge branch 'dev'
Signed-off-by: salmonik <raisersoft@proton.me>
Diffstat (limited to 'cogs/downloader.py')
-rw-r--r--cogs/downloader.py35
1 files changed, 30 insertions, 5 deletions
diff --git a/cogs/downloader.py b/cogs/downloader.py
index 36bd723..900bafb 100644
--- a/cogs/downloader.py
+++ b/cogs/downloader.py
@@ -12,6 +12,7 @@ import re
12import yt_dlp 12import yt_dlp
13from discord.ext import commands 13from discord.ext import commands
14import aiofiles 14import aiofiles
15from cogs.utils.url_helper import clean_url_for_ytdlp
15 16
16logger = logging.getLogger(__name__) 17logger = logging.getLogger(__name__)
17 18
@@ -61,6 +62,10 @@ class Downloader(commands.Cog):
61 file_data = response["content"] 62 file_data = response["content"]
62 await ctx.respond(file=discord.File(file_data)) 63 await ctx.respond(file=discord.File(file_data))
63 else: 64 else:
65 error_msg = response["content"]
66 if 'details' in response:
67 error_msg += f"\n{response['details']}"
68 await ctx.respond(f"Błąd: {error_msg}", ephemeral=True)
64 logger.error(f"Error: {response['content']}") 69 logger.error(f"Error: {response['content']}")
65 if 'details' in response: 70 if 'details' in response:
66 logger.error(f"Details: {response['details']}") 71 logger.error(f"Details: {response['details']}")
@@ -68,10 +73,11 @@ class Downloader(commands.Cog):
68 @staticmethod 73 @staticmethod
69 async def download_standalone(url: str, catbox: bool = False, fformat: str = "mp4", filename_user: str | None = None): 74 async def download_standalone(url: str, catbox: bool = False, fformat: str = "mp4", filename_user: str | None = None):
70 try: 75 try:
76 url = clean_url_for_ytdlp(url)
71 logger.info(f"Downloading {url} as {fformat}") 77 logger.info(f"Downloading {url} as {fformat}")
72 78
73 with tempfile.TemporaryDirectory(delete=False) as temp_dir: 79 with tempfile.TemporaryDirectory(delete=False) as temp_dir:
74 ydl_opts = Downloader._get_ydl_options(fformat, temp_dir) 80 ydl_opts = Downloader._get_ydl_options(filename_user, fformat, temp_dir)
75 81
76 with yt_dlp.YoutubeDL(ydl_opts) as ydl: 82 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
77 ydl.download([url]) 83 ydl.download([url])
@@ -87,15 +93,23 @@ class Downloader(commands.Cog):
87 return Downloader._create_error_response("Download failed", str(e), None) 93 return Downloader._create_error_response("Download failed", str(e), None)
88 94
89 @staticmethod 95 @staticmethod
90 def _get_ydl_options(fformat: str, temp_dir: str) -> dict: 96 def _sanitize_filename(name: str) -> str:
97 invalid = '<>:"/\\|?*'
98 for c in invalid:
99 name = name.replace(c, '')
100 return name.strip()
101
102 @staticmethod
103 def _get_ydl_options(filename: str = None, fformat: str = None, temp_dir: str = None) -> dict:
104 if filename:
105 filename = Downloader._sanitize_filename(filename)[:100]
91 ydl_opts = { 106 ydl_opts = {
92 'outtmpl': os.path.join(temp_dir, '%(title)s.%(ext)s'), 107 'outtmpl': os.path.join(temp_dir, filename if filename is not None else '%(title).100s.%(ext)s'),
93 'format': 'bestaudio/best' if fformat in ['mp3', 'wav', 'm4a'] else 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', 108 'format': 'bestaudio/best' if fformat in ['mp3', 'wav', 'm4a'] else 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
94 'merge_output_format': 'mp4', 109 'merge_output_format': 'mp4',
95 'postprocessors': [], 110 'postprocessors': [],
96 'remote-components': 'ejs:github', 111 'remote-components': 'ejs:github',
97 'js-runtimes': {'deno': {'path': '/usr/bin/deno'}}, 112 'js-runtimes': {'deno': {'path': '/usr/bin/deno'}},
98 'o': '"%(title)s.%(ext)s"'
99 } 113 }
100 114
101 if fformat in ['mp3', 'wav', 'm4a']: 115 if fformat in ['mp3', 'wav', 'm4a']:
@@ -120,10 +134,15 @@ class Downloader(commands.Cog):
120 134
121 actual_file = os.path.join(temp_dir, files[0]) 135 actual_file = os.path.join(temp_dir, files[0])
122 extension = actual_file.split('.')[-1] 136 extension = actual_file.split('.')[-1]
137 extension = Downloader._sanitize_filename(extension)
123 138
124 if not filename_user: 139 if not filename_user:
125 filename = os.path.basename(actual_file) 140 filename = os.path.basename(actual_file)
141 filename = Downloader._sanitize_filename(filename)
142 if len(filename) > 100:
143 filename = filename[:100]
126 else: 144 else:
145 filename_user = Downloader._sanitize_filename(filename_user)[:100]
127 filename = filename_user + '.' + extension 146 filename = filename_user + '.' + extension
128 actual_file = os.path.join(temp_dir, filename) 147 actual_file = os.path.join(temp_dir, filename)
129 148
@@ -144,12 +163,18 @@ class Downloader(commands.Cog):
144 files = {'f': (filename, content, 'application/octet-stream')} 163 files = {'f': (filename, content, 'application/octet-stream')}
145 headers = {'Cookie': f'cppwd={os.getenv("COPYPARTY_PASSWORD")}'} 164 headers = {'Cookie': f'cppwd={os.getenv("COPYPARTY_PASSWORD")}'}
146 params = {'j': '1', 'ck': 'b2'} 165 params = {'j': '1', 'ck': 'b2'}
147 base_url = "https://catbox.2137697.xyz/sperma/" 166 base_url = os.getenv("COPYPARTY_URL_UPLOAD")
148 167
149 response = requests.post(base_url, files=files, headers=headers, params=params) 168 response = requests.post(base_url, files=files, headers=headers, params=params)
150 169
151 if response.status_code in [200, 201]: 170 if response.status_code in [200, 201]:
152 return Downloader._handle_upload_success(response, filename, temp_dir) 171 return Downloader._handle_upload_success(response, filename, temp_dir)
172 elif response.status_code == 413:
173 return Downloader._create_error_response(
174 "File too large for upload",
175 "Plik jest za duży, by wysłać go na serwer (limit to ok. 100MB)",
176 temp_dir
177 )
153 else: 178 else:
154 return Downloader._create_error_response( 179 return Downloader._create_error_response(
155 f"Server returned {response.status_code}", 180 f"Server returned {response.status_code}",