aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/qr.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cogs/qr.py154
1 files changed, 0 insertions, 154 deletions
diff --git a/cogs/qr.py b/cogs/qr.py
deleted file mode 100644
index 32c574e..0000000
--- a/cogs/qr.py
+++ /dev/null
@@ -1,154 +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 asyncio
7import logging
8import os
9import tempfile
10
11import aiohttp
12import discord
13import qrcode
14from discord.ext import commands
15
16logger = logging.getLogger(__name__)
17
18_pil_image = None
19_decode_func = None
20_decode_available = False
21
22
23def _ensure_qr():
24 global _pil_image, _decode_func, _decode_available
25
26 if _pil_image is not None:
27 return _decode_available
28
29 try:
30 from PIL import Image
31 from pyzbar.pyzbar import decode as _decode_func
32 _pil_image = Image
33 _decode_available = True
34 except ImportError:
35 _decode_available = False
36 logger.warning("pyzbar or PIL not available, decode command will be disabled")
37 return _decode_available
38
39
40class QR(commands.Cog):
41 def __init__(self, bot):
42 self.bot = bot
43
44 async def _download_image(self, url):
45 """Download image from URL to temporary file"""
46 async with aiohttp.ClientSession() as session:
47 async with session.get(url) as response:
48 if response.status == 200:
49 content = await response.read()
50 with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as f:
51 await asyncio.get_event_loop().run_in_executor(None, f.write, content)
52 return f.name
53 return None
54
55 @commands.slash_command(
56 name="qr_generuj", description="Generuje kod QR z podanego tekstu"
57 )
58 async def qr(
59 self,
60 ctx,
61 text: str = discord.Option(str, "Tekst do zakodowania", required=True),
62 ):
63 await ctx.defer()
64
65 from cogs.utils.temp import get_temp_dir
66 temp_path = os.path.join(
67 get_temp_dir(), f"qr_{os.getpid()}_{asyncio.get_event_loop().time()}.png"
68 )
69
70 try:
71 loop = asyncio.get_event_loop()
72 await loop.run_in_executor(None, self._generate_qr, text, temp_path)
73 await ctx.respond(file=discord.File(temp_path, filename="qr.png"))
74 logger.info(f"Generated QR for text: {text}")
75 except Exception as e:
76 logger.error(f"QR generation error: {e}")
77 await ctx.respond("Error generating QR code", ephemeral=True)
78 finally:
79 try:
80 if os.path.exists(temp_path):
81 os.unlink(temp_path)
82 except Exception as e:
83 logger.error(f"Error cleaning up temp file: {e}")
84
85 def _generate_qr(self, text, output_path):
86 """Generate QR code (runs in executor)"""
87 qr = qrcode.QRCode(
88 version=1,
89 error_correction=qrcode.constants.ERROR_CORRECT_L, # type: ignore[attr-defined]
90 box_size=10,
91 border=4,
92 )
93 qr.add_data(text)
94 qr.make(fit=True)
95 img = qr.make_image(fill_color="black", back_color="white")
96 img.save(output_path)
97
98 @commands.slash_command(name="qr_dekoduj", description="Dekoduje kod QR z obrazka")
99 async def decode(
100 self,
101 ctx,
102 image: discord.Attachment = discord.Option(
103 discord.Attachment, "Obrazek z kodem QR", required=True
104 ),
105 ):
106 if not _ensure_qr():
107 await ctx.respond(
108 "Dekodowanie nie jest dostępne (brak biblioteki pyzbar)", ephemeral=True
109 )
110 return
111
112 await ctx.defer()
113
114 try:
115 temp_path = await self._download_image(image.url)
116 if not temp_path:
117 await ctx.respond("Nie udało się pobrać obrazka", ephemeral=True)
118 return
119
120 try:
121 loop = asyncio.get_event_loop()
122 decoded = await loop.run_in_executor(None, self._decode_qr, temp_path)
123
124 if decoded:
125 await ctx.respond(f"```\n{decoded}\n```")
126 logger.info(f"Decoded QR: {decoded}")
127 else:
128 await ctx.respond(
129 "Nie znaleziono kodu QR na obrazku", ephemeral=True
130 )
131 finally:
132 if os.path.exists(temp_path):
133 os.unlink(temp_path)
134 except Exception as e:
135 logger.error(f"QR decode error: {e}")
136 await ctx.respond("Error dekodowania QR", ephemeral=True)
137
138 def _decode_qr(self, image_path):
139 """Decode QR code from image (runs in executor)"""
140 if not _ensure_qr() or _decode_func is None:
141 return None
142
143 try:
144 img = _pil_image.open(image_path)
145 decoded_list = _decode_func(img)
146 if decoded_list:
147 return decoded_list[0].data.decode("utf-8")
148 except Exception as e:
149 logger.error(f"Error decoding QR: {e}")
150 return None
151
152
153def setup(bot):
154 bot.add_cog(QR(bot))