From 786c07127489fc00a1c70fe03579e8a5ebcbe15b Mon Sep 17 00:00:00 2001 From: tonlls Date: Sat, 14 Oct 2023 04:06:03 +0200 Subject: [PATCH] added connection to api and missing to create the data file --- .gitignore | 222 +++---- .idea/.gitignore | 4 +- .idea/IdentificationGenerator.iml | 20 +- .../inspectionProfiles/profiles_settings.xml | 10 +- .idea/misc.xml | 6 +- .idea/modules.xml | 14 +- .idea/vcs.xml | 10 +- .vscode/launch.json | 28 +- Dockerfile | 20 +- Model.py | 547 +++++++++--------- PrivateConfig.sample.py | 2 + README.md | 12 +- Tools.py | 260 ++++----- api_connector.py | 23 + main.py | 50 +- old.requirements.txt | 62 +- resources/editions/data_sample.json | 30 +- test.py | 140 ++--- 18 files changed, 748 insertions(+), 712 deletions(-) create mode 100644 PrivateConfig.sample.py create mode 100644 api_connector.py diff --git a/.gitignore b/.gitignore index 63edd56..2922d14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,110 +1,112 @@ -#custom -resources/*_firebase_cert.json -resources/editions/*/data.json -_out_/ -*.pdf - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ +#custom +resources/*_firebase_cert.json +resources/editions/*/data.json +_out_/ +*.pdf +PrivateConfig.py +.idea/ +.vscode +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/.idea/.gitignore b/.idea/.gitignore index 0e40fe8..5a36972 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -1,3 +1,3 @@ - -# Default ignored files + +# Default ignored files /workspace.xml \ No newline at end of file diff --git a/.idea/IdentificationGenerator.iml b/.idea/IdentificationGenerator.iml index 6711606..9c88284 100644 --- a/.idea/IdentificationGenerator.iml +++ b/.idea/IdentificationGenerator.iml @@ -1,11 +1,11 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml index 105ce2d..20fc29e 100644 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -1,6 +1,6 @@ - - - + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index d4fc832..c9da8e2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index e59bda9..43bab96 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..9661ac7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index de19f71..7a47f91 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,15 +1,15 @@ -{ - // Use IntelliSense para saber los atributos posibles. - // Mantenga el puntero para ver las descripciones de los existentes atributos. - // Para más información, visite: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Archivo actual", - "type": "python", - "request": "launch", - "program": "python main.py", - "console": "integratedTerminal" - } - ] +{ + // Use IntelliSense para saber los atributos posibles. + // Mantenga el puntero para ver las descripciones de los existentes atributos. + // Para más información, visite: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Archivo actual", + "type": "python", + "request": "launch", + "program": "python main.py", + "console": "integratedTerminal" + } + ] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 30c1b19..709e0ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,10 @@ -FROM python:3.10 -ENV PYTHONUNBUFFERED=1 -WORKDIR /app - -RUN pip install --no-cache-dir -U pip - -COPY requirements.txt /tmp/requirements.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt - -COPY . /app +FROM python:3.10 +ENV PYTHONUNBUFFERED=1 +WORKDIR /app + +RUN pip install --no-cache-dir -U pip + +COPY requirements.txt /tmp/requirements.txt +RUN pip install --no-cache-dir -r /tmp/requirements.txt + +COPY . /app diff --git a/Model.py b/Model.py index ab80de4..41cffe7 100644 --- a/Model.py +++ b/Model.py @@ -1,269 +1,278 @@ -import os - -import firebase_admin -from PIL import Image -from firebase_admin import firestore - -import Config -import Tools - - -class Card: - QR_PIX_SIZE = 1 - QR_POS = (450, 78) - _QR_SIZE = 267 - QR_SIZE = (_QR_SIZE, _QR_SIZE) - QR_BORDER_SIZE = 0 - TYPE_POS = (0, 475) - NAME_POS = (QR_POS[0], 370) - NICK_POS = (1198, 870) - - -class Assistant(object): - __ID:int = 1 - __DATA:str = 'empty' - _DATA_FILE:str = Config.DATA_PATH - - def __init__(self, id:str, type:str='', name:str=None): - self.id = id - self.type = type - self.name = name - self.card = None - self.qr = None - - def show(self): - self.card.show() - - def save(self): - self.card.save(os.path.join(Config.OUT_PATH, str(self.id) + '.png')) - - def generate_qr(self, crypt_id=False): - self.qr = Tools.generate_qr(self.id, Card.QR_PIX_SIZE, Card.QR_BORDER_SIZE) - self.qr = Tools.scale(self.qr, Card.QR_SIZE, False) - - def generate_card(self, rgb_back=(255, 255, 255)): - self.card = Image.open(Config.BAK_PATH) - Tools.draw_text(self.card, self.type, Card.TYPE_POS, Config.TYPE_FONT, Config.WHITE_FONT_COLOR) - if self.type == '': - self.smallen() - - def smallen(self): - blank = Image.new('RGB', (1082, 782),(255,255,255)) - blank.paste(self.card, (0, 0)) - self.card = blank - - @staticmethod - def get_data(): - data = Tools.DataFile.get_content(Assistant._DATA_FILE, 'JSON') - num = data[Assistant.__DATA] - res = [] - for _ in range(num): - res.append(Assistant('A' + str(Assistant.__ID))) - Assistant.__ID += 1 - if Config.TEST: - break - return res - - -class Guest(Assistant): - __ID:int = 1 - __TYPE:str = 'CONVIDAT' - __DATA:str = 'guests' - - def __init__(self, name:str, mtype:str='', logo:str='', has_qr:bool=False): - super().__init__('HackEPS_Guest_' + str(Guest.__ID), (mtype, Guest.__TYPE)[mtype == ''], name) - Guest.__ID += 1 - self.has_qr = has_qr - self.logo = logo - if has_qr: - self.generate_qr(True) - if not logo == '': - self.logopath = os.path.join(Config.RES_PATH, Config.EDITIONS_FOLDER, Config.EDITION, 'images', logo) - - def generate_card(self, rgb_back=(255, 255, 255)): - super().generate_card(rgb_back) - if self.logo != '': - logo = Image.open(self.logopath).convert("RGBA") - logo = Tools.scale(logo, Card.QR_SIZE) - self.card.paste(logo, Card.QR_POS) - elif self.has_qr: - self.card.paste(self.qr, Card.QR_POS) - if self.name != '': - Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) - self.smallen() - - @staticmethod - def get_data(name=None): - res = [] - data = Tools.DataFile.get_content(Guest._DATA_FILE, 'JSON') - for u in data[Guest.__DATA]: - if name is None or u['name'] == name: - res.append(Guest(u['name'], u['type'], u['logo'], u['qr'])) - if Config.TEST or (name is not None and u['name'] == name): - break - return res - - -class Company(Assistant): - __ID:int = 1 - __TYPE:str = 'EMPRESA' - __DATA:str = 'companies' - - def __init__(self, name:str, image): - super().__init__('C' + str(Company.__ID), Company.__TYPE, name) - Company.__ID += 1 - self.logopath = os.path.join(Config.RES_PATH, Config.EDITIONS_FOLDER, Config.EDITION, 'images', image) - - def generate_card(self, rgb_back=(255, 255, 255)): - super().generate_card(rgb_back) - image = Image.open(self.logopath).convert("RGBA") # .resize((550,350), Image.ANTIALIAS) - image = Tools.scale(image, Card.QR_SIZE) - self.card.paste(image, Card.QR_POS) - Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) - self.smallen() - - @staticmethod - def get_data(name=None): - res = [] - data = Tools.DataFile.get_content(Company._DATA_FILE, 'JSON') - for u in data[Company.__DATA]: - for _ in range(u['number_of_cards']): - if name is None or u['name'] == name: - res.append(Company(u['name'], u['logo'])) - if Config.TEST: - break - if Config.TEST or (name is not None and u['name'] == name): - break - return res - - -class Volunteer(Assistant): - __ID:int = 1 - __LOGO_PATH:str = os.path.join(Config.RES_PATH, 'editions', Config.EDITION, 'images', 'logogran.png') - __TYPE:str = 'VOLUNTARI/A' - __DATA:str = 'volunteers' - - def __init__(self, name:str): - super().__init__('V' + str(Volunteer.__ID), Volunteer.__TYPE, name) - Volunteer.__ID += 1 - - def generate_card(self, rgb_back=(255, 255, 255)): - super().generate_card(rgb_back) - image = Image.open(Volunteer.__LOGO_PATH).convert("RGBA") - image = Tools.scale(image, Card.QR_SIZE) - self.card.paste(image, Card.QR_POS) - Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) - self.smallen() - - @staticmethod - def get_data(name=None): - res = [] - data = Tools.DataFile.get_content(Volunteer._DATA_FILE, 'JSON') - for u in data[Volunteer.__DATA]: - if name is None or name == u['name']: - res.append(Volunteer(u['name'])) - if Config.TEST or (name is not None and name == u['name']): - break - return res - -class Mentor(Assistant): - __ID:int = 1 - __LOGO_PATH:str = os.path.join(Config.RES_PATH, 'editions', Config.EDITION, 'images', 'logogran.png') - __TYPE:str = 'MENTOR/A' - __DATA:str = 'mentors' - - def __init__(self, name:str): - super().__init__('M' + str(Mentor.__ID), Mentor.__TYPE, name) - Mentor.__ID += 1 - - def generate_card(self, rgb_back=(255, 255, 255)): - super().generate_card(rgb_back) - image = Image.open(Mentor.__LOGO_PATH).convert("RGBA") - image = Tools.scale(image, Card.QR_SIZE) - self.card.paste(image, Card.QR_POS) - Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) - self.smallen() - - @staticmethod - def get_data(name=None): - res = [] - data = Tools.DataFile.get_content(Mentor._DATA_FILE, 'JSON') - for u in data[Mentor.__DATA]: - if name is None or name == u['name']: - res.append(Mentor(u['name'])) - if Config.TEST or (name is not None and name == u['name']): - break - return res - -class Organizer(Assistant): - __ID:int = 1 - __LOGO_PATH:str = os.path.join(Config.RES_PATH, 'editions', Config.EDITION, 'images', 'logogran.png') - __TYPE:str = 'ORGANIZACIÓ' - __DATA:str = 'organizers' - - def __init__(self, name): - super().__init__('O' + str(Organizer.__ID), Organizer.__TYPE, name) - Organizer.__ID += 1 - - def generate_card(self, rgb_back=(255, 255, 255)): - super().generate_card(rgb_back) - image = Image.open(Organizer.__LOGO_PATH).convert("RGBA") - image = Tools.scale(image, Card.QR_SIZE) - self.card.paste(image, Card.QR_POS) - Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) - # Tools.draw_text(self.card, self.name, Card.NAME_POS, Config.NAME_FONT, Config.WHITE_FONT_COLOR, False) - self.smallen() - - @staticmethod - def get_data(name=None): - res = [] - print(Organizer._DATA_FILE) - data = Tools.DataFile.get_content(Organizer._DATA_FILE, 'JSON') - for u in data[Organizer.__DATA]: - if name is None or u['name'] == name: - res.append(Organizer(u['name'])) - if Config.TEST or (name is not None and u['name'] == name): - break - return res - - -class Contestant(Assistant): - __CRYPT_ID = False - __TYPE:str = 'HACKER' - __FIREBASE = None - __FIRE_PATH:str = Config.DB_PATH_T if Config.TEST else Config.DB_PATH - - def __init__(self, id, data): - super().__init__(id, Contestant.__TYPE) - self.generate_qr() - self.name = data['fullName'] - self.nick = '\"' + data['nickname'] + '\"' - if Config.TEST: - Contestant.__FIRE_PATH = Config.DB_PATH_T - - def generate_card(self, rgb_back=(255, 255, 255)): - super().generate_card(rgb_back) - self.card.paste(self.qr, Card.QR_POS) - Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) - self.smallen() - - @staticmethod - def __firebase_init(cred): - if Contestant.__FIREBASE is None: - Contestant.__FIREBASE = firebase_admin.initialize_app(cred) - return Contestant.__FIREBASE - - @staticmethod - def get_data(id=None, name=None): - cred = firebase_admin.credentials.Certificate(Config.DB_CERT_PATH) - Contestant.__firebase_init(cred) - db = firestore.client() - users_ref = db.collection(Contestant.__FIRE_PATH) - usrs = users_ref.stream() - users = [] - for usr in usrs: - if ((id is None and name is None) - or (id is not None and usr.id == id) - or (name is not None and name == usr.to_dict()['fullName'])): - users.append(Contestant(usr.id, usr.to_dict())) - return users +import os + +# import firebase_admin +from PIL import Image +# from firebase_admin import firestore + +import Config +import Tools + +from api_connector import get_accepted + + +class Card: + QR_PIX_SIZE = 1 + QR_POS = (450, 78) + _QR_SIZE = 267 + QR_SIZE = (_QR_SIZE, _QR_SIZE) + QR_BORDER_SIZE = 0 + TYPE_POS = (0, 475) + NAME_POS = (QR_POS[0], 370) + NICK_POS = (1198, 870) + + +class Assistant(object): + __ID:int = 1 + __DATA:str = 'empty' + _DATA_FILE:str = Config.DATA_PATH + + def __init__(self, id:str, type:str='', name:str=None): + self.id = id + self.type = type + self.name = name + self.card = None + self.qr = None + self.code = None + + def show(self): + self.card.show() + + def save(self): + self.card.save(os.path.join(Config.OUT_PATH, str(self.id) + '.png')) + + def generate_qr(self, crypt_id=False): + if self.code: + self.qr = Tools.generate_qr(self.code, Card.QR_PIX_SIZE, Card.QR_BORDER_SIZE) + else: + self.qr = Tools.generate_qr(self.id, Card.QR_PIX_SIZE, Card.QR_BORDER_SIZE) + self.qr = Tools.scale(self.qr, Card.QR_SIZE, False) + + def generate_card(self, rgb_back=(255, 255, 255)): + self.card = Image.open(Config.BAK_PATH) + Tools.draw_text(self.card, self.type, Card.TYPE_POS, Config.TYPE_FONT, Config.WHITE_FONT_COLOR) + if self.type == '': + self.smallen() + + def smallen(self): + blank = Image.new('RGB', (1082, 782),(255,255,255)) + blank.paste(self.card, (0, 0)) + self.card = blank + + @staticmethod + def get_data(): + data = Tools.DataFile.get_content(Assistant._DATA_FILE, 'JSON') + num = data[Assistant.__DATA] + res = [] + for _ in range(num): + res.append(Assistant('A' + str(Assistant.__ID))) + Assistant.__ID += 1 + if Config.TEST: + break + return res + + +class Guest(Assistant): + __ID:int = 1 + __TYPE:str = 'CONVIDAT' + __DATA:str = 'guests' + + def __init__(self, name:str, mtype:str='', logo:str='', has_qr:bool=False): + super().__init__('HackEPS_Guest_' + str(Guest.__ID), (mtype, Guest.__TYPE)[mtype == ''], name) + Guest.__ID += 1 + self.has_qr = has_qr + self.logo = logo + if has_qr: + self.generate_qr(True) + if not logo == '': + self.logopath = os.path.join(Config.RES_PATH, Config.EDITIONS_FOLDER, Config.EDITION, 'images', logo) + + def generate_card(self, rgb_back=(255, 255, 255)): + super().generate_card(rgb_back) + if self.logo != '': + logo = Image.open(self.logopath).convert("RGBA") + logo = Tools.scale(logo, Card.QR_SIZE) + self.card.paste(logo, Card.QR_POS) + elif self.has_qr: + self.card.paste(self.qr, Card.QR_POS) + if self.name != '': + Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) + self.smallen() + + @staticmethod + def get_data(name=None): + res = [] + data = Tools.DataFile.get_content(Guest._DATA_FILE, 'JSON') + for u in data[Guest.__DATA]: + if name is None or u['name'] == name: + res.append(Guest(u['name'], u['type'], u['logo'], u['qr'])) + if Config.TEST or (name is not None and u['name'] == name): + break + return res + + +class Company(Assistant): + __ID:int = 1 + __TYPE:str = 'EMPRESA' + __DATA:str = 'companies' + + def __init__(self, name:str, image): + super().__init__('C' + str(Company.__ID), Company.__TYPE, name) + Company.__ID += 1 + self.logopath = os.path.join(Config.RES_PATH, Config.EDITIONS_FOLDER, Config.EDITION, 'images', image) + + def generate_card(self, rgb_back=(255, 255, 255)): + super().generate_card(rgb_back) + image = Image.open(self.logopath).convert("RGBA") # .resize((550,350), Image.ANTIALIAS) + image = Tools.scale(image, Card.QR_SIZE) + self.card.paste(image, Card.QR_POS) + Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) + self.smallen() + + @staticmethod + def get_data(name=None): + res = [] + data = Tools.DataFile.get_content(Company._DATA_FILE, 'JSON') + for u in data[Company.__DATA]: + for _ in range(u['number_of_cards']): + if name is None or u['name'] == name: + res.append(Company(u['name'], u['logo'])) + if Config.TEST: + break + if Config.TEST or (name is not None and u['name'] == name): + break + return res + + +class Volunteer(Assistant): + __ID:int = 1 + __LOGO_PATH:str = os.path.join(Config.RES_PATH, 'editions', Config.EDITION, 'images', 'logogran.png') + __TYPE:str = 'VOLUNTARI/A' + __DATA:str = 'volunteers' + + def __init__(self, name:str): + super().__init__('V' + str(Volunteer.__ID), Volunteer.__TYPE, name) + Volunteer.__ID += 1 + + def generate_card(self, rgb_back=(255, 255, 255)): + super().generate_card(rgb_back) + image = Image.open(Volunteer.__LOGO_PATH).convert("RGBA") + image = Tools.scale(image, Card.QR_SIZE) + self.card.paste(image, Card.QR_POS) + Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) + self.smallen() + + @staticmethod + def get_data(name=None): + res = [] + data = Tools.DataFile.get_content(Volunteer._DATA_FILE, 'JSON') + for u in data[Volunteer.__DATA]: + if name is None or name == u['name']: + res.append(Volunteer(u['name'])) + if Config.TEST or (name is not None and name == u['name']): + break + return res + +class Mentor(Assistant): + __ID:int = 1 + __LOGO_PATH:str = os.path.join(Config.RES_PATH, 'editions', Config.EDITION, 'images', 'logogran.png') + __TYPE:str = 'MENTOR/A' + __DATA:str = 'mentors' + + def __init__(self, name:str): + super().__init__('M' + str(Mentor.__ID), Mentor.__TYPE, name) + Mentor.__ID += 1 + + def generate_card(self, rgb_back=(255, 255, 255)): + super().generate_card(rgb_back) + image = Image.open(Mentor.__LOGO_PATH).convert("RGBA") + image = Tools.scale(image, Card.QR_SIZE) + self.card.paste(image, Card.QR_POS) + Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) + self.smallen() + + @staticmethod + def get_data(name=None): + res = [] + data = Tools.DataFile.get_content(Mentor._DATA_FILE, 'JSON') + for u in data[Mentor.__DATA]: + if name is None or name == u['name']: + res.append(Mentor(u['name'])) + if Config.TEST or (name is not None and name == u['name']): + break + return res + +class Organizer(Assistant): + __ID:int = 1 + __LOGO_PATH:str = os.path.join(Config.RES_PATH, 'editions', Config.EDITION, 'images', 'logogran.png') + __TYPE:str = 'ORGANIZACIÓ' + __DATA:str = 'organizers' + + def __init__(self, name): + super().__init__('O' + str(Organizer.__ID), Organizer.__TYPE, name) + Organizer.__ID += 1 + + def generate_card(self, rgb_back=(255, 255, 255)): + super().generate_card(rgb_back) + image = Image.open(Organizer.__LOGO_PATH).convert("RGBA") + image = Tools.scale(image, Card.QR_SIZE) + self.card.paste(image, Card.QR_POS) + Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) + # Tools.draw_text(self.card, self.name, Card.NAME_POS, Config.NAME_FONT, Config.WHITE_FONT_COLOR, False) + self.smallen() + + @staticmethod + def get_data(name=None): + res = [] + print(Organizer._DATA_FILE) + data = Tools.DataFile.get_content(Organizer._DATA_FILE, 'JSON') + for u in data[Organizer.__DATA]: + if name is None or u['name'] == name: + res.append(Organizer(u['name'])) + if Config.TEST or (name is not None and u['name'] == name): + break + return res + +import PrivateConfig +class Contestant(Assistant): + __CRYPT_ID = False + __TYPE:str = 'HACKER' + __FIREBASE = None + __FIRE_PATH:str = Config.DB_PATH_T if Config.TEST else Config.DB_PATH + + def __init__(self, id, data): + super().__init__(id, Contestant.__TYPE) + self.code = data['code'] + self.generate_qr() + self.name = data['name'] + self.nick = '\"' + data['nickname'] + '\"' + if Config.TEST: + Contestant.__FIRE_PATH = Config.DB_PATH_T + + def generate_card(self, rgb_back=(255, 255, 255)): + super().generate_card(rgb_back) + self.card.paste(self.qr, Card.QR_POS) + Tools.centrate_text_relative(self.card, self.name,Config.NAME_FONT, Card.NAME_POS, Card.QR_SIZE) + self.smallen() + + @staticmethod + def __firebase_init(cred): + if Contestant.__FIREBASE is None: + Contestant.__FIREBASE = firebase_admin.initialize_app(cred) + return Contestant.__FIREBASE + + @staticmethod + def get_data(id=None, name=None): + # cred = firebase_admin.credentials.Certificate(Config.DB_CERT_PATH) + # Contestant.__firebase_init(cred) + # db = firestore.client() + # users_ref = db.collection(Contestant.__FIRE_PATH) + # usrs = users_ref.stream() + usrs = get_accepted() + users = [] + for usr in usrs: + if ((id is None and name is None) + or (id is not None and usr['id'] == id) + or (name is not None and name == usr.name)): + # or (name is not None and name == usr.to_dict()['fullName'])): + users.append(Contestant(usr['id'], usr)) + return users diff --git a/PrivateConfig.sample.py b/PrivateConfig.sample.py new file mode 100644 index 0000000..2644fe9 --- /dev/null +++ b/PrivateConfig.sample.py @@ -0,0 +1,2 @@ +SERVICE_TOKEN = 'backend SERVICE TOKEN' +BASE_URL = 'backend url' \ No newline at end of file diff --git a/README.md b/README.md index d069e03..89f58ed 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# IdentificationGenerator -Program used to generate Identification cards - - -to run as a container -- docker build -t test . +# IdentificationGenerator +Program used to generate Identification cards + + +to run as a container +- docker build -t test . - docker run -it test /bin/bash \ No newline at end of file diff --git a/Tools.py b/Tools.py index 8c2405c..c80988c 100644 --- a/Tools.py +++ b/Tools.py @@ -1,130 +1,130 @@ -import hashlib -import json -import os - -import qrcode -from PIL import ImageDraw, Image -import Config - - -def create_dir(path): - exists = os.path.isdir(path) - if not exists: - try: - os.mkdir(path) - except OSError: - raise OSError('dir creation error') - - -def empty_dir(path, delete_files=True, delete_dirs=True): - exists = os.path.isdir(path) - if exists and (delete_files or delete_dirs): - for root, dirs, files in os.walk(path): - if delete_files: - for file in files: - os.remove(os.path.join(root, file)) - if delete_dirs: - for dir in dirs: - os.remove(os.path.join(root, dir)) - - -def draw_text(image, text, pos, font, fill, centrate=True, mayus=True): - if mayus: - text = text.upper() - draw = ImageDraw.Draw(image) - w, h = draw.textsize(text, font=font) - if centrate: - ImageDraw.Draw(image).text(((image.width-w)/2, pos[1]), text, font=font,fill=fill) - else: - ImageDraw.Draw(image).text(pos, text, font=font,fill=fill) - -def centrate_text_relative(image, text, font, relative_pos, relative_size, mayus=True): - #centrate relative on x and split in 2 lines if text width is bigger than relative_size - if mayus: - text = text.upper() - draw = ImageDraw.Draw(image) - w, h = draw.textsize(text, font=font) - x = relative_pos[0] + (relative_size[0] - w) / 2 - y = relative_pos[1] - if w > relative_size[0]: - #split in 2 lines - words = text.split(' ') - line1 = '' - line2 = '' - for word in words: - if draw.textsize(line1 + ' ' + word, font=font)[0] < relative_size[0]: - line1 += ' ' + word - else: - line2 += ' ' + word - x1 = relative_pos[0] + (relative_size[0] - draw.textsize(line1, font=font)[0]) / 2 - x2 = relative_pos[0] + (relative_size[0] - draw.textsize(line2, font=font)[0]) / 2 - draw.text((x1, y), line1, font=font) - draw.text((x2, y + h), line2, font=font) - else: - ImageDraw.Draw(image).text((x, y), text, font=font) - -def scale(image, max_size, add_mask=True, method=Image.ANTIALIAS): - """ - resize 'image' to 'max_size' keeping the aspect ratio - and place it in center of white 'max_size' image - """ - im_aspect = float(image.size[0]) / float(image.size[1]) - out_aspect = float(max_size[0]) / float(max_size[1]) - if im_aspect >= out_aspect: - scaled = image.resize((max_size[0], int((float(max_size[0]) / im_aspect) + 0.5)), method) - else: - scaled = image.resize((int((float(max_size[1]) * im_aspect) + 0.5), max_size[1]), method) - - offset = (((max_size[0] - scaled.size[0]) / 2), ((max_size[1] - scaled.size[1]) / 2)) - back = Image.new("RGBA", max_size, Config.BAK_COLOR) - if add_mask: - back.paste(scaled, (int(offset[0]), int(offset[1])), scaled) - else: - back.paste(scaled, (int(offset[0]), int(offset[1]))) - return back - -def generate_qr(input, size, border_size): - qr = qrcode.QRCode( - version=2, - error_correction=qrcode.constants.ERROR_CORRECT_H, - box_size=size, - border=border_size) - qr.add_data(input) - qr.make(fit=True) - qr = qr.make_image() - return qr - - -def crypt(input, method='md5'): - m = hashlib.new(method) - m.update(bytes(input, 'utf')) - return str(m.digest()) - - -class DataFile: - __contents = {} - - @staticmethod - def get_content(filepath, type, reload_if_cached=False): - if not reload_if_cached and filepath in DataFile.__contents: - return DataFile.__contents[filepath] - else: - with open(filepath, 'r', encoding='utf-8') as json_file: - if type == 'JSON': - data = json.load(json_file) - DataFile.__contents[filepath] = data - return data - else: - raise Exception(NotImplemented) - - @staticmethod - def clear_cached_content(filepath): - if filepath in DataFile.__contents: - del DataFile.__contents[filepath] - return True - else: - return False - - @staticmethod - def clear_cache(): - DataFile.__contents = {} +import hashlib +import json +import os + +import qrcode +from PIL import ImageDraw, Image +import Config + + +def create_dir(path): + exists = os.path.isdir(path) + if not exists: + try: + os.mkdir(path) + except OSError: + raise OSError('dir creation error') + + +def empty_dir(path, delete_files=True, delete_dirs=True): + exists = os.path.isdir(path) + if exists and (delete_files or delete_dirs): + for root, dirs, files in os.walk(path): + if delete_files: + for file in files: + os.remove(os.path.join(root, file)) + if delete_dirs: + for dir in dirs: + os.remove(os.path.join(root, dir)) + + +def draw_text(image, text, pos, font, fill, centrate=True, mayus=True): + if mayus: + text = text.upper() + draw = ImageDraw.Draw(image) + w, h = draw.textsize(text, font=font) + if centrate: + ImageDraw.Draw(image).text(((image.width-w)/2, pos[1]), text, font=font,fill=fill) + else: + ImageDraw.Draw(image).text(pos, text, font=font,fill=fill) + +def centrate_text_relative(image, text, font, relative_pos, relative_size, mayus=True): + #centrate relative on x and split in 2 lines if text width is bigger than relative_size + if mayus: + text = text.upper() + draw = ImageDraw.Draw(image) + w, h = draw.textsize(text, font=font) + x = relative_pos[0] + (relative_size[0] - w) / 2 + y = relative_pos[1] + if w > relative_size[0]: + #split in 2 lines + words = text.split(' ') + line1 = '' + line2 = '' + for word in words: + if draw.textsize(line1 + ' ' + word, font=font)[0] < relative_size[0]: + line1 += ' ' + word + else: + line2 += ' ' + word + x1 = relative_pos[0] + (relative_size[0] - draw.textsize(line1, font=font)[0]) / 2 + x2 = relative_pos[0] + (relative_size[0] - draw.textsize(line2, font=font)[0]) / 2 + draw.text((x1, y), line1, font=font) + draw.text((x2, y + h), line2, font=font) + else: + ImageDraw.Draw(image).text((x, y), text, font=font) + +def scale(image, max_size, add_mask=True, method=Image.ANTIALIAS): + """ + resize 'image' to 'max_size' keeping the aspect ratio + and place it in center of white 'max_size' image + """ + im_aspect = float(image.size[0]) / float(image.size[1]) + out_aspect = float(max_size[0]) / float(max_size[1]) + if im_aspect >= out_aspect: + scaled = image.resize((max_size[0], int((float(max_size[0]) / im_aspect) + 0.5)), method) + else: + scaled = image.resize((int((float(max_size[1]) * im_aspect) + 0.5), max_size[1]), method) + + offset = (((max_size[0] - scaled.size[0]) / 2), ((max_size[1] - scaled.size[1]) / 2)) + back = Image.new("RGBA", max_size, Config.BAK_COLOR) + if add_mask: + back.paste(scaled, (int(offset[0]), int(offset[1])), scaled) + else: + back.paste(scaled, (int(offset[0]), int(offset[1]))) + return back + +def generate_qr(input, size, border_size): + qr = qrcode.QRCode( + version=2, + error_correction=qrcode.constants.ERROR_CORRECT_H, + box_size=size, + border=border_size) + qr.add_data(input) + qr.make(fit=True) + qr = qr.make_image() + return qr + + +def crypt(input, method='md5'): + m = hashlib.new(method) + m.update(bytes(input, 'utf')) + return str(m.digest()) + + +class DataFile: + __contents = {} + + @staticmethod + def get_content(filepath, type, reload_if_cached=False): + if not reload_if_cached and filepath in DataFile.__contents: + return DataFile.__contents[filepath] + else: + with open(filepath, 'r', encoding='utf-8') as json_file: + if type == 'JSON': + data = json.load(json_file) + DataFile.__contents[filepath] = data + return data + else: + raise Exception(NotImplemented) + + @staticmethod + def clear_cached_content(filepath): + if filepath in DataFile.__contents: + del DataFile.__contents[filepath] + return True + else: + return False + + @staticmethod + def clear_cache(): + DataFile.__contents = {} diff --git a/api_connector.py b/api_connector.py new file mode 100644 index 0000000..c888dab --- /dev/null +++ b/api_connector.py @@ -0,0 +1,23 @@ +# import http.client +import requests +import json +import PrivateConfig + + + +def send_request(endpoint: str): + url = PrivateConfig.BASE_URL + endpoint + headers = { + "Authorization": "Bearer " + PrivateConfig.SERVICE_TOKEN, + } + r = requests.get(url, headers=headers) + +# some JSON: + +# parse x: + print(json.loads(r.content)[0]['id']) + return (json.loads(r.content)) + return r + +def get_accepted(): + return send_request('/event/1/get_approved_hackers') diff --git a/main.py b/main.py index 23d2916..caa6904 100644 --- a/main.py +++ b/main.py @@ -1,26 +1,26 @@ -import Config -import Model -import Tools -from PIL import Image -import os - -users = [] -users += Model.Contestant.get_data() -users += Model.Organizer.get_data() -users += Model.Volunteer.get_data() -users += Model.Mentor.get_data() -users += Model.Company.get_data() -users += Model.Guest.get_data() -users += Model.Assistant.get_data() - -Tools.create_dir(Config.OUT_PATH) -Tools.empty_dir(Config.OUT_PATH) - -i = 0 -for u in users: - u.generate_card() - u.save() - i+=1 - # break - +import Config +import Model +import Tools +from PIL import Image +import os + +users = [] +users += Model.Contestant.get_data() +# users += Model.Organizer.get_data() +# users += Model.Volunteer.get_data() +# users += Model.Mentor.get_data() +# users += Model.Company.get_data() +# users += Model.Guest.get_data() +# users += Model.Assistant.get_data() + +Tools.create_dir(Config.OUT_PATH) +Tools.empty_dir(Config.OUT_PATH) + +i = 0 +for u in users: + u.generate_card() + u.save() + i+=1 + break + print('Generated ' + str(i) + ' cards') \ No newline at end of file diff --git a/old.requirements.txt b/old.requirements.txt index 57004d6..c7a0cc1 100644 --- a/old.requirements.txt +++ b/old.requirements.txt @@ -1,32 +1,32 @@ -CacheControl==0.12.5 -cachetools==3.1.1 -certifi==2019.9.11 -chardet==3.0.4 -firebase-admin==3.2.0 -google-api-core==1.14.3 -google-api-python-client==1.7.11 -google-auth==1.7.1 -google-auth-httplib2==0.0.3 -google-cloud-core==1.0.3 -google-cloud-firestore==1.6.0 -google-cloud-storage==1.23.0 -google-resumable-media==0.5.0 -googleapis-common-protos==1.6.0 -# grpcio==1.25.0 -grpcio==1.50.0 -httplib2==0.19.0 -idna==2.8 -msgpack==0.6.2 -Pillow==8.3.2 -# pkg-resources==0.0.0 -# protobuf==3.15.0 -protobuf==4.21.6 -pyasn1==0.4.7 -pyasn1-modules==0.2.7 -pytz==2019.3 -qrcode==6.1 -requests==2.22.0 -rsa==4.0 -six==1.13.0 -uritemplate==3.0.0 +CacheControl==0.12.5 +cachetools==3.1.1 +certifi==2019.9.11 +chardet==3.0.4 +firebase-admin==3.2.0 +google-api-core==1.14.3 +google-api-python-client==1.7.11 +google-auth==1.7.1 +google-auth-httplib2==0.0.3 +google-cloud-core==1.0.3 +google-cloud-firestore==1.6.0 +google-cloud-storage==1.23.0 +google-resumable-media==0.5.0 +googleapis-common-protos==1.6.0 +# grpcio==1.25.0 +grpcio==1.50.0 +httplib2==0.19.0 +idna==2.8 +msgpack==0.6.2 +Pillow==8.3.2 +# pkg-resources==0.0.0 +# protobuf==3.15.0 +protobuf==4.21.6 +pyasn1==0.4.7 +pyasn1-modules==0.2.7 +pytz==2019.3 +qrcode==6.1 +requests==2.22.0 +rsa==4.0 +six==1.13.0 +uritemplate==3.0.0 urllib3==1.22.0 \ No newline at end of file diff --git a/resources/editions/data_sample.json b/resources/editions/data_sample.json index 411efb8..5cc3461 100644 --- a/resources/editions/data_sample.json +++ b/resources/editions/data_sample.json @@ -1,15 +1,15 @@ -{ - "empty": 5, - "organizers": [ - {"name":"Ton Llucià Senserrich"} - ], - "volunteers": [ - {"name":"Ton Llucià Senserrich"} - ], - "companies": [ - {"name":"Ton Llucià Senserrich","number_of_cards":5,"logo":"logo.png"} - ], - "guests": [ - {"name":"Ton Llucià Senserrich","type":"HACKER","qr":true} - ] -} +{ + "empty": 5, + "organizers": [ + {"name":"Ton Llucià Senserrich"} + ], + "volunteers": [ + {"name":"Ton Llucià Senserrich"} + ], + "companies": [ + {"name":"Ton Llucià Senserrich","number_of_cards":5,"logo":"logo.png"} + ], + "guests": [ + {"name":"Ton Llucià Senserrich","type":"HACKER","qr":true} + ] +} diff --git a/test.py b/test.py index ee2f8d2..f1cf8ed 100644 --- a/test.py +++ b/test.py @@ -1,71 +1,71 @@ -from reportlab.pdfgen import canvas -from reportlab.lib.pagesizes import A4, landscape -from reportlab.lib.units import mm -from reportlab.lib.utils import ImageReader - -from PIL import Image - -import os - -path = '_out_' -filename = 'test.pdf' -title = 'Test' - -MAXY = 139 -MAXX = -5 -MARGIN = 10 - -def createPDF(path_to_images, document_name, document_title): - - def rowGen(list_of_images): #Creates a list of 4 image rows - - for i in range(0, len(list_of_images), 2): - yield list_of_images[i:i + 2] - - - def renderRow(path_to_images, row, y_pos): #Renders each row to the page - - x_pos = 27.5 #starting x position - thumb_size = 450, 400 #Thumbnail image size - - for i in row: - - img = Image.open(os.path.join(path_to_images, i)) #Opens image as a PIL object - img.thumbnail(thumb_size) #Creates thumbnail - - img = ImageReader(img) #Passes PIL object to the Reportlab ImageReader - - #Lays out the image and filename - pdf.drawImage(img, x_pos * mm , y_pos * mm, width = 317, height = 227, preserveAspectRatio=True, anchor='c') - - x_pos += 150 #Increments the x position ready for the next image - - - images = [i for i in os.listdir(path_to_images) if i.endswith('.png')] #Creates list of images filtering out non .jpgs - row_layout = list(rowGen(images)) #Creates the layout of image rows - - pdf = canvas.Canvas(document_name, pagesize=landscape(A4), pageCompression=1) #Creates the PDF object - pdf.setTitle(document_title) - - rows_rendered = 0 - - y_pos = 113.5 #Sets starting y pos - pdf.setFont('Helvetica', 10) - - for row in row_layout: #Loops through each row in the row_layout list and renders the row. For each 5 rows, makes a new page - - if rows_rendered == 2: - - pdf.showPage() - pdf.setFont('Helvetica', 10) - y_pos = -100 - rows_rendered = 0 - break - - else: - - renderRow(path_to_images, row, y_pos) - y_pos -= 100 - rows_rendered += 1 - pdf.save() +from reportlab.pdfgen import canvas +from reportlab.lib.pagesizes import A4, landscape +from reportlab.lib.units import mm +from reportlab.lib.utils import ImageReader + +from PIL import Image + +import os + +path = '_out_' +filename = 'test.pdf' +title = 'Test' + +MAXY = 139 +MAXX = -5 +MARGIN = 10 + +def createPDF(path_to_images, document_name, document_title): + + def rowGen(list_of_images): #Creates a list of 4 image rows + + for i in range(0, len(list_of_images), 2): + yield list_of_images[i:i + 2] + + + def renderRow(path_to_images, row, y_pos): #Renders each row to the page + + x_pos = 27.5 #starting x position + thumb_size = 450, 400 #Thumbnail image size + + for i in row: + + img = Image.open(os.path.join(path_to_images, i)) #Opens image as a PIL object + img.thumbnail(thumb_size) #Creates thumbnail + + img = ImageReader(img) #Passes PIL object to the Reportlab ImageReader + + #Lays out the image and filename + pdf.drawImage(img, x_pos * mm , y_pos * mm, width = 317, height = 227, preserveAspectRatio=True, anchor='c') + + x_pos += 150 #Increments the x position ready for the next image + + + images = [i for i in os.listdir(path_to_images) if i.endswith('.png')] #Creates list of images filtering out non .jpgs + row_layout = list(rowGen(images)) #Creates the layout of image rows + + pdf = canvas.Canvas(document_name, pagesize=landscape(A4), pageCompression=1) #Creates the PDF object + pdf.setTitle(document_title) + + rows_rendered = 0 + + y_pos = 113.5 #Sets starting y pos + pdf.setFont('Helvetica', 10) + + for row in row_layout: #Loops through each row in the row_layout list and renders the row. For each 5 rows, makes a new page + + if rows_rendered == 2: + + pdf.showPage() + pdf.setFont('Helvetica', 10) + y_pos = -100 + rows_rendered = 0 + break + + else: + + renderRow(path_to_images, row, y_pos) + y_pos -= 100 + rows_rendered += 1 + pdf.save() createPDF(path, filename, title) \ No newline at end of file