Browse Source

print with a random code

Davide Alberani 4 years ago
parent
commit
ad2051e0e0
4 changed files with 79 additions and 18 deletions
  1. 2 0
      README.md
  2. 3 1
      dist/static/js/httprint.js
  3. 74 17
      httprint.py
  4. 0 0
      queue/.gitkeep

+ 2 - 0
README.md

@@ -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
 

+ 3 - 1
dist/static/js/httprint.js

@@ -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 {

+ 74 - 17
httprint.py

@@ -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,12 +193,15 @@ 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)
-        self.build_success("file sent to printer")
+        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")
 
 
 class TemplateHandler(BaseHandler):
@@ -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'),

+ 0 - 0
uploads/.gitkeep → queue/.gitkeep