qrkodbot / services /qr_reader.py
ibrohm's picture
Upload folder using huggingface_hub
833e15d verified
"""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))
# RGBA bo'lsa RGB ga o'tkazish
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']}`"
)
# Bir nechta QR kod
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