print with a random code

This commit is contained in:
Davide Alberani 2019-08-15 10:41:24 +02:00
parent 2e395edfd1
commit ad2051e0e0
4 changed files with 79 additions and 18 deletions

View file

@ -21,6 +21,8 @@ Now you can **point your browser to [http://localhost:7777/](http://localhost:77
You can also **run the server in https**, putting in the *ssl* directory two files named *httprint_key.pem* and *httprint_cert.pem*
By default the **--print-with-code** argument is true, and the uploaded files are just scheduled for priting. To actually print them, you should supply the generated code, for example: `curl -X POST http://localhost:7777/api/print/1234`
# License and copyright

View file

@ -12,8 +12,10 @@ function uploadFile() {
if (reply && !reply.error) {
iziToast.success({
title: "DONE!",
message: "file sent to printer",
message: reply.message,
position: 'topCenter',
timeout: false,
closeOnEscape: true,
layout: 2
});
} else {

View file

@ -16,9 +16,11 @@ limitations under the License.
"""
import os
import re
import time
import glob
import random
import asyncio
import shutil
import logging
import subprocess
import multiprocessing as mp
@ -32,10 +34,12 @@ from tornado import gen, escape
API_VERSION = '1.0'
UPLOAD_PATH = 'uploads'
QUEUE_DIR = 'queue'
ARCHIVE = True
ARCHIVE_DIR = 'archive'
PRINT_CMD = ['lp']
PROCESS_TIMEOUT = 60
ENCODING = 'utf-8'
CODE_DIGITS = 4
PRINT_WITH_CODE = True
logger = logging.getLogger()
logger.setLevel(logging.INFO)
@ -118,8 +122,51 @@ class BaseHandler(tornado.web.RequestHandler):
p = mp.Process(target=self._run, args=(cmd,))
p.start()
def print_file(self, fname):
cmd = PRINT_CMD + [fname]
self.run_subprocess(cmd)
if self.cfg.archive:
if not os.path.isdir(self.cfg.archive_dir):
os.makedirs(self.cfg.archive_dir)
shutil.move(fname, self.cfg.archive_dir)
class PrintHandler(BaseHandler):
"""File print handler."""
@gen.coroutine
def post(self, code=None):
if not code:
self.build_error("empty code")
return
files = glob.glob(self.cfg.queue_dir + '/%s-*' % code)
if not files:
self.build_error("no matching files")
return
self.print_file(files[0])
self.build_success("file sent to printer")
class UploadHandler(BaseHandler):
"""Reset schedules handler."""
"""File upload handler."""
def generateCode(self):
filler = '%0' + str(self.cfg.code_digits) + 'd'
existing = set()
re_code = re.compile('(\d{' + str(self.cfg.code_digits) + '})-.*')
for fname in glob.glob(self.cfg.queue_dir + '/*'):
fname = os.path.basename(fname)
match = re_code.match(fname)
if not match:
continue
fcode = match.group(1)
existing.add(fcode)
code = None
for i in range(10**self.cfg.code_digits):
intCode = random.randint(0, (10**self.cfg.code_digits)-1)
code = filler % intCode
if code not in existing:
break
return code
@gen.coroutine
def post(self):
if not self.request.files.get('file'):
@ -132,13 +179,12 @@ class UploadHandler(BaseHandler):
extension = os.path.splitext(webFname)[1]
except Exception:
pass
if not os.path.isdir(UPLOAD_PATH):
os.makedirs(UPLOAD_PATH)
fname = '%s-%s%s' % (
time.strftime('%Y%m%d%H%M%S'),
'%04d' % random.randint(0, 9999),
extension)
pname = os.path.join(UPLOAD_PATH, fname)
if not os.path.isdir(self.cfg.queue_dir):
os.makedirs(self.cfg.queue_dir)
now = time.strftime('%Y%m%d%H%M%S')
code = self.generateCode()
fname = '%s-%s%s' % (code, now, extension)
pname = os.path.join(self.cfg.queue_dir, fname)
try:
with open(pname, 'wb') as fd:
fd.write(fileinfo['body'])
@ -147,11 +193,14 @@ class UploadHandler(BaseHandler):
return
try:
with open(pname + '.info', 'w') as fd:
fd.write('originale file name: %s\n' % webFname)
fd.write('original file name: %s\n' % webFname)
fd.write('uploaded on: %s\n' % now)
except Exception:
pass
cmd = PRINT_CMD + [pname]
self.run_subprocess(cmd)
if self.cfg.print_with_code:
self.build_success("go to the printer and enter this code: %s" % code)
else:
self.print_file(pname)
self.build_success("file sent to printer")
@ -175,6 +224,11 @@ def serve():
help='specify the SSL certificate to use for secure connections')
define('ssl_key', default=os.path.join(os.path.dirname(__file__), 'ssl', 'httprint_key.pem'),
help='specify the SSL private key to use for secure connections')
define('code-digits', default=CODE_DIGITS, help='number of digits of the code', type=int)
define('queue-dir', default=QUEUE_DIR, help='directory to store files before they are printed', type=str)
define('archive', default=True, help='archive printed files', type=bool)
define('archive-dir', default=ARCHIVE_DIR, help='directory to archive printed files', type=str)
define('print-with-code', default=True, help='a code must be entered for printing', type=bool)
define('debug', default=False, help='run in debug mode', type=bool)
tornado.options.parse_command_line()
@ -185,12 +239,15 @@ def serve():
if os.path.isfile(options.ssl_key) and os.path.isfile(options.ssl_cert):
ssl_options = dict(certfile=options.ssl_cert, keyfile=options.ssl_key)
init_params = dict(listen_port=options.port, logger=logger, ssl_options=ssl_options)
init_params = dict(listen_port=options.port, logger=logger, ssl_options=ssl_options, cfg=options)
_upload_path = r'upload/?'
_print_path = r'print/(?P<code>\d+)'
application = tornado.web.Application([
(r'/api/%s' % _upload_path, UploadHandler, init_params),
(r'/api/v%s/%s' % (API_VERSION, _upload_path), UploadHandler, init_params),
(r'/api/%s' % _print_path, PrintHandler, init_params),
(r'/api/v%s/%s' % (API_VERSION, _print_path), PrintHandler, init_params),
(r'/?(.*)', TemplateHandler, init_params),
],
static_path=os.path.join(os.path.dirname(__file__), 'dist/static'),