Spaces:
Running
Running
DaDaDaTheoryNow
commited on
Commit
•
d1bba0a
1
Parent(s):
9bb44d4
first commit
Browse files- .gitignore +2 -0
- Dockerfile +11 -0
- requirements.txt +45 -0
- src/main.py +9 -0
- src/qr_generate/router.py +47 -0
- src/qr_generate/schemas.py +32 -0
- src/util/rgb_model.py +6 -0
.gitignore
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
venv/
|
2 |
+
**/__pycache__/
|
Dockerfile
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.12
|
2 |
+
|
3 |
+
WORKDIR /app
|
4 |
+
|
5 |
+
COPY ./requirements.txt /app/requirements.txt
|
6 |
+
|
7 |
+
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
|
8 |
+
|
9 |
+
COPY . .
|
10 |
+
|
11 |
+
CMD ["uvicorn", "app.src.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
requirements.txt
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
annotated-types==0.6.0
|
2 |
+
anyio==4.0.0
|
3 |
+
certifi==2023.7.22
|
4 |
+
click==8.1.7
|
5 |
+
colorama==0.4.6
|
6 |
+
distlib==0.3.7
|
7 |
+
dnspython==2.4.2
|
8 |
+
email-validator==2.1.0.post1
|
9 |
+
exceptiongroup==1.1.3
|
10 |
+
fastapi==0.108.0
|
11 |
+
filelock==3.12.4
|
12 |
+
h11==0.14.0
|
13 |
+
httpcore==0.17.3
|
14 |
+
httptools==0.6.1
|
15 |
+
httpx==0.24.1
|
16 |
+
idna==3.4
|
17 |
+
itsdangerous==2.1.2
|
18 |
+
Jinja2==3.1.2
|
19 |
+
MarkupSafe==2.1.3
|
20 |
+
netifaces==0.11.0
|
21 |
+
orjson==3.9.10
|
22 |
+
packaging==23.2
|
23 |
+
pillow==10.2.0
|
24 |
+
ping3==4.0.4
|
25 |
+
platformdirs==3.10.0
|
26 |
+
psutil==5.9.6
|
27 |
+
pydantic==2.5.3
|
28 |
+
pydantic-extra-types==2.4.0
|
29 |
+
pydantic-settings==2.1.0
|
30 |
+
pydantic_core==2.14.6
|
31 |
+
pydentic==0.0.1.dev3
|
32 |
+
python-dotenv==1.0.0
|
33 |
+
python-multipart==0.0.6
|
34 |
+
python-stdnum==1.19
|
35 |
+
PyYAML==6.0.1
|
36 |
+
qrcode-artistic==3.0.2
|
37 |
+
segno==1.6.0
|
38 |
+
sniffio==1.3.0
|
39 |
+
starlette==0.32.0.post1
|
40 |
+
typing_extensions==4.9.0
|
41 |
+
ujson==5.9.0
|
42 |
+
uvicorn==0.25.0
|
43 |
+
virtualenv==20.24.5
|
44 |
+
watchfiles==0.21.0
|
45 |
+
websockets==12.0
|
src/main.py
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI
|
2 |
+
|
3 |
+
from qr_generate.router import router as qr_generate_router
|
4 |
+
|
5 |
+
app = FastAPI(
|
6 |
+
title="Animated QR Maker"
|
7 |
+
)
|
8 |
+
|
9 |
+
app.include_router(qr_generate_router)
|
src/qr_generate/router.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import base64
|
2 |
+
import io
|
3 |
+
from fastapi import APIRouter
|
4 |
+
from qr_generate.schemas import QRCode, StaticQRCodeRequest, StaticQRCodeResponseModel, AnimatedQRCodeRequest, AnimatedQRCodeResponseModel
|
5 |
+
from urllib.request import urlopen
|
6 |
+
|
7 |
+
import segno
|
8 |
+
|
9 |
+
router = APIRouter(
|
10 |
+
prefix="/qr_generate",
|
11 |
+
tags=["Generate QR Code"]
|
12 |
+
)
|
13 |
+
|
14 |
+
|
15 |
+
@router.post("/static", response_model=StaticQRCodeResponseModel)
|
16 |
+
def generate_static_qr_code(qr_request: StaticQRCodeRequest):
|
17 |
+
qrcode = segno.make_qr(qr_request.content)
|
18 |
+
image_buffer = io.BytesIO()
|
19 |
+
|
20 |
+
qrcode.save(image_buffer,
|
21 |
+
kind="png",
|
22 |
+
scale=qr_request.scale,
|
23 |
+
dark=(qr_request.qr_code_color.red, qr_request.qr_code_color.green, qr_request.qr_code_color.blue),
|
24 |
+
border=qr_request.border_size,
|
25 |
+
light=(qr_request.border_color.red, qr_request.border_color.green, qr_request.border_color.blue),
|
26 |
+
data_dark=(qr_request.data_color.red, qr_request.data_color.green, qr_request.data_color.blue))
|
27 |
+
|
28 |
+
image_buffer.seek(0)
|
29 |
+
return StaticQRCodeResponseModel(status="success", data=QRCode(image_bytes=base64.b64encode(image_buffer.read()),
|
30 |
+
content=qr_request.content))
|
31 |
+
|
32 |
+
@router.post("/animated", response_model=AnimatedQRCodeResponseModel)
|
33 |
+
def generate_animated_qr_code(qr_request: AnimatedQRCodeRequest):
|
34 |
+
qrcode = segno.make_qr(qr_request.content)
|
35 |
+
image_buffer = io.BytesIO()
|
36 |
+
|
37 |
+
video_url = urlopen(qr_request.background_video_link)
|
38 |
+
qrcode.to_artistic(
|
39 |
+
background=video_url,
|
40 |
+
target=image_buffer,
|
41 |
+
scale=qr_request.scale,
|
42 |
+
kind='gif'
|
43 |
+
)
|
44 |
+
|
45 |
+
image_buffer.seek(0)
|
46 |
+
return AnimatedQRCodeResponseModel(status="success", data=QRCode(image_bytes=base64.b64encode(image_buffer.read()),
|
47 |
+
content=qr_request.content))
|
src/qr_generate/schemas.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from util.rgb_model import RGBModel
|
2 |
+
from pydantic import BaseModel
|
3 |
+
|
4 |
+
class QRCode(BaseModel):
|
5 |
+
content: str
|
6 |
+
image_bytes: str
|
7 |
+
|
8 |
+
### models for generate static(without video) qr code / png
|
9 |
+
class StaticQRCodeRequest(BaseModel):
|
10 |
+
content: str
|
11 |
+
border_size: int = 1
|
12 |
+
scale: int = 15
|
13 |
+
qr_code_color: RGBModel = RGBModel(red=0, green=0, blue=0)
|
14 |
+
data_color: RGBModel = RGBModel(red=0, green=0, blue=0)
|
15 |
+
border_color: RGBModel
|
16 |
+
|
17 |
+
class StaticQRCodeResponseModel(BaseModel):
|
18 |
+
status: str
|
19 |
+
data: QRCode
|
20 |
+
### end
|
21 |
+
|
22 |
+
|
23 |
+
### models for generate static(without video) qr code / png
|
24 |
+
class AnimatedQRCodeRequest(BaseModel):
|
25 |
+
content: str
|
26 |
+
scale: int = 15
|
27 |
+
background_video_link: str
|
28 |
+
|
29 |
+
class AnimatedQRCodeResponseModel(BaseModel):
|
30 |
+
status: str
|
31 |
+
data: QRCode
|
32 |
+
### end
|
src/util/rgb_model.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pydantic import BaseModel
|
2 |
+
|
3 |
+
class RGBModel(BaseModel):
|
4 |
+
red: int = 255
|
5 |
+
green: int = 255
|
6 |
+
blue: int = 255
|