97 lines
4.4 KiB
Python
Executable File
97 lines
4.4 KiB
Python
Executable File
|
|
#!/usr/bin/env python
|
|
|
|
from argparse import ArgumentParser
|
|
from math import ceil, floor
|
|
from random import randrange, choice
|
|
from reportlab.pdfgen import canvas
|
|
from reportlab.lib.pagesizes import A4
|
|
from reportlab.graphics.shapes import Drawing
|
|
from reportlab.graphics.barcode.qr import QrCodeWidget
|
|
from reportlab.graphics import renderPDF
|
|
from svglib.svglib import svg2rlg
|
|
from urllib.parse import urljoin
|
|
|
|
def generate_random_username(female_nouns, male_nouns, adjectives, used_usernames):
|
|
random_username = None
|
|
while True:
|
|
nouns = choice([female_nouns, male_nouns])
|
|
random_username = f"{adjectives[randrange(len(adjectives)-1)]}{'' if nouns is female_nouns else 'r'}-{nouns[randrange(len(nouns)-1)].lower()}"
|
|
if random_username not in used_usernames:
|
|
used_usernames.add(random_username)
|
|
print(random_username)
|
|
return random_username
|
|
|
|
if __name__ == "__main__":
|
|
parser = ArgumentParser(description="Generates a QR code PDF with random usernames and prints the names to stdout.")
|
|
parser.add_argument("url", help="Base URL, e.g. 'https://url.com'.")
|
|
parser.add_argument("-n", "--number", type=int, help="Amount of requested usernames, defaults to 50.", default=50)
|
|
parser.add_argument("-o", "--output", type=str, help="Output file, defaults to 'qrcodes.pdf'.", default="qrcodes.pdf")
|
|
parser.add_argument("-s", "--size", type=int, help="Ticket height, defaults to 150.", default=150)
|
|
parser.add_argument("-m", "--margin", type=int, help="Margin (depends on printer), defaults to 0.", default=0)
|
|
|
|
args = parser.parse_args()
|
|
|
|
adjectives = set()
|
|
female_nouns = set()
|
|
male_nouns = set()
|
|
with open('adjektive-weiblich.txt', 'r') as file:
|
|
for line in file:
|
|
adjectives.add(line.strip())
|
|
with open('nomen-weiblich.txt', 'r') as file:
|
|
for line in file:
|
|
female_nouns.add(line.strip())
|
|
with open('nomen-maennlich.txt', 'r') as file:
|
|
for line in file:
|
|
male_nouns.add(line.strip())
|
|
adjectives = list(adjectives)
|
|
female_nouns = list(female_nouns)
|
|
male_nouns = list(male_nouns)
|
|
|
|
pdf = canvas.Canvas(args.output, pagesize=A4)
|
|
page_width, page_height = A4
|
|
used_usernames = set()
|
|
|
|
ticket_height = args.size
|
|
qr_code_size = ticket_height/2
|
|
logo = svg2rlg("img/karaoke-outline.svg")
|
|
scaling_factor = ticket_height/logo.height
|
|
logo.scale(scaling_factor, scaling_factor)
|
|
logo_width = logo.width*scaling_factor
|
|
logo_height = logo.height*scaling_factor
|
|
|
|
ticket_width = logo_width + qr_code_size
|
|
codes_per_row = floor((page_width-args.margin*2)/ticket_width)
|
|
codes_per_col = floor((page_height-args.margin*2)/ticket_height)
|
|
if codes_per_col == 0 or codes_per_row == 0:
|
|
raise Exception(f"There is not enough space on A4 page to fit a QR code of size {ticket_width}x{ticket_height}!")
|
|
codes_per_page = codes_per_row*codes_per_col
|
|
required_pages = ceil(args.number/codes_per_page)
|
|
generated_codes = 0
|
|
|
|
for page in range(required_pages):
|
|
for y in range(codes_per_col):
|
|
for x in range(codes_per_row):
|
|
url = urljoin(args.url, generate_random_username(female_nouns, male_nouns, adjectives, used_usernames))
|
|
qr_code = QrCodeWidget(url)
|
|
bounds = qr_code.getBounds()
|
|
|
|
code_width = bounds[2] - bounds[0]
|
|
code_height = bounds[3] - bounds[1]
|
|
|
|
drawing = Drawing(ticket_height, ticket_height, transform=[qr_code_size/code_width, 0, 0, qr_code_size/code_height, 0, 0])
|
|
drawing.add(qr_code)
|
|
renderPDF.draw(logo, pdf, args.margin+ticket_width*(x%codes_per_row), args.margin+ticket_height*(y%codes_per_col))
|
|
pdf.drawString(args.margin+ticket_width*(x%codes_per_row), args.margin+ticket_height*(y%codes_per_col), url)
|
|
|
|
pdf.drawString(args.margin+ticket_width*(x%codes_per_row), args.margin+ticket_height*(y%codes_per_col)+logo_height, "Hier Code scannen")
|
|
pdf.drawString(args.margin+ticket_width*(x%codes_per_row), args.margin+ticket_height*(y%codes_per_col)+logo_height-10, "und Song anmelden!")
|
|
|
|
renderPDF.draw(drawing, pdf, args.margin+ticket_width*(x%codes_per_row)+logo_width, args.margin+ticket_height*(y%codes_per_col))
|
|
generated_codes += 1
|
|
if generated_codes >= args.number:
|
|
pdf.save()
|
|
exit()
|
|
pdf.showPage()
|
|
|
|
pdf.save() |