IFPass/IFPass.py

284 lines
11 KiB
Python
Raw Normal View History

2018-04-12 14:32:42 +02:00
#!/usr/bin/python3
# Written by Jordan ERNST Q1 2018.
# Contact : pro.ernst@gmail.com
import configparser
2018-04-12 14:32:42 +02:00
import sys
import os
import re
from datetime import date, timedelta
import csv
import code128
import cv2
from pywinauto.findwindows import find_window
from pywinauto.win32functions import SetForegroundWindow
from PIL import Image, ImageDraw, ImageFont
from PyPDF2 import PdfFileReader, PdfFileWriter
import subprocess
from shutil import copyfile
from pyfiglet import Figlet
from colorama import init
from termcolor import colored
version = 'devnocam' # dev/devnocam
2018-04-12 14:32:42 +02:00
config = 'IFPass.conf'
def initialisation():
conf = configparser.ConfigParser()
conf.optionxform = str # For case sensitive config file
if not os.path.exists(config): # Check if config file exists
print('Fichier de configuration introuvable.')
IFPassdir = input(r'Quel est le répertoire IFPass ? (Ex : \\192.168.1.1\IFPass) : ')
printername = input("Quel est le nom de l'imprimante à cartes ? : " )
AcrobatReader = input(r"Quel est le chemain vers Acrobat Reader ? ( Ex : C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe) : ")
conf['DEFAULT'] = {'IFPassdir': IFPassdir, 'printername': printername, 'AcrobatReader': AcrobatReader}
with open(config, 'w') as configfile:
conf.write(configfile)
else:
conf.read(config)
IFPassdir = conf['DEFAULT']['IFPassdir']
printername = conf['DEFAULT']['printername']
AcrobatReader = conf['DEFAULT']['AcrobatReader']
clientsfile = os.path.join(IFPassdir, 'Clients_IFPass.csv')
clientsbkpfile = os.path.join(IFPassdir, 'Clients_IFPass_backup.csv')
imgdir = os.path.join(IFPassdir, 'Cartes')
pdftemplate = os.path.join(IFPassdir, 'Templates', 'IFPass_PDF_Template.pdf')
pngtemplate = os.path.join(IFPassdir, 'Templates', 'IFPass_PNG_Template.png')
fonttemplate = os.path.join(IFPassdir, 'Templates', 'Roboto-Bold.ttf')
2018-04-12 14:32:42 +02:00
if not os.path.exists(imgdir): # Cartes dir creation if it doesn't exist
2018-04-17 16:27:41 +02:00
os.makedirs(imgdir)
if not os.path.exists(clientsfile): # Creation Clients_File if it doesn't exist
2018-04-17 16:27:41 +02:00
with open(clientsfile, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile, delimiter=';')
writer.writerow(['Titre', 'Prénom', 'Nom', 'Numéro de client', "Date d'inscription", "Date d'expiration"])
return IFPassdir, printername, AcrobatReader, clientsfile, clientsbkpfile, imgdir, pdftemplate, pngtemplate, fonttemplate
2018-04-17 16:27:41 +02:00
2018-04-12 14:32:42 +02:00
def get_fullname():
firstname = input("Prénom : ").strip()
firstname = firstname[0].upper() + firstname[1:].lower()
if '-' in firstname:
pos = firstname.find("-")
firstname = firstname[:pos + 1] + firstname[pos + 1].upper() + \
firstname[pos + 2:] # Check if compound name
if ' ' in firstname:
pos = firstname.find(" ")
firstname = firstname[:pos + 1] + firstname[pos + 1].upper() + \
firstname[pos + 2:] # Check if compound name
surname = input("Nom : ").upper().strip()
docteur = yes_or_no('Est-ce un Docteur ?')
if docteur:
titre = 'Dr.'
fullname = titre + ' ' + surname + ' ' + firstname
else:
titre = ''
fullname = surname + ' ' + firstname
return titre, firstname, surname, fullname
def yes_or_no(question):
while "the answer is invalid":
reply = input(question + " O/N : ").lower().strip()
if reply[:1] in ['oui', 'ou', 'o']:
return True
if reply[:1] in ['non', 'no', 'n']:
return False
def getclientID():
with open(clientsfile, 'r', newline='', encoding='utf-8') as csvfile:
lastline = csvfile.readlines()[-1]
lastID = lastline.split(';')[3]
if lastID == "Numéro de client":
clientID = "0000000001"
else:
clientID = str(int(lastID) + 1).zfill(10)
writeindb(clientID)
return clientID
def barcode_gen(clientID):
print("Génération du code barre... ", end='')
barcode = code128.image(clientID, thickness=4) # .save(imgdir + clientID + '.png')
print(colored('[OK]', 'green'))
return barcode
def getpic():
while True:
print("Prendre la photo... ", end='')
sys.stdout.flush()
cap = cv2.VideoCapture(0)
while True: # Loop stream webcam
try:
ret, frame = cap.read()
cv2.rectangle(frame, (170, 73), (470, 407), (0, 255, 0), 2)
2018-04-17 14:31:11 +02:00
cv2.imshow('IFCamera - Touche Espace pour prendre la photo, Echap pour une carte sans photo, Q pour quitter.', frame)
2018-04-12 14:32:42 +02:00
except cv2.error:
2018-04-17 14:31:11 +02:00
print(colored('\nLa webcam est débranchée. Branchez-la, puis relancez le programme.', 'red'))
2018-04-12 14:32:42 +02:00
os.system("pause")
2018-04-17 14:31:11 +02:00
sys.exit()
2018-04-12 14:32:42 +02:00
SetForegroundWindow(find_window(title='IFCamera - Touche Espace '
'pour prendre la photo, Echap pour une carte sans photo, Q pour quitter.'))
k = cv2.waitKey(1)
if k == 27: # Echap
print(colored('[OK]', 'green'))
cv2.destroyAllWindows()
defaultpicture = os.path.join(IFPassdir, 'Templates', 'default_avatar.jpg')
2018-04-12 14:32:42 +02:00
picture = Image.open(defaultpicture)
return picture
elif k & 0xFF == ord(' '): # Space
break
elif k & 0xFF == ord('q'): # Q or q to quit
cap.release()
cv2.destroyAllWindows()
sys.exit()
cap.release()
cv2.destroyAllWindows()
cropped = frame[75:405, 172:468]
cv2.imshow('IFCamera - Espace pour valider, Echap pour modifier, Q pour quitter', cropped)
while True:
k = cv2.waitKey(1)
if k == 27: # Echap
print(colored('[KO]', 'red'))
cv2.destroyAllWindows()
break
elif k & 0xFF == ord(' '): # Space
print(colored('[OK]', 'green'))
cv2.destroyAllWindows()
# Color conversion and cv2 img to Pillow img
cropped = cv2.cvtColor(cropped, cv2.COLOR_BGR2RGB)
picture = Image.fromarray(cropped)
return picture
elif k & 0xFF == ord('q'): # Q or q to quit
cv2.destroyAllWindows()
sys.exit()
def writeindb(clientID):
print("Ajout dans la base de données... ", end="")
with open(clientsfile, 'a', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile, delimiter=';')
writer.writerow([titre, firstname, surname, clientID, dateinsc, dateexp])
print(colored('[OK]', 'green'))
def bkpdb():
copyfile(clientsfile, clientsbkpfile)
def fillcard(barcode):
print("Création de la carte avec les informations...", end='')
im = Image.open(pngtemplate)
draw = ImageDraw.Draw(im)
# Name embedding :
font = ImageFont.truetype(fonttemplate, 45)
draw.text((401, 310), fullname, fill=(0,0,0), font=font)
# Date embedding :
font = ImageFont.truetype(fonttemplate, 30)
draw.text((401, 390), dateexp, fill=(0,0,0), font=font)
# ID embedding :
font = ImageFont.truetype('arial.ttf', 30)
draw.text((693, 560), clientID, fill=(0,0,0), font=font)
# Barcode + picture embedding :
im.paste(barcode,(556, 460))
if version != 'devnocam':
im.paste(picture,(47, 49))
2018-04-12 14:32:42 +02:00
# Create PDF :
im = im.convert("RGB")
im.save(imgdir + clientID + '_Front.pdf', 'PDF', resolution=299.0, quality=98)
print(colored('[OK]', 'green'))
def mergepdf():
cartefilename = os.path.join(imgdir, clientID + '.pdf')
2018-04-12 14:32:42 +02:00
output = PdfFileWriter()
pdf1 = PdfFileReader(imgdir + clientID + '_Front.pdf', 'rb')
recto = pdf1.getPage(0)
output.addPage(recto)
pdf2 = PdfFileReader(pdftemplate, 'rb')
verso = pdf2.getPage(1)
output.addPage(verso)
with open(cartefilename, 'wb') as f:
output.write(f)
os.remove(imgdir + clientID + '_Front.pdf')
return cartefilename
def printcard(cartefilename):
# Working : subprocess.Popen('"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" /h /n /t ' + cartefilename + ' '+ printername, shell=False)
subprocess.Popen('"' + AcrobatReader + '"' + ' /h /n /t ' + cartefilename + ' '+ printername, shell=False)
2018-04-12 14:32:42 +02:00
while "the informations are incorrect": # Loop Filling informations
os.system('cls')
init()
f = Figlet(font='big')
print(colored(f.renderText('IFPass'), 'cyan', attrs=['bold']))
print('Version : ', version)
if version in ('dev', 'devnocam'):
print(colored("\nATTENTION : Il s'agit d'une version en cours de développement, potentiellement instable !", 'red'))
2018-04-12 14:32:42 +02:00
print('\nLe programme IFPass à été écrit par Jordan ERNST Q1 2018.')
print('Pour toute question ou problème contactez-moi à pro.ernst@gmail.com.\n')
titre, firstname, surname, fullname = get_fullname()
dateinsc = date.today()
dateexp = dateinsc + timedelta(days=365)
dateinsc = dateinsc.strftime('%d/%m/%Y')
dateexp = dateexp.strftime('%d/%m/%Y')
changeexp = yes_or_no("Voulez-vous choisir la date d'expiration ?")
2018-04-12 14:32:42 +02:00
if changeexp:
while True:
dateexp = input("Quelle date d'expiration voulez-vous mettre (Format : JJ/MM/AAAA)? : ")
2018-04-12 14:32:42 +02:00
match = re.fullmatch(r'^(0[1-9]|1[0-9]|2[0-9]|3[0-1])/(0[1-9]|1[0-2])/([0-9]){4}$', dateexp)
if match:
break
else:
print('Mauvais format ! JJ/MM/AAAA, exemple : 01/08/2042')
os.system('cls')
print("Titre : ", colored(titre, 'green'))
print("Prénom : ", colored(firstname, 'green'))
print("Nom : ", colored(surname, 'green'))
print("Date d'inscription :", colored(dateinsc, 'green'))
print("Date d'expiration : ", colored(dateexp, 'green'))
correct = yes_or_no("Ces informations sont elles correctes ?")
if correct:
os.system('cls')
IFPassdir, printername, AcrobatReader, clientsfile, clientsbkpfile, imgdir, pdftemplate, pngtemplate, fonttemplate = initialisation()
if version != 'devnocam':
picture = getpic()
2018-04-12 14:32:42 +02:00
clientID = getclientID()
barcode = barcode_gen(clientID)
fillcard(barcode)
cartefilename = mergepdf()
if version not in ('dev', 'devnocam'):
bkpdb()
2018-04-12 14:32:42 +02:00
printcard(cartefilename)
2018-04-17 14:31:11 +02:00
sys.exit()