Delete & notify on bad files
This commit is contained in:
parent
db9e8c1105
commit
5ceb2d1488
7 changed files with 95 additions and 14 deletions
|
@ -64,6 +64,8 @@ def manipulate_files():
|
||||||
os.unlink(file.path)
|
os.unlink(file.path)
|
||||||
|
|
||||||
ctx.db.delete_file(uid=ctx.uid, fid=file.id)
|
ctx.db.delete_file(uid=ctx.uid, fid=file.id)
|
||||||
|
ctx.db.delete_file_analysis_by_fid(fid=file.id)
|
||||||
|
ctx.db.delete_jobs_by_fid(uid=ctx.uid, fid=file.id)
|
||||||
flash("File deleted", category="info")
|
flash("File deleted", category="info")
|
||||||
|
|
||||||
case _:
|
case _:
|
||||||
|
|
|
@ -43,22 +43,23 @@ WHERE
|
||||||
user_id = :uid
|
user_id = :uid
|
||||||
;
|
;
|
||||||
|
|
||||||
-- name: delete-file*!
|
-- name: delete-file!
|
||||||
DELETE FROM jobs
|
DELETE FROM files
|
||||||
WHERE
|
WHERE
|
||||||
user_id = :uid
|
user_id = :uid
|
||||||
AND file_id = :fid
|
AND id = :fid
|
||||||
;
|
;
|
||||||
|
|
||||||
|
-- name: delete-file-analysis-by-fid!
|
||||||
DELETE FROM file_analysis
|
DELETE FROM file_analysis
|
||||||
WHERE
|
WHERE
|
||||||
file_id = :fid
|
file_id = :fid
|
||||||
;
|
;
|
||||||
|
|
||||||
DELETE FROM files
|
-- name: delete-file-analysis!
|
||||||
|
DELETE FROM file_analysis
|
||||||
WHERE
|
WHERE
|
||||||
user_id = :uid
|
id = :aid
|
||||||
AND id = :fid
|
|
||||||
;
|
;
|
||||||
|
|
||||||
-- name: fetch-file^
|
-- name: fetch-file^
|
||||||
|
|
|
@ -192,3 +192,10 @@ WHERE
|
||||||
user_id = :uid
|
user_id = :uid
|
||||||
AND id = :jid
|
AND id = :jid
|
||||||
;
|
;
|
||||||
|
|
||||||
|
-- name: delete-jobs-by-fid!
|
||||||
|
DELETE FROM jobs
|
||||||
|
WHERE
|
||||||
|
user_id = :uid
|
||||||
|
AND file_id = :fid
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="https://tentacles.tirefireind.us/static/css/style.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="container navbar">
|
||||||
|
<span class="logo">
|
||||||
|
<a class="row" href="https://tentacles.tirefireind.us/">
|
||||||
|
<img src="https://tentacles.tirefireind.us/static/tentacles.svg" alt="Tentacles">
|
||||||
|
<span class="name color-yellow">Tentacles</span>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container content">
|
||||||
|
<div class="row">
|
||||||
|
<p>
|
||||||
|
Dear {{ username }},
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We're sorry to inform you that the file <code>{{ filename }}</code> you attempted to print has been rejected.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
At this time, Tentacles requires that all submitted Gcode be generated by PrusaSlicer 2.0.0 or later, and
|
||||||
|
contain the PrusaSlicer emitted configuration metadata. This allows us to verify that the Gcode you've
|
||||||
|
submitted fits within the constraints of the printers we have available and choose an appropriately printer
|
||||||
|
for running the job. This protects our printers from damage and ensures that you get usable results.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please re-slice the object using <a href="https://www.prusa3d.com/page/prusaslicer_424/">PrusaSlicer</a> and
|
||||||
|
re-submit the resulting Gcode.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Thank you for your understanding
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<footer>
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
</html>
|
|
@ -3,13 +3,13 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="{{ base_url }}/static/css/style.css" />
|
<link rel="stylesheet" href="https://tentacles.tirefireind.us/static/css/style.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="container navbar">
|
<nav class="container navbar">
|
||||||
<span class="logo">
|
<span class="logo">
|
||||||
<a class="row" href="/">
|
<a class="row" href="https://tentacles.tirefireind.us/">
|
||||||
<img src="{{ base_url }}/static/tentacles.svg" alt="Tentacles">
|
<img src="https://tentacles.tirefireind.us/static/tentacles.svg" alt="Tentacles">
|
||||||
<span class="name color-yellow">Tentacles</span>
|
<span class="name color-yellow">Tentacles</span>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<body>
|
<body>
|
||||||
<nav class="container navbar">
|
<nav class="container navbar">
|
||||||
<span class="logo">
|
<span class="logo">
|
||||||
<a class="row" href="/">
|
<a class="row" href="{{ base_url }}">
|
||||||
<img src="{{ base_url }}/static/tentacles.svg" alt="Tentacles">
|
<img src="{{ base_url }}/static/tentacles.svg" alt="Tentacles">
|
||||||
<span class="name color-yellow">Tentacles</span>
|
<span class="name color-yellow">Tentacles</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -7,6 +7,7 @@ Supporting the core app with asynchronous maintenance tasks.
|
||||||
Mostly related to monitoring and managing Printer state.
|
Mostly related to monitoring and managing Printer state.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
from functools import cache
|
from functools import cache
|
||||||
import logging
|
import logging
|
||||||
|
@ -19,6 +20,7 @@ from cherrypy.process.plugins import Monitor
|
||||||
from fastmail import FastMailSMTP
|
from fastmail import FastMailSMTP
|
||||||
from gcode import analyze_gcode_file
|
from gcode import analyze_gcode_file
|
||||||
from flask import Flask as App
|
from flask import Flask as App
|
||||||
|
from flask import render_template
|
||||||
from octorest import OctoRest as _OR
|
from octorest import OctoRest as _OR
|
||||||
from requests import Response
|
from requests import Response
|
||||||
from requests.exceptions import (
|
from requests.exceptions import (
|
||||||
|
@ -302,16 +304,40 @@ def send_emails(app, db: Db):
|
||||||
|
|
||||||
|
|
||||||
def analyze_files(app: App, db: Db):
|
def analyze_files(app: App, db: Db):
|
||||||
for unanalyzed in db.list_unanalyzed_files():
|
for file in db.list_unanalyzed_files():
|
||||||
record = analyze_gcode_file(Path(unanalyzed.path))
|
p = Path(file.path)
|
||||||
|
if not p.is_file():
|
||||||
|
log.error(f"Invalid file {file.id}!")
|
||||||
|
continue
|
||||||
|
|
||||||
|
record = analyze_gcode_file(p)
|
||||||
if not record:
|
if not record:
|
||||||
log.error(
|
log.error(
|
||||||
f"Unable to analyze {unanalyzed.path} ({unanalyzed.filename} owned by {unanalyzed.user_id})!"
|
f"Unable to analyze {file.path} ({file.filename} owned by {file.user_id})!"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
db.delete_file(uid=file.user_id, fid=file.id)
|
||||||
|
db.delete_file_analysis_by_fid(fid=file.id)
|
||||||
|
db.delete_jobs_by_fid(uid=file.user_id, fid=file.id)
|
||||||
|
|
||||||
|
if os.path.exists(file.path):
|
||||||
|
os.unlink(file.path)
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
db.create_email(
|
||||||
|
uid=file.user_id,
|
||||||
|
subject=f"Failure to print: {file.filename}",
|
||||||
|
body=render_template(
|
||||||
|
"analysis_failure_email.html.j2",
|
||||||
|
username=db.fetch_user(uid=file.user_id).name,
|
||||||
|
filename=file.filename,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
db.create_analysis(
|
db.create_analysis(
|
||||||
file_id=unanalyzed.id,
|
file_id=file.id,
|
||||||
max_x=record.max_x,
|
max_x=record.max_x,
|
||||||
max_y=record.max_y,
|
max_y=record.max_y,
|
||||||
max_z=record.max_z,
|
max_z=record.max_z,
|
||||||
|
|
Loading…
Reference in a new issue