diff --git a/.gitignore b/.gitignore index 40cb5fc..d91c3ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .venv test.pdf -.idea \ No newline at end of file +.idea +files \ No newline at end of file diff --git a/ezgg_badge_generator.py b/ezgg_badge_generator.py new file mode 100644 index 0000000..ef70003 --- /dev/null +++ b/ezgg_badge_generator.py @@ -0,0 +1,27 @@ +import asyncio + +from services.DatabaseService import DatabaseService +from services.BadgeGeneratorService import BadgeGeneratorService +from pathlib import Path + + +async def main(): + db = DatabaseService("sql_config.toml") + await db.init_db_pool() + + badges = await db.get_user_badges() + + badge_generator = BadgeGeneratorService( + svg_template=Path("template/template_dynamic_name_size.svg"), + chrome_path=Path(r"C:\Program Files\Google\Chrome\Application\chrome.exe") + ) + for user_badge in badges: + badge_generator.generate_badge( + name=user_badge["user_name"], + seat_id=user_badge["seat_id"], + picture=user_badge["picture"] + ) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..643d45d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +mysql-connector-python~=9.6.0 +aiomysql~=0.3.2 +Jinja2~=3.1.6 \ No newline at end of file diff --git a/services/BadgeGeneratorService.py b/services/BadgeGeneratorService.py new file mode 100644 index 0000000..c746268 --- /dev/null +++ b/services/BadgeGeneratorService.py @@ -0,0 +1,68 @@ +import logging +import os +import re +import base64 +import subprocess +import tempfile +from pathlib import Path +from jinja2 import Environment, FileSystemLoader + +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s [%(levelname)s] %(name)s: %(message)s" +) + +logger = logging.getLogger(__name__.split(".")[-1]) + + +class BadgeGeneratorService: + + def __init__(self, svg_template: Path, chrome_path: Path): + self.svg_template = svg_template + self.chrome_path = chrome_path + + def generate_badge(self, name, seat_id, picture) -> None: + svg = self.generate_svg(name, seat_id, picture) + self.svg_to_pdf(svg, f"files/{name}.pdf") + + def generate_svg(self, username: str, seat: str, image_base64: bytes) -> str: + with open(self.svg_template, "r", encoding="utf-8") as f: + svg = f.read() + # ToDo: Select font size for long names + svg = svg.replace(">test_username", f">{username}") + svg = svg.replace(">Platz: XYZ<", f">Platz: {seat}<") + if image_base64: + encoded = base64.b64encode(image_base64).decode("utf-8") + svg = svg.replace('xlink:href="data:image/jpeg;base64,"', f'xlink:href="data:image/jpeg;base64,{encoded}"') + logger.info(f"Generate svg string: Username: {username}, Seat: {seat}, Picture: {str(image_base64)[:15]}") + return svg + + def svg_to_pdf(self, svg_string: str, pdf_path: str): + + width = re.search(r'width="([^"]+)"', svg_string).group(1) + height = re.search(r'height="([^"]+)"', svg_string).group(1) + + env = Environment(loader=FileSystemLoader("template")) + template = env.get_template("badge_pdf.html") + + html = template.render( + width=width, + height=height, + svg_string=svg_string + ) + + with tempfile.NamedTemporaryFile(delete=False, suffix=".html", mode="w", encoding="utf-8") as f: + f.write(html) + html_path = f.name + + try: + subprocess.run([ + self.chrome_path, + "--headless", + "--disable-gpu", + f"--print-to-pdf={os.path.abspath(pdf_path)}", + html_path + ], check=True) + finally: + os.remove(html_path) + logger.info(f"Created: {pdf_path}") diff --git a/services/DatabaseService.py b/services/DatabaseService.py new file mode 100644 index 0000000..0236a13 --- /dev/null +++ b/services/DatabaseService.py @@ -0,0 +1,38 @@ +import tomllib +import aiomysql +from typing import Optional + + +class DatabaseService: + + def __init__(self, sql_config: str): + with open(sql_config, "rb") as f: + config = tomllib.load(f) + + self.db_config = config["database"] + self._pool: Optional[aiomysql.Pool] = None + + async def init_db_pool(self): + self._pool = await aiomysql.create_pool( + host=self.db_config["db_host"], + port=self.db_config["db_port"], + user=self.db_config["db_user"], + password=self.db_config["db_password"], + db=self.db_config["db_name"], + minsize=1, + maxsize=40, + autocommit=True + ) + + async def get_user_badges(self) -> list: + async with self._pool.acquire() as conn: + async with conn.cursor(aiomysql.DictCursor) as cursor: + await cursor.execute( + """SELECT u.user_id, u.user_name, s.seat_id, upp.picture + FROM users AS u + LEFT JOIN seats AS s + ON u.user_id = s.`user` + LEFT JOIN user_profile_picture AS upp + ON u.user_id = upp.user_id;""" + ) + return await cursor.fetchall() diff --git a/services/__init__.py b/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sql_config.toml b/sql_config.toml new file mode 100644 index 0000000..8411c13 --- /dev/null +++ b/sql_config.toml @@ -0,0 +1,6 @@ +[database] + db_user="demo_user" + db_password="demo_password" + db_host="127.0.0.1" + db_port=3306 + db_name="ezgg_lan_manager" \ No newline at end of file diff --git a/template/Vorlage_LAN_Ausweis_mit_Daten.svg b/template/Vorlage_LAN_Ausweis_mit_Daten.svg deleted file mode 100644 index 3a6466c..0000000 --- a/template/Vorlage_LAN_Ausweis_mit_Daten.svg +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - - - - - - - - - - - - -LANtest_namePlatz: c05ich bin dein bier-geld diff --git a/template/badge_pdf.html b/template/badge_pdf.html new file mode 100644 index 0000000..58093f0 --- /dev/null +++ b/template/badge_pdf.html @@ -0,0 +1,39 @@ + + + + + + +
+{{ svg_string | safe }} +
+ +
+{{ svg_string | safe }} +
+ + + \ No newline at end of file diff --git a/template/template_dynamic_name_size.svg b/template/template_dynamic_name_size.svg new file mode 100644 index 0000000..7f6560a --- /dev/null +++ b/template/template_dynamic_name_size.svg @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + +LANtest_usernamePlatz: XYZich bin dein bier-geld diff --git a/template/test_profile_picture.png b/template/test_profile_picture.png deleted file mode 100644 index 3ac3657..0000000 Binary files a/template/test_profile_picture.png and /dev/null differ diff --git a/user_badge_creator.py b/user_badge_creator.py deleted file mode 100644 index 21af5f0..0000000 --- a/user_badge_creator.py +++ /dev/null @@ -1,104 +0,0 @@ -import os -import re -import base64 -import subprocess -import tempfile -from pathlib import Path - -SVG_TEMPLATE = Path("template/Vorlage_LAN_Ausweis.svg") -CHROME_PATH = Path(r"C:\Program Files\Google\Chrome\Application\chrome.exe") - - -def get_image_as_base64(image_path: str) -> str: - with open(image_path, "rb") as image_file: - encoded_bytes = base64.b64encode(image_file.read()) - encoded_string = encoded_bytes.decode("utf-8") - return f'xlink:href="data:image/jpeg;base64,{encoded_string}"' - - -def get_user_svg_string(username: str, seat: str, user_image: str) -> str: - with open(SVG_TEMPLATE, "r", encoding="utf-8") as svg_file: - svg_string = svg_file.read() - - svg_string = svg_string.replace(">test_username", f">{username}") - svg_string = svg_string.replace(">Platz: XYZ<", f">Platz: {seat}<") - svg_string = svg_string.replace('xlink:href="data:image/jpeg;base64,"', user_image) - - """ - with open("test.svg", "w", encoding="utf-8") as f: - f.write(svg_content) - """ - - return svg_string - - -def create_pdf_from_svg(svg_string: str, pdf_path: str): - width = re.search(r'width="([^"]+)"', svg_string) - height = re.search(r'height="([^"]+)"', svg_string) - - width = width.group(1) - height = height.group(1) - - html = f""" - - - - - - -
-{svg_string} -
- -
-{svg_string} -
- - - -""" - - with tempfile.NamedTemporaryFile(delete=False, suffix=".html", mode="w", encoding="utf-8") as f: - f.write(html) - html_path = f.name - - try: - subprocess.run([ - CHROME_PATH, - "--headless", - "--disable-gpu", - f"--print-to-pdf={os.path.abspath(pdf_path)}", - html_path - ], check=True) - finally: - os.remove(html_path) - - -if __name__ == "__main__": - img_base64 = get_image_as_base64("template/test_profile_picture.png") - user_svg_string = get_user_svg_string("Tcprod.", "C01", img_base64) - create_pdf_from_svg(user_svg_string, "test.pdf")