aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/uploader.py
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-07-08 02:13:35 +0200
committersalmonik <raisersoft@proton.me>2026-07-08 02:13:35 +0200
commitcd8ed8bc5793985df2c1692072a932ceee517b95 (patch)
tree42d18a4140259b5c68b4dd05b7fcb398f78b8d7f /cogs/uploader.py
parentMerge pull request 'Voice related fixes, alongside simplifying assistant' (#5... (diff)
downloadsenator-sperma-cd8ed8bc5793985df2c1692072a932ceee517b95.tar.gz
senator-sperma-cd8ed8bc5793985df2c1692072a932ceee517b95.zip
OPEN THE RUST GATES
Signed-off-by: salmonik <raisersoft@proton.me>
Diffstat (limited to '')
-rw-r--r--cogs/uploader.py156
1 files changed, 0 insertions, 156 deletions
diff --git a/cogs/uploader.py b/cogs/uploader.py
deleted file mode 100644
index a5d0e05..0000000
--- a/cogs/uploader.py
+++ /dev/null
@@ -1,156 +0,0 @@
1# This file is part of Senator Sperma
2# Licensed under the GPL-3.0 License
3# Copyright (C) 2026 Salmonik @ salmonik@tuta.io
4# https://codeberg.org/salmonik/senator-sperma
5
6import os
7import aiofiles
8import requests
9import urllib.parse
10from typing import Optional
11import discord
12from discord.ext import commands
13from discord import AutocompleteContext
14from cogs.utils import file_search as search_utils
15from cogs.utils.settings import get_uploadurl
16import logging
17
18logger = logging.getLogger(__name__)
19
20
21class Uploader(commands.Cog):
22 def __init__(self, bot):
23 from cogs.utils.temp import get_temp_dir
24 self.bot = bot
25 self.temp_dir = get_temp_dir()
26 self._cached_urls = {}
27 self._uploadurl = get_uploadurl()
28
29 async def _file_autocomplete(self, ctx: AutocompleteContext):
30 query = ctx.value.lower() if ctx.value else ""
31 results = await search_utils.UniversalSearcher.search_copyparty_autocomplete(query, max_results=25)
32
33 user_id = ctx.interaction.user.id
34 self._cached_urls[user_id] = {urllib.parse.unquote(url.split('/')[-1]): url for url in results}
35
36 choices = []
37 for url in results[:25]:
38 filename = urllib.parse.unquote(url.split('/')[-1])
39 display_name = filename[:99] + "…" if len(filename) > 100 else filename
40 choices.append(discord.OptionChoice(name=display_name, value=filename))
41 return choices
42
43 async def _download_from_url(self, url: str) -> Optional[str]:
44 """Download file from copyparty URL and return local path"""
45 try:
46 response = requests.get(url)
47 if response.status_code != 200:
48 return None
49
50 filename = url.split('/')[-1].split('?')[0]
51 filename = urllib.parse.unquote(filename)
52 file_path = os.path.join(self.temp_dir, filename)
53
54 async with aiofiles.open(file_path, 'wb') as f:
55 await f.write(response.content)
56 return file_path
57 except Exception as e:
58 logger.error(f"Error downloading from {url}: {e}")
59 return None
60
61 async def _upload_to_copyparty(self, file_path: str) -> Optional[str]:
62 """Upload file to copyparty and return download URL"""
63 try:
64 async with aiofiles.open(file_path, 'rb') as f:
65 file_content = await f.read()
66
67 files = {'f': (os.path.basename(file_path), file_content, 'application/octet-stream')}
68 headers = {'Cookie': f'cppwd={os.getenv("COPYPARTY_PASSWORD")}'}
69 params = {'j': '1', 'ck': 'b2'}
70
71 response = requests.post(self._uploadurl, files=files, headers=headers, params=params)
72
73 if response.status_code in [200, 201]:
74 result = response.json()
75 return result.get('fileurl')
76 except Exception as e:
77 logger.error(f"Upload error: {e}")
78 return None
79
80 async def _upload_file(self, file_path: str) -> Optional[str]:
81 """Upload a file and return the URL"""
82 if self._uploadurl == "http://localhost:3939":
83 logger.warning("COPYPARTY_URL_UPLOAD not set! Using default")
84 return None
85
86 return await self._upload_to_copyparty(file_path)
87
88 @commands.message_command(
89 name="upload",
90 description="wyślij załączniki na copyparty",
91 )
92 async def message_upload(self, ctx, message: discord.Message):
93 if not message.attachments:
94 await ctx.respond("Brak załączników w wiadomości", ephemeral=True)
95 return
96
97 await ctx.defer()
98
99 uploaded_urls = []
100 failed_count = 0
101
102 for attachment in message.attachments:
103 file_path = os.path.join(self.temp_dir, attachment.filename)
104 await attachment.save(file_path)
105
106 url = await self._upload_file(file_path)
107 if url:
108 uploaded_urls.append(url)
109 else:
110 failed_count += 1
111
112 if os.path.exists(file_path):
113 os.remove(file_path)
114
115 if uploaded_urls:
116 response = f"Wysłano {len(uploaded_urls)} plików:\n" + "\n".join(uploaded_urls)
117 if failed_count > 0:
118 response += f"\n\nNie wysłano {failed_count} plików"
119 await ctx.respond(response)
120 else:
121 await ctx.respond("Nie udało się wysłać żadnych plików", ephemeral=True)
122
123 @commands.slash_command(
124 name="upload",
125 description="wyślij plik na copyparty",
126 )
127 @discord.option(
128 name="zalacznik",
129 description="plik z discorda",
130 required=True,
131 type=discord.Attachment
132 )
133 async def upload(self, ctx, zalacznik: discord.Attachment = None):
134 await ctx.defer()
135
136 file_path = None
137 file_path = os.path.join(self.temp_dir, zalacznik.filename)
138 await zalacznik.save(file_path)
139
140 if not file_path or not os.path.exists(file_path):
141 await ctx.respond("Nie udało się pobrać pliku", ephemeral=True)
142 return
143
144 try:
145 dl_url = await self._upload_file(file_path)
146 if dl_url:
147 await ctx.respond(dl_url)
148 else:
149 await ctx.respond("Nie udało się wysłać pliku", ephemeral=True)
150 finally:
151 if file_path and os.path.exists(file_path):
152 os.remove(file_path)
153
154
155def setup(bot):
156 bot.add_cog(Uploader(bot))