-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First version for certificate generation #77
Draft
hgingras
wants to merge
25
commits into
main
Choose a base branch
from
certificates
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
eaeea51
First version for certificate generation
5e0bd60
Adding some parameters and french certificate update.
e8a7acf
Editing create_certificate.py and attestation template
b4089a0
Ligne 25, remplacé certificate et ceritificate par attestation et cha…
119152e
Enlevé print(language) ligne 91, Ligne33, ajout de choices pour langu…
6ddf2b0
Ajout de la valeur pour --event_id dans le usage
be039c1
Enleve le / en préfix pour la constante ATTESTATION_CQ_TEMPLATE
f61996a
ajout de os.path.join afin de créer correctement le chemin avec le te…
b104110
Ajout de paramètres dans la section aide des fonctions. Envoie par co…
13d5f21
Added requirements file for certificate. Removed unused import
ccoulombe 7810f30
Changement de nom de variable pour attended_guest
76ff734
Remplacer certification par attestation de participation
0f332e5
Enlève répétition Set template name, Ajustement --send_self et --send…
e291ecd
Enlevé répétition dans send_email
5a3936d
Ajout du fichier config pour email
08a4bad
Changement de nom pour les templates email
5d9d35c
Modified certificate template.
667ef02
build_registratrant_list update
3f83194
Ajustement config
109aa79
Debug self_email
146d307
Corrections pour self-email
4044ed6
Modification argument self_email
23a8d9d
send-self ajustement
d1b933e
Revert "Ajustement config"
03378de
Revert "Ajustement config - enlevé email perso"
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
137 changes: 137 additions & 0 deletions
137
Attestation_template/attestation_template_sample_english_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 125 additions & 0 deletions
125
Attestation_template/attestation_template_sample_french_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
#!/bin/env python3 | ||
|
||
import argparse | ||
import cairosvg | ||
import unidecode | ||
import os | ||
import jinja2 | ||
import click | ||
from datetime import datetime | ||
import interfaces.eventbrite.EventbriteInterface as Eventbrite | ||
|
||
from common import get_config | ||
from common import to_iso8061 | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument("--config_dir", default=".", help="Directory that holds the configuration files") | ||
parser.add_argument("--secrets_dir", default=".", help="Directory that holds the configuration files") | ||
parser.add_argument("--title", default=None, help="Event title") | ||
parser.add_argument("--date", default=None, help="Event date (iso8061) XXXX-XX-XX ; year-month-day") | ||
parser.add_argument("--duration", default=None, help="Event duration in hour") | ||
parser.add_argument("--language", default=None, help="Event language. en = english ; fr = french") | ||
parser.add_argument("--certificate_dir", default="./certificates", help="Directory to write the certificates.") | ||
parser.add_argument("event_id", help="EventBrite event id") | ||
ccoulombe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
parser.add_argument("--certificate_svg_tplt_dir",default="./Attestation_template", help="Directory that holds certificate templates.") | ||
args = parser.parse_args() | ||
ccoulombe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
""" | ||
Usage: | ||
|
||
python3 create_certificate.py 778466443087 | ||
ccoulombe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
|
||
def write_certificates(event, guests, certificate_svg_tplt_dir, language, certificate_dir): | ||
""" | ||
Generates one PDF per attendee | ||
|
||
Parameters | ||
---------- | ||
event : str | ||
EventBrite event id | ||
|
||
guests : dict | ||
Get information for attendees that participated, that is that have their status to `checked in` or `attended`. | ||
get_event_attendees_present(eb_event['id'], fields = ['title', 'email', 'first_name', 'last_name', 'status', 'name', 'order_id']) | ||
|
||
certificate_svg_tplt_dir : directory | ||
Directory that contain the template for the french and english certificate. | ||
|
||
language : str | ||
Event language. en = english ; fr = french | ||
|
||
certificate_dir : directory | ||
Directory to write the certificates. | ||
|
||
Returns | ||
------- | ||
One certificate for each participant in french or english depending on the event language. | ||
|
||
""" | ||
print("--- Generating PDFs ---") | ||
try: | ||
os.mkdir(certificate_dir) | ||
except OSError: | ||
pass | ||
|
||
# Set language: | ||
if not language: | ||
language = event['locale'].split("_")[0] | ||
|
||
elif ((language != "en") and (language != "fr")): | ||
ccoulombe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
print("write_certificates: We do not support other languages than French and English to create a certificate.") | ||
exit(1) | ||
|
||
# Set template name: | ||
if language == "en": | ||
for file in os.listdir(certificate_svg_tplt_dir): | ||
if file == "attestation_template_sample_english_logo.svg": | ||
tpl_name = file | ||
elif language == "fr": | ||
for file in os.listdir(certificate_svg_tplt_dir): | ||
if file == "attestation_template_sample_french_logo.svg": | ||
tpl_name = file | ||
|
||
tpl = jinja2.Environment(loader=jinja2.FileSystemLoader(certificate_svg_tplt_dir)).get_template(tpl_name) | ||
|
||
for guest in guests: | ||
print(f"Generating: {guest['filename']}") | ||
cairosvg.svg2pdf(bytestring=tpl.render(guest).encode('utf-8'), | ||
write_to=guest['filename']) | ||
|
||
def safe_filename(filename): | ||
rules = {"!" : ".", | ||
"@" : "_at_", | ||
"#" : "_no_", | ||
"$" : "S", | ||
"%" : "_per_", | ||
"?" : ".", | ||
"&" : "_and_", | ||
"+" : "_and_", | ||
"*" : "_", | ||
"~" : "_in_", | ||
";" : ".", | ||
":" : ".", | ||
"," : ".", | ||
"/" : "-", | ||
"|" : "-", | ||
"\\": "-", | ||
" " : "_", | ||
"'" : "_", | ||
'"' : "_" } | ||
|
||
filename = unidecode.unidecode(filename) | ||
|
||
for old, new in rules.items(): | ||
filename = filename.replace(old, new) | ||
|
||
return filename.upper() | ||
|
||
def safe_name(name): | ||
rules = {"&" : " and ", | ||
"\\": "/" } | ||
|
||
for old, new in rules.items(): | ||
name = name.replace(old, new) | ||
|
||
return name.upper() | ||
|
||
def build_registrant_list(event, guests, title, duration, date, language, certificate_dir): | ||
""" | ||
Generate a registration list. | ||
|
||
Parameters | ||
---------- | ||
event : str | ||
EventBrite event id | ||
|
||
guests : dict | ||
Get information for attendees that participated, that is that have their status to `checked in` or `attended`. | ||
get_event_attendees_present(eb_event['id'], fields = ['title', 'email', 'first_name', 'last_name', 'status', 'name', 'order_id']) | ||
|
||
title : str | ||
Event title | ||
|
||
duration : float | ||
Event duration in hour | ||
|
||
date : date | ||
Event date (iso8061) XXXX-XX-XX ; year-month-day | ||
|
||
language : str | ||
Event language. en = english ; fr = french | ||
|
||
certificate_dir : directory | ||
Directory to write the certificates. | ||
|
||
---------- | ||
Returns - Python dictionary with formatted attendees information | ||
""" | ||
|
||
# Set title: | ||
if not title: | ||
title = event['name']['text'].strip() | ||
|
||
# Set duration: | ||
if not duration: | ||
time_start = datetime.strptime(event['start']['local'], '%Y-%m-%dT%H:%M:%S') | ||
time_end = datetime.strptime(event['end']['local'], '%Y-%m-%dT%H:%M:%S') | ||
duration = (time_end - time_start).total_seconds() / 3600 | ||
|
||
# Set date: | ||
if not date: | ||
date = to_iso8061(event['start']['local']).date() | ||
|
||
# Set language: | ||
if not language: | ||
language = event['locale'].split("_")[0] | ||
|
||
elif ((language != "en") and (language != "fr")): | ||
ccoulombe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
print("build_registrant_list: write_certificates: We do not support other languages than French and English to create a certificate.") | ||
exit(1) | ||
|
||
# Set filename_template: | ||
filename_template = str(certificate_dir) + "/Attestation_CQ_{}_{}_{}.pdf" | ||
ccoulombe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Complete duration with the right term for time spelling: | ||
if language == "en": | ||
if duration <= 1.0: | ||
duration = str(duration) + " hour." | ||
else: | ||
duration = str(duration) + " hours." | ||
|
||
elif language == "fr": | ||
if duration <= 1.0: | ||
duration = str(duration) + " heure." | ||
else: | ||
duration = str(duration) + " heures." | ||
|
||
attended_guests = [] | ||
|
||
for guest in guests: | ||
|
||
first_name = guests[guest]['first_name'] | ||
last_name = guests[guest]['last_name'] | ||
email = guests[guest]['email'] | ||
order_id = guests[guest]['order_id'] | ||
context = {'workshop' : title, | ||
'first_name' : safe_name(first_name), | ||
'last_name' : safe_name(last_name), | ||
'email' : email, | ||
'date' : date, | ||
'duration' : duration, | ||
'order_id' : order_id, | ||
'filename' : filename_template.format(safe_filename(first_name), | ||
safe_filename(last_name), | ||
order_id) | ||
} | ||
attended_guests.append(context) | ||
|
||
return attended_guests | ||
|
||
|
||
ccoulombe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Read configuration files: | ||
global_config = get_config(args) | ||
|
||
# Initialize EventBrite interface: | ||
eb = Eventbrite.EventbriteInterface(global_config['eventbrite']['api_key']) | ||
|
||
# Get event information: | ||
eb_event = eb.get_event(args.event_id) | ||
|
||
# Get information for attendees that participated, that is that have their status to `checked in` or `attended`: | ||
eb_attendees = eb.get_event_attendees_present(eb_event['id'], fields = ['title', 'email', 'first_name', 'last_name', 'status', 'name', 'order_id']) | ||
|
||
# Generate a registration list: | ||
attended_guest = build_registrant_list(eb_event, eb_attendees, args.title, args.duration, args.date, args.language, args.certificate_dir) | ||
|
||
# Write the certificates: | ||
write_certificates(eb_event, attended_guest, args.certificate_svg_tplt_dir, args.language, args.certificate_dir) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corriger le titre
Ceritificate
->Attestation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay