aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/downloader.py
blob: 7925f2d7bc4b6d51a04e817571ea2c1c6b70fbba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import os
import tempfile
import logging
import requests
import discord
import re
import yt_dlp
from discord.ext import commands
from dotenv import load_dotenv

logger = logging.getLogger(__name__)

# Load environment variables
load_dotenv()


class Downloader(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    URL_PATTERN = re.compile(
        r'https://(?:[A-Za-z0-9-]+\.)*[A-Za-z0-9-]{1,63}\.[A-Za-z]{2,63}/\S*'
    )

    @commands.message_command(
        name="download",
        description="Download and convert video/audio from internet"
    )
    async def message_download(self, ctx, message: discord.Message):
        # check if message has a valid url
        url = [m.group(0) for m in self.URL_PATTERN.finditer(message.content)]
        if url:
            for url in url:
                await self.download(ctx=ctx, url=url, fformat="mp4")
        else:
            await ctx.respond("Brak załączników w wiadomości", ephemeral=True)

    @commands.slash_command(
        name="download",
        description="Download and convert video/audio from internet"
    )
    async def download(
            self,
            ctx: discord.ApplicationContext,
            url: str = discord.Option(str, description="Link media", required=True),
            catbox: bool = discord.Option(bool, description="wysłać na serwer??", required=False, default=False),
            fformat: str = discord.Option(str, description="jaki format? (mp4, mp3, wav, etc.)", required=False, default="mp4"),
            filename_user: str = discord.Option(str, description="jaka nazwa pliku?", required=False)
    ):
        """Download and convert media from a URL to the specified format"""
        await ctx.defer()
        try:
            logger.info(f"Downloading {url} as {fformat}")

            with tempfile.TemporaryDirectory() as temp_dir:
                # Configure yt-dlp to use the original filename
                ydl_opts = {
                    'outtmpl': os.path.join(temp_dir, '%(title)s.%(ext)s'),
                    'format': 'bestaudio/best' if fformat in ['mp3', 'wav',
                                                              'm4a'] else 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
                    'merge_output_format': 'mp4',
                    'postprocessors': [],
                    'remote-components': 'ejs:github',
                    'js-runtimes': 'deno:/usr/bin/deno',
                    'o': '"%(title)s.%(ext)s"'
                }

                # Add post-processing for audio formats
                if fformat in ['mp3', 'wav', 'm4a']:
                    ydl_opts['postprocessors'].append({
                        'key': 'FFmpegExtractAudio',
                        'preferredcodec': fformat,
                        'preferredquality': '192',
                    })
                elif fformat != 'mp4':  # For other video formats
                    ydl_opts['postprocessors'].append({
                        'key': 'FFmpegVideoConvertor',
                        'preferedformat': fformat,
                    })

                with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                    ydl.download([url])

                # Find the downloaded file (should be the only file in the temp directory)
                files = [f for f in os.listdir(temp_dir) if os.path.isfile(os.path.join(temp_dir, f))]
                if not files:
                    raise Exception(f"No file was downloaded")

                actual_file = os.path.join(temp_dir, files[0])
                extension = actual_file.split('.')[-1]

                if not filename_user:
                    filename = os.path.basename(actual_file)
                else:
                    filename = filename_user + '.' + extension

                if not os.path.exists(actual_file):
                    raise Exception(f"Downloaded file not found: {actual_file}")

                if os.path.getsize(actual_file) > 1024*1024*10 or catbox:
                    try:

                        # Upload to Copyparty
                        with open(actual_file, 'rb') as f:
                            files = {
                                'f': (filename, f, 'application/octet-stream')
                            }
                            headers = {
                                'Cookie': f'cppwd={os.getenv("COPYPARTY_PASSWORD")}'
                            }
                            params = {
                                'j': '1',  # Return JSON response
                                'ck': 'b2'  # Use blake2b checksum
                            }

                            # Ensure the URL ends with a single slash
                            base_url = "https://catbox.2137697.xyz/sperma/"

                            response = requests.post(
                                base_url,
                                files=files,
                                headers=headers,
                                params=params
                            )

                            if response.status_code == 200 or response.status_code == 201:
                                try:
                                    result = response.json()
                                    if 'fileurl' in result:
                                        dl_url = result['fileurl']
                                        await ctx.followup.send(
                                            f"wysyłon\n"
                                            f"{dl_url}\n"
                                        )
                                    else:
                                        await ctx.followup.send(
                                            f"Odpowiedź serwera nie zawiera wymaganych danych: {result}")
                                except ValueError:
                                    await ctx.followup.send(f"Nieprawidłowa odpowiedź z serwera: {response.text}")
                            else:
                                error_msg = response.text if response.text else 'Unknown error'
                                await ctx.followup.send(
                                    f"nie udało się wysłać pliku (HTTP {response.status_code}): {error_msg}")

                    except Exception as upload_error:
                        await ctx.followup.send(f"copyparty mnie nienawidzi :cccc\n {str(upload_error)}")
                        logger.error(f"copyparty upload error: {upload_error}", exc_info=True)

                else:
                    await ctx.followup.send("wysyłon na discord\n", file=discord.File(filename))

                logger.info(f"File processed: {actual_file}")

        except Exception as e:
            await ctx.followup.send(f":(\n{str(e)}")
            logger.error(f"Error in download command: {e}", exc_info=True)


def setup(bot):
    bot.add_cog(Downloader(bot))