littleprynter/src/main.py
2022-03-12 04:28:17 +01:00

120 lines
3.7 KiB
Python

# Welcome to the LittlePrynter's source code.
# This program expose a web interface, with user authentification, that makes it possible to print messages from the web.
# It also exposes a API, making it possible to print and interface with much of the printer's abilities.
# We first define the connection to the printer itself,
# Then we build the API around Flask,
# Then we build the web interface, using the simple Jinja2 templating.
# Following are the librairies we import,
from flask import Flask, request, render_template, flash, abort, redirect, url_for, make_response, jsonify # Used for the web framework
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from printer import Printer # The wrapper for the printer class
from web import Web # Wrapper for the web routes and API
import toml # Used for the config file parsing
import pprint # To pretty print JSON
import time # To sleep
import os # For VARS from the shell.
# Variables
# Load the configuration file
try:
configuration_file = toml.load("configuration/config.toml")
except TypeError :
print("Unable to load the config file: invalid type or is a list containing invalid types")
exit(-1)
except toml.TomlDecodeError:
print("An error occured while decoding the file")
exit(-1)
except Exception as e:
print("Error while loading file : " + str(e))
# Define the USB connections here.
vendor_id = configuration_file["printer"]["vendor_id"]
device_id = configuration_file["printer"]["device_id"]
# Output the config file
if os.getenv('LIPY_DEBUG') == True:
pprint.pprint(configuration_file)
# We define the app module used by Flask
app = Flask(__name__)
app.secret_key = configuration_file["secrets"]["flask_secret_key"]
# Printer connection
# Uses the class defined in the printer.py file
printer = Printer(app,0x04b8, 0x0e28)
printer.init_printer()
# Web routes
web = Web(app, printer)
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/')
@limiter.limit("1/second", override_defaults=False)
def index():
return render_template('index.html')
# API routes
# The api has the following methods
# api/print/{sms,img,letter,qr,barcode}
# api/auth/{login,logout}
# api/status/{paper,ping,stats}
# If you just call the api route, you get a help back.
@app.route('/api')
@app.route('/api/print')
@limiter.limit("1/second", override_defaults=False)
def api_index():
return render_template("api.html")
@app.route('/api/print/sms', methods=['POST'])
@limiter.limit("2/minute", override_defaults=False)
def api_print_sms():
try:
txt = request.form["txt"]
sign = request.form["signature"]
except Exception as e:
flash(e)
redirect(url_for('index'))
flash(web.print_sms(txt,sign))
return redirect(url_for('index'))
@app.route('/api/print/image', methods=['POST'])
@limiter.limit("2/minute", override_defaults=False)
def api_print_image():
flash(web.print_image())
return "print image"
@app.route('/login')
@limiter.limit("1/second", override_defaults=False)
def login_page():
# web.login(username,password)
return render_template("index.html")
@app.route('/logout')
@limiter.limit("1/second", override_defaults=False)
def logout_page():
# web.logout(username, password)
return render_template("index.html")
@app.errorhandler(429)
def ratelimit_handler(e):
flash("Rate limit reached, please slow down :) ( Currently at "+ e.description + ")", 'error')
return render_template('index.html')
@app.route("/ping")
@limiter.exempt
def ping():
return "PONG"