Skip to content

Commit

Permalink
add fastapi server
Browse files Browse the repository at this point in the history
  • Loading branch information
nimarion committed Jan 30, 2024
1 parent 90247b9 commit bc176cb
Show file tree
Hide file tree
Showing 22 changed files with 163 additions and 20 deletions.
69 changes: 69 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Docker

on:
workflow_dispatch:
push:
branches:
- main
permissions:
actions: write
contents: read
packages: write

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build:
name: 🐳 Build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
with:
access_token: ${{ github.token }}

- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: ⚡️ Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: 🔑 Github Registry Auth
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: 👀 Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: 🐳 Build
uses: docker/build-push-action@v3
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
COMMIT_SHA=${{ github.sha }}
BRANCH=${{ github.head_ref || github.ref_name }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new

- name: 🚚 Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM python:3.10-alpine

WORKDIR /code

COPY ./requirements.txt /code/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY . /code/app

CMD ["uvicorn", "app.server:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ python3 .\main.py --excel .\data.xlsx --output .\output\ --font .\agency_fb.ttf
```

```bash
python3 .\bib.py --text MARION --output NiklasMarion.png --header .\sponsor\lotto.png --footer .\footer.png --font .\agency_fb.ttf --header-offset 60
python3 .\bib.py --text MARION --output NiklasMarion.png --header .\header\lotto.png --footer .\footer\rehlingen.png --font .\agency_fb.ttf --header-offset 60
```

![image](https://github.com/nimarion/bib-generator/assets/23435250/5a7272fb-e5bb-4117-b3e0-b769daf06912)
Expand Down
31 changes: 15 additions & 16 deletions bib.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
from PIL import ImageFont, ImageDraw, Image
import argparse
import img2pdf
import os
import uuid
import io

def main(txt, output_file, header_file, footer_file, font_file, header_offset = 0):
def generate_image(txt, header_file, footer_file, font_file, header_offset = 0):
# A5 size
image = Image.new("RGB", (3508, 2480), "white")
header = Image.open(header_file)
footer = Image.open(footer_file)
header = Image.open("header/" + header_file)
footer = Image.open("footer/" + footer_file)
draw = ImageDraw.Draw(image)
fontsize = 1 # starting font size

Expand Down Expand Up @@ -48,16 +46,17 @@ def main(txt, output_file, header_file, footer_file, font_file, header_offset =
image.paste(header, (0, header_offset))
image.paste(footer, (0, image.size[1] - footer.size[1]))

if output_file.endswith('.pdf'):
a5 = (img2pdf.mm_to_pt(210), img2pdf.mm_to_pt(148))
layout = img2pdf.get_layout_fun(a5)
tmp_file = str(uuid.uuid4()) + '.png'
image.save(tmp_file)
with open(output_file, 'wb') as f:
f.write(img2pdf.convert([tmp_file], layout_fun=layout))
os.remove(tmp_file)
else:
image.save(output_file)
img_byte_arr = io.BytesIO()
image.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
return img_byte_arr



def main(txt, output_file, header_file, footer_file, font_file, header_offset = 0):
bytes = generate_image(txt, header_file, footer_file, font_file, header_offset)
image = Image.open(io.BytesIO(bytes))
image.save(output_file)

if __name__ == "__main__":
parser = argparse.ArgumentParser(
Expand Down
Empty file added footer/.gitkeep
Empty file.
File renamed without changes
Empty file added header/.gitkeep
Empty file.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
4 changes: 2 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
'--output', '-o', help='Output folder', required=True)
argparse.add_argument('--font', '-F', help='Font file name', required=True)
argparse.add_argument(
'--footer', '-he', help='Footer file name', default="footer.png", required=False)
'--footer', '-he', help='Footer file name', default="rehlingen.png", required=False)
argparse.add_argument(
'--header-offset', '-ho', help='Header offset', default=0, required=False, type=int)

Expand All @@ -30,7 +30,7 @@
lastname = row['Nachname']
text = lastname.upper()
sponsor = row['Sponsor']
header_file = "sponsor/" + sponsor + ".png"
header_file = sponsor + ".png"
output_file = output_folder + "/" + lastname + "_" + firstname + ".png"
print("Generating bib for", firstname, lastname, "with sponsor", sponsor)
bib_generator(text, output_file, header_file, footer_file, font_file, header_offset)
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
openpyxl==3.1.2
pandas==2.2.0
pillow==10.2.0
img2pdf==0.5.1
img2pdf==0.5.1
fastapi==0.105.0
uvicorn[standard]==0.25.0
62 changes: 62 additions & 0 deletions server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from fastapi import FastAPI, Response
from typing import Optional
from os import walk
from fastapi.staticfiles import StaticFiles
from bib import generate_image

app = FastAPI(title="DLV", docs_url="/swagger",
openapi_url="/swagger-json", redoc_url=None)

app.mount("/header", StaticFiles(directory="header"), name="header")
app.mount("/footer", StaticFiles(directory="footer"), name="footer")


def headers():
header = []
for (dirpath, dirnames, filenames) in walk("header"):
filenames = [f for f in filenames if f.endswith(
'.png') or f.endswith('.jpg')]
header.extend(filenames)
break
return header


def footers():
footer = []
for (dirpath, dirnames, filenames) in walk("footer"):
filenames = [f for f in filenames if f.endswith(
'.png') or f.endswith('.jpg')]
footer.extend(filenames)
break
return footer


@app.get("/", responses={
200: {
"content": {"image/png": {}}
}
}, response_class=Response)
def generate_bib(
text: str,
header: str,
footer: str,
header_offset: Optional[int] = 60,
):
# check if header and footer are valid
if header not in headers():
return {"error": "Header not found"}
if footer not in footers():
return {"error": "Footer not found"}
image = generate_image(text, header, footer,
"agency_fb.ttf", header_offset)
return Response(content=image, media_type="image/png", headers={"Content-Disposition": "filename=" + text + ".png"})


@app.get("/headers")
def get_headers():
return headers()


@app.get("/footers")
def get_footers():
return footers()

0 comments on commit bc176cb

Please sign in to comment.