| """QR kod o'qish servisi""" |
|
|
| import io |
| import asyncio |
| from PIL import Image |
|
|
| try: |
| from pyzbar.pyzbar import decode as pyzbar_decode |
| PYZBAR_AVAILABLE = True |
| except (ImportError, OSError): |
| PYZBAR_AVAILABLE = False |
|
|
|
|
| async def read_qr_from_bytes_async(image_bytes: bytes) -> list[dict]: |
| """Asinxron o'qish asosi uchn thread ishlatiladi""" |
| return await asyncio.to_thread(read_qr_from_bytes, image_bytes) |
|
|
| def read_qr_from_bytes(image_bytes: bytes) -> list[dict]: |
| """ |
| Rasm baytlaridan QR kodlarni o'qish |
| :param image_bytes: Rasm fayl baytlari |
| :return: Topilgan QR kodlar ro'yxati [{"type": "...", "data": "..."}] |
| """ |
| if not PYZBAR_AVAILABLE: |
| return _read_qr_fallback(image_bytes) |
|
|
| try: |
| img = Image.open(io.BytesIO(image_bytes)) |
| |
| if img.mode == "RGBA": |
| img = img.convert("RGB") |
|
|
| decoded_objects = pyzbar_decode(img) |
|
|
| results = [] |
| for obj in decoded_objects: |
| results.append({ |
| "type": obj.type, |
| "data": obj.data.decode("utf-8", errors="replace"), |
| }) |
|
|
| return results |
| except Exception as e: |
| return [{"type": "ERROR", "data": f"QR kodni o'qishda xato: {str(e)}"}] |
|
|
|
|
| def _read_qr_fallback(image_bytes: bytes) -> list[dict]: |
| """ |
| pyzbar mavjud bo'lmaganda qrcode kutubxonasi bilan o'qish |
| """ |
| try: |
| from qreader import QReader |
| import numpy as np |
|
|
| img = Image.open(io.BytesIO(image_bytes)) |
| if img.mode == "RGBA": |
| img = img.convert("RGB") |
|
|
| reader = QReader() |
| img_array = np.array(img) |
| decoded_texts = reader.detect_and_decode(image=img_array) |
|
|
| results = [] |
| for text in decoded_texts: |
| if text: |
| results.append({"type": "QRCODE", "data": text}) |
|
|
| return results |
| except ImportError: |
| return [{ |
| "type": "ERROR", |
| "data": "β οΈ QR kod o'qish uchun kerakli kutubxona (pyzbar) o'rnatilmagan.\n" |
| "O'rnatish: pip install pyzbar\n" |
| "Windows uchun: Visual C++ Redistributable kerak bo'lishi mumkin." |
| }] |
| except Exception as e: |
| return [{"type": "ERROR", "data": f"QR kodni o'qishda xato: {str(e)}"}] |
|
|
|
|
| def format_qr_result(results: list[dict]) -> str: |
| """ |
| QR kod natijalarini chiroyli formatda qaytarish |
| """ |
| if not results: |
| return "β Rasmda QR kod topilmadi." |
|
|
| if len(results) == 1: |
| r = results[0] |
| if r["type"] == "ERROR": |
| return r["data"] |
| return ( |
| f"β
**QR kod topildi!**\n\n" |
| f"π **Tur:** {r['type']}\n" |
| f"π **Ma'lumot:**\n\n`{r['data']}`" |
| ) |
|
|
| |
| text = f"β
**{len(results)} ta QR kod topildi!**\n\n" |
| for i, r in enumerate(results, 1): |
| if r["type"] == "ERROR": |
| text += f"**#{i}:** {r['data']}\n\n" |
| else: |
| text += ( |
| f"**#{i}**\n" |
| f"π Tur: {r['type']}\n" |
| f"π Ma'lumot: `{r['data']}`\n\n" |
| ) |
| return text |
|
|