Remove old backend. Byebye.
This commit is contained in:
parent
e222962eee
commit
f6ad73ef85
@ -1 +0,0 @@
|
|||||||
[]
|
|
@ -1,60 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
from pathlib import Path
|
|
||||||
from string import Template
|
|
||||||
import sys
|
|
||||||
|
|
||||||
DEFAULT_SHEET_TEMPLATE = Path(__file__).parent / 'planche.svg.in'
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description='Make a sheet with 12 stickers')
|
|
||||||
parser.add_argument('--template',
|
|
||||||
'-t',
|
|
||||||
default=DEFAULT_SHEET_TEMPLATE,
|
|
||||||
help='path to the sheet template')
|
|
||||||
parser.add_argument('--out',
|
|
||||||
'-o',
|
|
||||||
default=sys.stdout,
|
|
||||||
type=argparse.FileType('w'),
|
|
||||||
help='output path (default: stdout)')
|
|
||||||
parser.add_argument('sticker',
|
|
||||||
type=argparse.FileType('r'),
|
|
||||||
default=sys.stdin,
|
|
||||||
nargs='?',
|
|
||||||
help='path to the sticker SVG (default: stdin)')
|
|
||||||
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def makeplanche(sticker, out, template=DEFAULT_SHEET_TEMPLATE):
|
|
||||||
with open(template) as tpl:
|
|
||||||
tpl_data = tpl.read()
|
|
||||||
|
|
||||||
lines = sticker.readlines()
|
|
||||||
if lines[0].startswith('<?xml'):
|
|
||||||
lines = lines[1:]
|
|
||||||
sticker_data = ''.join(lines)
|
|
||||||
|
|
||||||
subs = {
|
|
||||||
'left0': sticker_data,
|
|
||||||
'left1': sticker_data,
|
|
||||||
'left2': sticker_data,
|
|
||||||
'left3': sticker_data,
|
|
||||||
'left4': sticker_data,
|
|
||||||
'left5': sticker_data,
|
|
||||||
'right0': sticker_data,
|
|
||||||
'right1': sticker_data,
|
|
||||||
'right2': sticker_data,
|
|
||||||
'right3': sticker_data,
|
|
||||||
'right4': sticker_data,
|
|
||||||
'right5': sticker_data,
|
|
||||||
}
|
|
||||||
|
|
||||||
out.write(Template(tpl_data).substitute(subs))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
makeplanche(**vars(parse_args()))
|
|
@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
from string import Template
|
|
||||||
import sys
|
|
||||||
import typing
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
|
||||||
parser = argparse.ArgumentParser(description='Fill in sticker details')
|
|
||||||
parser.add_argument('--out',
|
|
||||||
'-o',
|
|
||||||
default=sys.stdout,
|
|
||||||
type=argparse.FileType('w'),
|
|
||||||
help='output path (default: stdout)')
|
|
||||||
parser.add_argument('--dluo',
|
|
||||||
'-d',
|
|
||||||
required=True,
|
|
||||||
help='Date Limite d\'Utilisation Optimale')
|
|
||||||
parser.add_argument('--lot', '-l', required=True, help='Numéro de lot')
|
|
||||||
parser.add_argument('--quantite', '-q', required=False, help='Quantité (volume ou masse)')
|
|
||||||
parser.add_argument('--teneur', '-t', required=False, help='Teneur en sucre')
|
|
||||||
parser.add_argument('--fruit', '-f', required=False, help='Quantité de fruits')
|
|
||||||
parser.add_argument('--size', '-s', required=False, help='Masse de produit')
|
|
||||||
parser.add_argument('--landscape',
|
|
||||||
action='store_true',
|
|
||||||
help='input sticker is in landscape orientation')
|
|
||||||
parser.add_argument('sticker', help='path to the sticker template')
|
|
||||||
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def makesticker(sticker: str, out: typing.IO, subs: dict, landscape=False):
|
|
||||||
with open(sticker) as fin:
|
|
||||||
lines = fin.readlines()
|
|
||||||
if lines[0].startswith('<?xml'):
|
|
||||||
lines = lines[1:]
|
|
||||||
sticker_data = ''.join(lines)
|
|
||||||
|
|
||||||
if landscape:
|
|
||||||
# Rotate the sticker 90 degrees
|
|
||||||
sticker_data = "<g transform=\"rotate(-90,0,0) translate(-102,0)\">{}</g>".format(sticker_data)
|
|
||||||
|
|
||||||
out.write(Template(sticker_data).substitute(subs))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
args = vars(parse_args())
|
|
||||||
subs = {
|
|
||||||
'dluo': args.pop('dluo'),
|
|
||||||
'lot': args.pop('lot'),
|
|
||||||
'teneur': args.pop('teneur'),
|
|
||||||
'fruit': args.pop('fruit'),
|
|
||||||
'qty': args.pop('quantite'),
|
|
||||||
'size': args.pop('size'),
|
|
||||||
}
|
|
||||||
args['subs'] = subs
|
|
||||||
makesticker(**args)
|
|
@ -1,25 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
DEFAULT_DPI=300
|
|
||||||
LARGE='370' # Large container (370g)
|
|
||||||
SMALL='220' # Small container (220g)
|
|
||||||
|
|
||||||
SIZE=$LARGE
|
|
||||||
DLUO='décembre 2023'
|
|
||||||
LOT='0722-2'
|
|
||||||
TENEUR='50' # %
|
|
||||||
FRUIT='80' # g
|
|
||||||
STICKER='Gelée Extra - Cassis.svg'
|
|
||||||
DATADIR=/data
|
|
||||||
|
|
||||||
PDF="`basename \"${STICKER}\" .svg` - ${LOT} (${SIZE}g).pdf"
|
|
||||||
|
|
||||||
here=$(dirname $(readlink -f $0))
|
|
||||||
cd $DATADIR
|
|
||||||
|
|
||||||
$here/makesticker.py --landscape --dluo "$DLUO" --lot "$LOT" --teneur "$TENEUR" --fruit "$FRUIT" --quantite "$SIZE" -o out.svg "$STICKER" && \
|
|
||||||
$here/makeplanche.py -o pout.svg -t $here/planche.svg.in out.svg && \
|
|
||||||
rm out.svg && \
|
|
||||||
inkscape --export-type="png" --export-dpi=$DEFAULT_DPI pout.svg && \
|
|
||||||
rm pout.svg && \
|
|
||||||
convert pout.png "$PDF"
|
|
@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 210 297"
|
|
||||||
height="297mm"
|
|
||||||
width="210mm">
|
|
||||||
<g transform="translate(3, 4.5)">
|
|
||||||
<g transform="translate(-42,144) rotate(-90,144,0)">
|
|
||||||
<g transform="translate( 0,0)">$right0</g>
|
|
||||||
<g transform="translate( 48,0)">$right1</g>
|
|
||||||
<g transform="translate( 96,0)">$right2</g>
|
|
||||||
<g transform="translate(144,0)">$right3</g>
|
|
||||||
<g transform="translate(192,0)">$right4</g>
|
|
||||||
<g transform="translate(240,0)">$right5</g>
|
|
||||||
</g>
|
|
||||||
<g transform="translate(-42,144) rotate(90,144,0)">
|
|
||||||
<g transform="translate( 0,0)">$left0</g>
|
|
||||||
<g transform="translate( 48,0)">$left1</g>
|
|
||||||
<g transform="translate( 96,0)">$left2</g>
|
|
||||||
<g transform="translate(144,0)">$left3</g>
|
|
||||||
<g transform="translate(192,0)">$left4</g>
|
|
||||||
<g transform="translate(240,0)">$left5</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 896 B |
@ -1,269 +0,0 @@
|
|||||||
import argparse
|
|
||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
||||||
import io
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import subprocess
|
|
||||||
import tempfile
|
|
||||||
import time
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from makesticker import makesticker
|
|
||||||
from makeplanche import makeplanche
|
|
||||||
|
|
||||||
# defaults
|
|
||||||
PORT = 8000
|
|
||||||
OUT_DIR = tempfile.gettempdir()
|
|
||||||
DATA_DIR = '/data'
|
|
||||||
TEMPLATE_DIR = DATA_DIR
|
|
||||||
DEFAULT_DPI = 300
|
|
||||||
LEMOTDEPASSE = 'je veux ajouter une étiquette'
|
|
||||||
TIKETTES = os.path.join(DATA_DIR, 'tikettes.json')
|
|
||||||
|
|
||||||
config = {}
|
|
||||||
|
|
||||||
def tikettes_path():
|
|
||||||
return config.get('tikettes', TIKETTES)
|
|
||||||
|
|
||||||
def template_dir():
|
|
||||||
return config.get('template_dir', TEMPLATE_DIR)
|
|
||||||
|
|
||||||
|
|
||||||
def inkscapize(svg_in, pdf_out):
|
|
||||||
png_out = tempfile.mktemp(suffix='.png')
|
|
||||||
try:
|
|
||||||
cmd = ['inkscape', '--export-type=png', f'--export-filename={png_out}',
|
|
||||||
f'--export-dpi={DEFAULT_DPI}', svg_in]
|
|
||||||
subprocess.check_call(cmd)
|
|
||||||
|
|
||||||
cmd = ['convert', png_out, pdf_out]
|
|
||||||
subprocess.check_call(cmd)
|
|
||||||
finally:
|
|
||||||
if os.path.exists(png_out):
|
|
||||||
os.unlink(png_out)
|
|
||||||
|
|
||||||
|
|
||||||
def handle_newtikette(formdata):
|
|
||||||
with open(tikettes_path()) as f:
|
|
||||||
tikettes = json.load(f)
|
|
||||||
|
|
||||||
sticker = formdata['title'] + '.svg'
|
|
||||||
with open(os.path.join(template_dir(), sticker), 'w') as f:
|
|
||||||
f.write(formdata['sticker'])
|
|
||||||
|
|
||||||
known_subs = {
|
|
||||||
"dluo": "germinal 9999",
|
|
||||||
"fruit": "80",
|
|
||||||
"teneur": "50",
|
|
||||||
"lot": "0000-0",
|
|
||||||
"qty": "370",
|
|
||||||
"vol": "50",
|
|
||||||
}
|
|
||||||
|
|
||||||
newtikette = {
|
|
||||||
'title': formdata['title'],
|
|
||||||
'sticker': sticker,
|
|
||||||
'landscape': 'landscape' in formdata,
|
|
||||||
'subs': {k: v for k, v in known_subs.items() if k in formdata},
|
|
||||||
}
|
|
||||||
|
|
||||||
logging.info(f'adding newtikette: {newtikette}')
|
|
||||||
|
|
||||||
tikettes.append(newtikette)
|
|
||||||
|
|
||||||
with open(tikettes_path(), 'w') as f:
|
|
||||||
json.dump(tikettes, f, indent=2)
|
|
||||||
|
|
||||||
return json.dumps({'status': 'ok', 'message': 'newtikette added'})
|
|
||||||
|
|
||||||
|
|
||||||
def handle_generate(request):
|
|
||||||
request = json.loads(request)
|
|
||||||
|
|
||||||
# fill in sticker details
|
|
||||||
sticker_out = tempfile.mktemp(suffix='.svg')
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(sticker_out, 'w') as stickout:
|
|
||||||
landscape = request.get('landscape', False)
|
|
||||||
print(f'landscape: {landscape}')
|
|
||||||
makesticker(os.path.join(template_dir(), request['sticker']), stickout,
|
|
||||||
request['subs'], landscape=landscape)
|
|
||||||
|
|
||||||
# make sticker sheet
|
|
||||||
planche_out = tempfile.mktemp(suffix='.svg')
|
|
||||||
with open(sticker_out, 'r') as stickin:
|
|
||||||
with open(planche_out, 'w') as planchout:
|
|
||||||
makeplanche(stickin, planchout)
|
|
||||||
|
|
||||||
# process to printable pdf
|
|
||||||
pdf_out = tempfile.mktemp(dir=OUT_DIR, suffix='.pdf')
|
|
||||||
inkscapize(planche_out, pdf_out)
|
|
||||||
|
|
||||||
response = {'status': 'ok', 'file': os.path.basename(pdf_out),
|
|
||||||
'message': 'this is the way'}
|
|
||||||
return json.dumps(response)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
if os.path.exists(sticker_out):
|
|
||||||
os.unlink(sticker_out)
|
|
||||||
if 'planche_out' in locals() and os.path.exists(planche_out):
|
|
||||||
os.unlink(planche_out)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_multipart(data, boundary):
|
|
||||||
logging.debug(f'parsing data with boundary: {boundary}')
|
|
||||||
f = io.StringIO(data)
|
|
||||||
out = []
|
|
||||||
|
|
||||||
if boundary not in f.readline():
|
|
||||||
return out
|
|
||||||
|
|
||||||
while True:
|
|
||||||
headers = []
|
|
||||||
while True:
|
|
||||||
h = f.readline().strip()
|
|
||||||
try:
|
|
||||||
k, v = re.findall(r'^([a-zA-Z-]+): (.*)$', h)[0]
|
|
||||||
except IndexError:
|
|
||||||
break
|
|
||||||
headers.append((k, v))
|
|
||||||
metadata = None
|
|
||||||
otherheaders = []
|
|
||||||
logging.debug(headers)
|
|
||||||
for k, v in headers:
|
|
||||||
if k == 'Content-Disposition':
|
|
||||||
parts = v.split('; ')
|
|
||||||
if parts[0] != 'form-data':
|
|
||||||
continue
|
|
||||||
d = dict(re.findall(r'([^=]+)="(.*)"$', p)[0] for p in parts[1:])
|
|
||||||
metadata = d
|
|
||||||
else:
|
|
||||||
otherheaders.append((k, v))
|
|
||||||
|
|
||||||
value = io.StringIO()
|
|
||||||
while True:
|
|
||||||
l = f.readline()
|
|
||||||
if not l:
|
|
||||||
break
|
|
||||||
if boundary in l:
|
|
||||||
# value.write(l.split(boundary)[0])
|
|
||||||
break
|
|
||||||
value.write(l)
|
|
||||||
if metadata is None:
|
|
||||||
break
|
|
||||||
logging.debug(f'({metadata}, {value.getvalue()[:-2]}, {otherheaders})')
|
|
||||||
out.append((metadata, value.getvalue()[:-2], otherheaders))
|
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
|
|
||||||
class MyServer(BaseHTTPRequestHandler):
|
|
||||||
def do_GET(self):
|
|
||||||
logging.info(f'GET {self.path}')
|
|
||||||
if self.path == '/list':
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "application/json")
|
|
||||||
self.send_header('Access-Control-Allow-Origin', '*')
|
|
||||||
self.end_headers()
|
|
||||||
with open(tikettes_path()) as f:
|
|
||||||
tikettes = json.load(f)
|
|
||||||
|
|
||||||
resp = {'status': 'ok', 'message': 'this is the way',
|
|
||||||
'tikettes': tikettes}
|
|
||||||
self.wfile.write(json.dumps(resp).encode())
|
|
||||||
return
|
|
||||||
match = re.match(r'/data/(\w+\.pdf)', self.path)
|
|
||||||
if match is not None:
|
|
||||||
pdf_path = os.path.join(OUT_DIR, match.groups()[0])
|
|
||||||
if not os.path.exists(pdf_path):
|
|
||||||
self.send_response(404)
|
|
||||||
self.end_headers()
|
|
||||||
return
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "application/pdf")
|
|
||||||
self.end_headers()
|
|
||||||
with open(pdf_path, 'rb') as f:
|
|
||||||
self.wfile.write(f.read())
|
|
||||||
return
|
|
||||||
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "text/html; charset=UTF-8")
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(b"<html><head><title>Zetikettes</title></head>")
|
|
||||||
self.wfile.write(b"<body>")
|
|
||||||
self.wfile.write("<p>This is not the way.</p>".encode())
|
|
||||||
self.wfile.write(b"</body></html>")
|
|
||||||
|
|
||||||
def do_OPTIONS(self):
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header('Access-Control-Allow-Origin', '*')
|
|
||||||
self.end_headers()
|
|
||||||
|
|
||||||
def do_POST(self):
|
|
||||||
logging.info(f'POST {self.path}')
|
|
||||||
try:
|
|
||||||
length = int(self.headers['content-length'])
|
|
||||||
req = self.rfile.read(length).decode()
|
|
||||||
if self.path == '/newtikette':
|
|
||||||
boundary = re.findall(r'boundary=(.*)$', self.headers['content-type'])[0]
|
|
||||||
formdata = {p['name']: v for p, v, _ in parse_multipart(req, boundary)}
|
|
||||||
logging.info({k: v[:100] for k, v in formdata.items()})
|
|
||||||
|
|
||||||
if formdata.get('lemotdepasse', None) != LEMOTDEPASSE:
|
|
||||||
logging.warning(f'wrong lemotdepasse')
|
|
||||||
self.send_response(403)
|
|
||||||
self.send_header("Content-type", "application/json")
|
|
||||||
self.send_header('Access-Control-Allow-Origin', '*')
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(json.dumps({'status': 'notok', 'message': 'bad lemotdepasse'}).encode())
|
|
||||||
return
|
|
||||||
|
|
||||||
resp = handle_newtikette(formdata).encode()
|
|
||||||
else:
|
|
||||||
resp = handle_generate(req).encode()
|
|
||||||
except:
|
|
||||||
self.send_response(500)
|
|
||||||
self.send_header("Content-type", "text/plain")
|
|
||||||
self.send_header('Access-Control-Allow-Origin', '*')
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(traceback.format_exc().encode())
|
|
||||||
raise
|
|
||||||
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "application/json")
|
|
||||||
self.send_header('Access-Control-Allow-Origin', '*')
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(resp)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
|
||||||
parser = argparse.ArgumentParser(description='Zetikette backend')
|
|
||||||
parser.add_argument('--port', type=int, default=PORT, help=f'default: {PORT}')
|
|
||||||
parser.add_argument('--data-dir', default=DATA_DIR, help=f'default: {DATA_DIR}')
|
|
||||||
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
args = parse_args()
|
|
||||||
|
|
||||||
config.update({
|
|
||||||
'tikettes': os.path.join(args.data_dir, 'tikettes.json'),
|
|
||||||
'template_dir': args.data_dir,
|
|
||||||
})
|
|
||||||
|
|
||||||
webServer = HTTPServer(('', args.port), MyServer)
|
|
||||||
print(f"Server started on port {args.port}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
webServer.serve_forever()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
|
|
||||||
webServer.server_close()
|
|
||||||
print("Server stopped.")
|
|
Loading…
Reference in New Issue
Block a user