server-tx part : web UI, PDF generator & transfer to RX server

This commit is contained in:
2025-05-15 14:34:08 +03:00
parent d969addd18
commit e1780fad99
32 changed files with 1272 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
from flask import Blueprint
m_print = Blueprint(
'print',
__name__,
template_folder='templates'
)
from . import views
Binary file not shown.
@@ -0,0 +1,20 @@
{% extends "general.html" %}
{% block title %}Загрузка кода на печать{% endblock %}
{% block header %}Команда: {{ user.team }} | Локация: {{ user.loc }} | <a href="/auth/logout">Выйти</a>{% endblock %}
{% block content %}
{% block extra %}
{% endblock %}
<div class="card">
<h2>Отправка кода на печать</h2>
<p>Скопируйте код с IDE и вставьте его в поле "Код".</p>
<form action="/printcode" method="POST">
<div class="form-group">
<label for="code">Код</label>
<textarea id="code" name="code" rows="25"></textarea>
</div>
<button type="submit" class="button">Узреть свой код на бересте!</button>
</form>
</div>
{% endblock %}
@@ -0,0 +1,4 @@
{% extends "print/print_code_t.html" %}
{% block title %}Загрузка кода на печать{% endblock %}
{% block header %}Админ: {{ user.username }} | <a href="/admin">Панель администратора</a> | <a href="/auth/logout">Выйти</a>{% endblock %}
@@ -0,0 +1,18 @@
{% extends "print/print_code.html" %}
{% block title %}Загрузка кода на печать{% endblock %}
{% block header %}Преподаватель: {{ user.username }} | <a href="/auth/logout">Выйти</a>{% endblock %}
{% block extra %}
<div class="card">
<h2>Отправка файла на печать</h2>
<p>У вас есть права на печать документов напрямую, загружая .pdf!</p>
<form class="file-upload" action="/printpdf" method="POST" enctype="multipart/form-data">
<label for="file">Загрузка файла .PDF</label>
<input type="file" id="file" name="file" accept=".pdf">
<label style="margin-top: 10px;" for="samples">Количество копий (допустимый максимум - 15, можно повторять запросы)</label>
<input type="number" id="samples" name="samples" value="1">
<button style="margin-top: 10px;" type="submit" class="button">Распечатать</button>
</form>
</div>
{% endblock %}
+175
View File
@@ -0,0 +1,175 @@
from . import m_print
import requests
import time
from datetime import datetime
from flask import render_template
from flask import redirect
from flask import request
from flask import session
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from io import BytesIO
from app._tools.decorators import auth_required
from app._tools.database import DataManager
from app._tools.database import SessionManager
from app._tools.database import ConfigManager
RENDER_TEMPLATE = {
"$root$" : "print/print_code_a.html",
"$tutor$" : "print/print_code_t.html"
}
pdfmetrics.registerFont(TTFont('webprint', ConfigManager.get_config()['font-path']))
def watermark_gen(p : canvas.Canvas, config, user, page) -> None:
REPLACEMENTS = {
"$time$": datetime.now().strftime('%d.%m.%Y %H:%M'),
"$team$": getattr(user, 'team', 'Unknown Team'),
"$loc$": getattr(user, 'loc', 'Unknown Location'),
"$page$": str(page)
}
wm_format = str(config['print']['watermark'])
for key, value in REPLACEMENTS.items():
wm_format = wm_format.replace(key, value)
p.setFont("webprint", 13)
p.setFillColorRGB(0.5, 0.5, 0.5)
p.rotate(45)
p.drawString(200, 200, wm_format * 10)
p.rotate(-45)
@m_print.route('/')
@auth_required
def print_code():
user = DataManager.get_user(SessionManager.get_session(session["token"]).user_id)
render = 'print/print_code.html'
if user.team in RENDER_TEMPLATE:
render = RENDER_TEMPLATE[user.team]
return render_template(
f'{render}', user = user
)
@m_print.route('/printcode', methods=['POST'])
@auth_required
def print_proc():
user_text = request.form.get('code')
lines = user_text.split('\n')
if len(lines) < 4:
return render_template("error.html", error = "Код, в котором так мало строк, можно запомнить и без печати :)")
user = DataManager.get_user(SessionManager.get_session(session["token"]).user_id)
config = ConfigManager.get_config()
timedelta = int(time.time()) - user.lastprint_ts
timedelta = config['print']['limits']['seconds-per-request'] - timedelta
if timedelta > 0:
return render_template("error.html", error = f"Пожалуйста, подождите ещё {timedelta} с. перед повторным запросом!")
DataManager.edit_user(user.id, "lastprint_ts", int(time.time()))
buffer = BytesIO()
proc_pdf = canvas.Canvas(buffer, pagesize = A4)
width, height = A4
left_margin = 15
top_margin = height - 30
line_height = 15
y = top_margin
pages = 1
watermark_gen(proc_pdf, config, user, pages)
proc_pdf.setFillColorRGB(0, 0, 0, 1)
proc_pdf.setFont("webprint", 9)
for line in lines:
line = line.replace('\r', '')
if y < 30:
pages += 1
if (pages > config['print']['limits']['pages-per-request']):
return render_template(
"error.html",
error = f"Достигнут лимит на генерацию в {config['print']['limits']['pages-per-request']} страниц за запрос!"
)
proc_pdf.showPage()
watermark_gen(proc_pdf, config, user, pages)
proc_pdf.setFillColorRGB(0, 0, 0, 1)
proc_pdf.setFont("webprint", 9)
y = top_margin
proc_pdf.drawString(left_margin, y, line)
y -= line_height
proc_pdf.showPage()
proc_pdf.save()
buffer.seek(0)
proc_pdf = buffer.getvalue()
try:
DataManager.edit_user(
user.id,
"pages",
user.pages + pages
)
response = requests.post(
f"http://{config['server']['ip']}:{config['server']['port']}/printfile",
files = {
'file' : (f"wp_{user.username}_{user.lastprint_ts}.pdf", proc_pdf)
},
data = {
'secret-key' : config['server']['secret']
},
timeout = 10
)
if response.status_code == 200:
return redirect("/")
else:
return render_template(
"error.html",
error = "Ошибка при отправке PDF файла на печать. Обратитесь к Администратору."
)
except Exception as e:
return render_template(
"error.html",
error = f"Ошибка при подключении к серверу печати: {str(e)}"
)
@m_print.route('/printpdf', methods=['POST'])
@auth_required
def print_pdf_proc():
user = DataManager.get_user(SessionManager.get_session(session["token"]).user_id)
config = ConfigManager.get_config()
if user.team not in RENDER_TEMPLATE:
return redirect("/")
samples = 1
file = request.files.get('file')
if file.filename == '':
return render_template("error.html", error = "Не был прикреплён файл!")
if 'samples' in request.form:
samples = int(request.form.get('samples'))
if samples not in range(1, 16):
return render_template(
"error.html",
error = "Допустимый диапазон копий составляет 1..15!"
)
DataManager.edit_user(user.id, "lastprint_ts", int(time.time()))
try:
response = requests.post(
f"http://{config['server']['ip']}:{config['server']['port']}/printfile",
files = {
'file' : (f"wp_{user.username}_{user.lastprint_ts}.pdf", file)
},
data = {
'secret-key' : config['server']['secret'],
'samples' : samples
},
timeout = 10
)
if response.status_code == 200:
return redirect("/")
else:
return render_template(
"error.html",
error = "Ошибка при отправке PDF файла на печать. Обратитесь к Администратору."
)
except Exception as e:
return render_template(
"error.html",
error = f"Ошибка при подключении к серверу печати: {str(e)}"
)