aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/conversion.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cogs/conversion.py181
1 files changed, 97 insertions, 84 deletions
diff --git a/cogs/conversion.py b/cogs/conversion.py
index 11f4f1b..f61d30f 100644
--- a/cogs/conversion.py
+++ b/cogs/conversion.py
@@ -8,8 +8,10 @@ import requests
8from discord.ext import commands 8from discord.ext import commands
9import logging 9import logging
10import os 10import os
11import subprocess 11import asyncio
12import aiofiles
12import mimetypes 13import mimetypes
14import subprocess
13 15
14logger = logging.getLogger(__name__) 16logger = logging.getLogger(__name__)
15 17
@@ -28,108 +30,119 @@ class Conversion(commands.Cog):
28 def __init__(self, bot): 30 def __init__(self, bot):
29 self.bot = bot 31 self.bot = bot
30 32
31 @commands.slash_command(name="konwersja", description="konwertuj plik na inny format") 33 async def _setup_file_paths(self, plik, output_format):
32 @discord.option( 34 """Setup input and output file paths"""
33 "plik",
34 description="plik do konwersji",
35 required=True,
36 type=discord.Attachment
37 )
38 @discord.option(
39 "format",
40 description="format konwersji",
41 required=True,
42 type=str
43 )
44 async def convert(self, ctx, plik, output_format, args):
45 await ctx.defer()
46 # Save files to the temp directory inside the bot's root directory
47 bot_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 35 bot_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
48 temp_dir = os.path.join(bot_dir, "temp") 36 temp_dir = os.path.join(bot_dir, "temp")
49 if not os.path.exists(temp_dir): 37 if not os.path.exists(temp_dir):
50 os.makedirs(temp_dir) 38 os.makedirs(temp_dir)
39
51 file_path = os.path.join(temp_dir, plik.filename) 40 file_path = os.path.join(temp_dir, plik.filename)
52 filename_noext = os.path.splitext(plik.filename)[0] 41 filename_noext = os.path.splitext(plik.filename)[0]
53 await plik.save(file_path) 42 await plik.save(file_path)
54 43
55 input_path = file_path 44 input_path = file_path
56 output_path = os.path.join(temp_dir, f"{filename_noext}k.{output_format}") 45 output_path = os.path.join(temp_dir, f"{filename_noext}k.{output_format}")
57 file_type = filetype(file_path) 46 return input_path, output_path
58 logger.info(f"Conversion started for: {file_type}") 47
59 if file_type == "Video" or file_type == "Audio": 48 def _build_conversion_command(self, file_type, input_path, output_path, args):
60 # Execute ffmpeg command to compress video 49 """Build the appropriate conversion command based on file type"""
61 ffmpeg_command = f"ffmpeg -i {input_path} {args} {output_path}" 50 if file_type in ["Video", "Audio"]:
51 return f"ffmpeg -i {input_path} {args} {output_path}"
62 elif file_type == "Image": 52 elif file_type == "Image":
63 img_command = f"magick {input_path} {args} {output_path}" 53 return f"magick {input_path} {args} {output_path}"
64 ffmpeg_command = img_command
65 else: 54 else:
66 await ctx.respond("Plik jest nieobsługiwany", ephemeral=True) 55 return None
67 logger.info("Unsupported file type")
68 return
69 56
57 async def _upload_to_copyparty(self, output_path):
58 """Upload file to copyparty and return download URL"""
70 try: 59 try:
71 subprocess.run(ffmpeg_command, check=True, shell=True) 60 async with aiofiles.open(output_path, 'rb') as f:
72 # Upload the compressed file 61 files = {
73 if os.path.getsize(output_path) > 1024*1024*10: 62 'f': (output_path, f, 'application/octet-stream')
74 try: 63 }
64 headers = {
65 'Cookie': f'cppwd={os.getenv("COPYPARTY_PASSWORD")}'
66 }
67 params = {
68 'j': '1',
69 'ck': 'b2'
70 }
71
72 base_url = "https://catbox.2137697.xyz/sperma/"
73 response = requests.post(base_url, files=files, headers=headers, params=params)
74
75 if response.status_code in [200, 201]:
76 result = response.json()
77 if 'fileurl' in result:
78 return result['fileurl']
79 else:
80 raise ValueError(f"Server response missing fileurl: {result}")
81 else:
82 error_msg = response.text if response.text else 'Unknown error'
83 raise requests.RequestException(f"HTTP {response.status_code}: {error_msg}")
84
85 except Exception as e:
86 logger.error(f"copyparty upload error: {e}", exc_info=True)
87 raise
75 88
76 # Upload to Copyparty 89 async def _handle_file_output(self, ctx, output_path):
77 with open(output_path, 'rb') as f: 90 """Handle file output based on size"""
78 files = { 91 if os.path.getsize(output_path) > 1024*1024*10:
79 'f': (output_path, f, 'application/octet-stream') 92 try:
80 } 93 dl_url = await self._upload_to_copyparty(output_path)
81 headers = { 94 await ctx.followup.send(f"wysyłon\n{dl_url}\n")
82 'Cookie': f'cppwd={os.getenv("COPYPARTY_PASSWORD")}' 95 except Exception as upload_error:
83 } 96 await ctx.followup.send(f"copyparty mnie nienawidzi :cccc\n {str(upload_error)}")
84 params = { 97 else:
85 'j': '1', # Return JSON response 98 await ctx.respond(file=discord.File(output_path))
86 'ck': 'b2' # Use blake2b checksum
87 }
88
89 # Ensure the URL ends with a single slash
90 base_url = "https://catbox.2137697.xyz/sperma/"
91
92 response = requests.post(
93 base_url,
94 files=files,
95 headers=headers,
96 params=params
97 )
98 99
99 if response.status_code == 200 or response.status_code == 201: 100 def _cleanup_files(self, *file_paths):
100 try: 101 """Clean up temporary files"""
101 result = response.json() 102 for path in file_paths:
102 if 'fileurl' in result: 103 if os.path.exists(path):
103 dl_url = result['fileurl'] 104 os.remove(path)
104 await ctx.followup.send(
105 f"wysyłon\n"
106 f"{dl_url}\n"
107 )
108 else:
109 await ctx.followup.send(
110 f"Odpowiedź serwera nie zawiera wymaganych danych: {result}")
111 except ValueError:
112 await ctx.followup.send(f"Nieprawidłowa odpowiedź z serwera: {response.text}")
113 else:
114 error_msg = response.text if response.text else 'Unknown error'
115 await ctx.followup.send(
116 f"nie udało się wysłać pliku (HTTP {response.status_code}): {error_msg}")
117 105
118 except Exception as upload_error: 106 @commands.slash_command(name="konwersja", description="konwertuj plik na inny format")
119 await ctx.followup.send(f"copyparty mnie nienawidzi :cccc\n {str(upload_error)}") 107 @discord.option(
120 logger.error(f"copyparty upload error: {upload_error}", exc_info=True) 108 "plik",
121 else: 109 description="plik do konwersji",
122 await ctx.respond(file=discord.File(output_path)) 110 required=True,
111 type=discord.Attachment
112 )
113 @discord.option(
114 "format",
115 description="format konwersji",
116 required=True,
117 type=str
118 )
119 async def convert(self, ctx, plik, output_format, args):
120 await ctx.defer()
121
122 try:
123 input_path, output_path = await self._setup_file_paths(plik, output_format)
124 file_type = filetype(input_path)
125 logger.info(f"Conversion started for: {file_type}")
126
127 command = self._build_conversion_command(file_type, input_path, output_path, args)
128 if not command:
129 await ctx.respond("Plik jest nieobsługiwany", ephemeral=True)
130 logger.info("Unsupported file type")
131 return
132
133 proc = await asyncio.create_subprocess_exec(*command.split())
134 await proc.wait()
135
136 await self._handle_file_output(ctx, output_path)
123 logger.info(f"Conversion completed for: {file_type}") 137 logger.info(f"Conversion completed for: {file_type}")
124 # Delete compressed file 138
125 os.remove(input_path)
126 os.remove(output_path)
127 except subprocess.CalledProcessError as e: 139 except subprocess.CalledProcessError as e:
128 await ctx.respond(f"Conversion failed: {str(e)}", ephemeral=True) 140 await ctx.respond(f"Conversion failed: {str(e)}", ephemeral=True)
129 if os.path.exists(input_path): 141 except Exception as e:
130 os.remove(input_path) 142 await ctx.respond(f"An error occurred: {str(e)}", ephemeral=True)
131 if os.path.exists(output_path): 143 finally:
132 os.remove(output_path) 144 if 'input_path' in locals():
145 self._cleanup_files(input_path, output_path)
133 146
134def setup(bot): 147def setup(bot):
135 bot.add_cog(Conversion(bot)) \ No newline at end of file 148 bot.add_cog(Conversion(bot)) \ No newline at end of file