Compare commits

...

2 commits

8 changed files with 97 additions and 16 deletions

View file

@ -64,6 +64,8 @@ def manipulate_files():
os.unlink(file.path)
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")
case _:

View file

@ -43,22 +43,23 @@ WHERE
user_id = :uid
;
-- name: delete-file*!
DELETE FROM jobs
-- name: delete-file!
DELETE FROM files
WHERE
user_id = :uid
AND file_id = :fid
AND id = :fid
;
-- name: delete-file-analysis-by-fid!
DELETE FROM file_analysis
WHERE
file_id = :fid
;
DELETE FROM files
-- name: delete-file-analysis!
DELETE FROM file_analysis
WHERE
user_id = :uid
AND id = :fid
id = :aid
;
-- name: fetch-file^

View file

@ -192,3 +192,10 @@ WHERE
user_id = :uid
AND id = :jid
;
-- name: delete-jobs-by-fid!
DELETE FROM jobs
WHERE
user_id = :uid
AND file_id = :fid
;

View file

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

View file

@ -3,13 +3,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<html lang="en">
<head>
<link rel="stylesheet" href="{{ base_url }}/static/css/style.css" />
<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="/">
<img src="{{ base_url }}/static/tentacles.svg" alt="Tentacles">
<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>

View file

@ -6,8 +6,8 @@
<div class="file row u-flex">
<div class="details six columns u-flex u-flex-wrap">
<span class="file-name">{{ file.filename }}</span>
<span class="file-sucesses">{{ file.print_successes }} successes</span>
<span class="file-failures">{{ file.print_failures }} errors</span>
<span class="file-sucesses"><label>Successes</label>{{ file.print_successes }}</span>
<span class="file-failures"><label>Failures</label>{{ file.print_failures }}</span>
</div>
<div class="controls u-flex u-ml-auto">
{{ macros.start_job(file.id) }}

View file

@ -8,7 +8,7 @@
<body>
<nav class="container navbar">
<span class="logo">
<a class="row" href="/">
<a class="row" href="{{ base_url }}">
<img src="{{ base_url }}/static/tentacles.svg" alt="Tentacles">
<span class="name color-yellow">Tentacles</span>
</a>

View file

@ -7,6 +7,7 @@ Supporting the core app with asynchronous maintenance tasks.
Mostly related to monitoring and managing Printer state.
"""
import os
from contextlib import closing
from functools import cache
import logging
@ -19,6 +20,7 @@ from cherrypy.process.plugins import Monitor
from fastmail import FastMailSMTP
from gcode import analyze_gcode_file
from flask import Flask as App
from flask import render_template
from octorest import OctoRest as _OR
from requests import Response
from requests.exceptions import (
@ -302,16 +304,40 @@ def send_emails(app, db: Db):
def analyze_files(app: App, db: Db):
for unanalyzed in db.list_unanalyzed_files():
record = analyze_gcode_file(Path(unanalyzed.path))
for file in db.list_unanalyzed_files():
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:
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
db.create_analysis(
file_id=unanalyzed.id,
file_id=file.id,
max_x=record.max_x,
max_y=record.max_y,
max_z=record.max_z,