diff options
| author | salmonik <raisersoft@proton.me> | 2026-07-08 02:13:35 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-07-08 02:13:35 +0200 |
| commit | cd8ed8bc5793985df2c1692072a932ceee517b95 (patch) | |
| tree | 42d18a4140259b5c68b4dd05b7fcb398f78b8d7f /cogs/uploader.py | |
| parent | Merge pull request 'Voice related fixes, alongside simplifying assistant' (#5... (diff) | |
| download | senator-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.py | 156 |
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 | |||
| 6 | import os | ||
| 7 | import aiofiles | ||
| 8 | import requests | ||
| 9 | import urllib.parse | ||
| 10 | from typing import Optional | ||
| 11 | import discord | ||
| 12 | from discord.ext import commands | ||
| 13 | from discord import AutocompleteContext | ||
| 14 | from cogs.utils import file_search as search_utils | ||
| 15 | from cogs.utils.settings import get_uploadurl | ||
| 16 | import logging | ||
| 17 | |||
| 18 | logger = logging.getLogger(__name__) | ||
| 19 | |||
| 20 | |||
| 21 | class 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 | |||
| 155 | def setup(bot): | ||
| 156 | bot.add_cog(Uploader(bot)) | ||
