Skip to content
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
wants to merge 25 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
eaeea51
First version for certificate generation
Feb 23, 2024
5e0bd60
Adding some parameters and french certificate update.
Feb 28, 2024
e8a7acf
Editing create_certificate.py and attestation template
Feb 29, 2024
b4089a0
Ligne 25, remplacé certificate et ceritificate par attestation et cha…
Mar 13, 2024
119152e
Enlevé print(language) ligne 91, Ligne33, ajout de choices pour langu…
Mar 13, 2024
6ddf2b0
Ajout de la valeur pour --event_id dans le usage
Mar 13, 2024
be039c1
Enleve le / en préfix pour la constante ATTESTATION_CQ_TEMPLATE
Mar 13, 2024
f61996a
ajout de os.path.join afin de créer correctement le chemin avec le te…
Mar 13, 2024
b104110
Ajout de paramètres dans la section aide des fonctions. Envoie par co…
Mar 15, 2024
13d5f21
Added requirements file for certificate. Removed unused import
ccoulombe Apr 2, 2024
7810f30
Changement de nom de variable pour attended_guest
Apr 2, 2024
76ff734
Remplacer certification par attestation de participation
Apr 2, 2024
0f332e5
Enlève répétition Set template name, Ajustement --send_self et --send…
Apr 3, 2024
e291ecd
Enlevé répétition dans send_email
Apr 3, 2024
5a3936d
Ajout du fichier config pour email
Apr 3, 2024
08a4bad
Changement de nom pour les templates email
Apr 3, 2024
5d9d35c
Modified certificate template.
Oct 3, 2024
667ef02
build_registratrant_list update
Oct 30, 2024
3f83194
Ajustement config
Nov 4, 2024
109aa79
Debug self_email
Nov 4, 2024
146d307
Corrections pour self-email
Nov 7, 2024
4044ed6
Modification argument self_email
Nov 11, 2024
23a8d9d
send-self ajustement
Dec 16, 2024
d1b933e
Revert "Ajustement config"
Dec 16, 2024
03378de
Revert "Ajustement config - enlevé email perso"
Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 187 additions & 20 deletions create_certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,24 @@
import os
import jinja2
import click
import yaml
import getpass
import smtplib

from datetime import datetime
from email import encoders
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

import interfaces.eventbrite.EventbriteInterface as Eventbrite

from common import get_config
from common import to_iso8061

ATTESTATION_CQ_TEMPLATE = "/Attestation_CQ_{}_{}_{}.pdf"
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved

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")
Expand All @@ -20,16 +32,26 @@
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")
parser.add_argument("--event_id", help="EventBrite event id", required=True)
parser.add_argument("--certificate_svg_tplt_dir",default="./Attestation_template", help="Directory that holds certificate templates.")
parser.add_argument("--gmail_user", help="Gmail username", type=str, default=None)
parser.add_argument("--gmail_password", help="Gmail password", type=str, default=None)
parser.add_argument("--email_tplt_dir", help="Email template directory", default="./email_template")
parser.add_argument("--send_self", default=False, help="Send to yourself")
parser.add_argument("--send_atnd", default=False, help="Send the certificate to each attendee")
parser.add_argument("--self_email", help="Email to send tests to", type=str, default=None)
parser.add_argument('--number_to_send', help="Total number of certificates to send", type=int, default=-1)
args = parser.parse_args()
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved



"""
Usage:

python3 create_certificate.py 778466443087
python3 create_certificate.py --event_id
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved
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
Expand Down Expand Up @@ -66,9 +88,10 @@ def write_certificates(event, guests, certificate_svg_tplt_dir, language, certif
# Set language:
if not language:
language = event['locale'].split("_")[0]
print(language)
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved

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.")
print("We do not support other languages than French and English to create a certificate.")
exit(1)

# Set template name:
Expand Down Expand Up @@ -169,18 +192,17 @@ def build_registrant_list(event, guests, title, duration, date, language, certif

# Set date:
if not date:
date = to_iso8061(event['start']['local']).date()
date = datetime.strptime(event['start']['local'], "%Y-%m-%dT%H:%M:%S")
date = date.strftime("%Y-%m-%d")


# 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.")
print("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"

# Complete duration with the right term for time spelling:
if language == "en":
Expand All @@ -195,6 +217,8 @@ def build_registrant_list(event, guests, title, duration, date, language, certif
else:
duration = str(duration) + " heures."

filename_template = str(certificate_dir) + ATTESTATION_CQ_TEMPLATE
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved

attended_guests = []

for guest in guests:
Expand All @@ -218,21 +242,164 @@ def build_registrant_list(event, guests, title, duration, date, language, certif

return attended_guests

def create_email(gmail_user, guest, email_tplt, send_self, self_email, attach_certificate=True):
"""
Create email, attatch body and PDF certificate

Parameters
----------
gmail_user : str
Gmail username

guest : dict
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'])

email_tplt : dict
Ditionnary with email template.

send_self : bool
Send to yourself.

attach_certificate : bool
If we want certificate to be attached to the email.

self_email: str
Email to send tests to

language : str
Event language. en = english ; fr = french

"""
# Create email
outer = MIMEMultipart()
outer['From'] = gmail_user
if send_self:
if self_email:
outer['To'] = self_email
else:
outer['To'] = gmail_user
else:
outer['To'] = guest['email']
outer['Reply-to'] = email_tplt['replyto']

outer['Subject'] = Header(email_tplt['subject'])

# Attach body
body = MIMEText(email_tplt['message'].format(**guest), 'plain')
outer.attach(body)
print("Outer variable:")
print(outer)

# Attach PDF Certificate
if attach_certificate:
msg = MIMEBase('application', "octet-stream")
with open(guest['filename'], 'rb') as file_:
msg.set_payload(file_.read())
encoders.encode_base64(msg)
msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(guest['filename']))
outer.attach(msg)

return outer


def send_email(event, guests, email_tplt_dir, send_self, number_to_send, language, gmail_user=None, gmail_password=None, self_email=None, attach_certificate=True):
"""
Create email, attatch body and PDF certificate

Parameters
----------
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'])

email_tplt_dir : directory
Directory containing email template in french and english.

"""

if not language:
language = event['locale'].split("_")[0]
elif ((language != "en") and (language != "fr")):
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved
print("We do not support sending email other than in french or english.")
exit(1)

if language == "fr":
for file in os.listdir(email_tplt_dir):
if file == "email_certificates_FR.yml":
email_tplt_file = email_tplt_dir + "/" + file
elif language == "en":
for file in os.listdir(email_tplt_dir):
if file == "email_certificates_EN.yml":
email_tplt_file = email_tplt_dir + "/" + file

email_tplt = {}

with open(email_tplt_file, 'rt', encoding='utf8') as f:
email_tplt = yaml.load(f, Loader=yaml.FullLoader)

if not gmail_user:
gmail_user = input('gmail username: ')
if not gmail_password:
gmail_password = getpass.getpass('gmail password: ')
if not self_email:
self_email = gmail_user

with smtplib.SMTP('smtp.gmail.com', 587) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.login(gmail_user, gmail_password)
nsent = 0

for guest in guests:
email = create_email(gmail_user, guest, email_tplt, args.send_self, args.self_email, attach_certificate)

# Send email
if send_self:
print("okay")
print('sending email to YOU about: {first_name} ({email})...'.format(**guest))
else:
print('sending email to: {first_name} {last_name} ({email})...'.format(**guest))

try:
server.sendmail(email['From'], email['To'], email.as_string())
except smtplib.SMTPAuthenticationError as e:
# If the GMail account is now allowing secure apps, the script will fail.
# read : http://stackabuse.com/how-to-send-emails-with-gmail-using-python/
print('Go to https://myaccount.google.com/lesssecureapps and Allow less secure apps.')
sys.exit(1)
nsent = nsent + 1
if nsent == number_to_send:
break


if __name__ == '__main__':

# 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'])

ccoulombe marked this conversation as resolved.
Show resolved Hide resolved
# Read configuration files:
global_config = get_config(args)
# Generate a registration list:
attended_guest = build_registrant_list(eb_event, eb_attendees, args.title, args.duration, args.date, args.language, args.certificate_dir)
#print(attended_guest)

# Initialize EventBrite interface:
eb = Eventbrite.EventbriteInterface(global_config['eventbrite']['api_key'])
attended_guest_test = [{'workshop': 'Meilleures pratiques en Python : CPU à GPU [en ligne, CPUGPU]', 'first_name': 'PAUL-ANDRÉ', 'last_name': 'ROBILLARD', 'email': '[email protected]', 'date': '2024-02-21', 'duration': '3.0 heures.', 'order_id': '8675624389', 'filename': './certificates/Attestation_CQ_PAUL-ANDRE_ROBILLARD_8675624389.pdf'}, {'workshop': 'Meilleures pratiques en Python : CPU à GPU [en ligne, CPUGPU]', 'first_name': 'JOSPER JUNIOR', 'last_name': 'JOSEPH', 'email': '[email protected]', 'date': '2024-02-21', 'duration': '3.0 heures.', 'order_id': '8681885929', 'filename': './certificates/Attestation_CQ_JOSPER_JUNIOR_JOSEPH_8681885929.pdf'}, {'workshop': 'Meilleures pratiques en Python : CPU à GPU [en ligne, CPUGPU]', 'first_name': 'GANIYOU', 'last_name': 'DA SILVA', 'email': '[email protected]', 'date': '2024-02-21', 'duration': '3.0 heures.', 'order_id': '8682499269', 'filename': './certificates/Attestation_CQ_GANIYOU_DA_SILVA_8682499269.pdf'}, {'workshop': 'Meilleures pratiques en Python : CPU à GPU [en ligne, CPUGPU]', 'first_name': 'LARA', 'last_name': 'HARTER', 'email': '[email protected]', 'date': '2024-02-21', 'duration': '3.0 heures.', 'order_id': '8685161409', 'filename': './certificates/Attestation_CQ_LARA_HARTER_8685161409.pdf'}]
ccoulombe marked this conversation as resolved.
Show resolved Hide resolved
print(attended_guest_test)

# Get event information:
eb_event = eb.get_event(args.event_id)
# Write the certificates:
write_certificates(eb_event, attended_guest_test, args.certificate_svg_tplt_dir, args.language, args.certificate_dir)

# 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'])
# Create email:

# Generate a registration list:
attended_guest = build_registrant_list(eb_event, eb_attendees, args.title, args.duration, args.date, args.language, args.certificate_dir)
if args.send_atnd or args.send_self:
send_email(eb_event, attended_guest_test, args.email_tplt_dir, args.send_self, args.number_to_send, args.language, args.gmail_user, args.gmail_password, args.self_email, attach_certificate=True)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attended_guest_test n'existe pas

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J'ai oublié de changer le nom de la variable. J'ai fait la correction.


# Write the certificates:
write_certificates(eb_event, attended_guest, args.certificate_svg_tplt_dir, args.language, args.certificate_dir)