@@ -19,6 +19,17 @@ def get_octo_client():
|
||||
return OctoPrintClient(url.value, apikey.value)
|
||||
return None
|
||||
|
||||
def _enrich_job_data(job_data):
|
||||
if job_data and job_data.get('job', {}).get('file', {}).get('name'):
|
||||
from app.models import PrintFile
|
||||
internal_name = job_data['job']['file']['name']
|
||||
print_file = PrintFile.query.filter_by(filename=internal_name).first()
|
||||
if print_file and print_file.original_filename:
|
||||
job_data['job']['file']['display_name'] = print_file.original_filename
|
||||
else:
|
||||
job_data['job']['file']['display_name'] = internal_name
|
||||
return job_data
|
||||
|
||||
@printer_bp.route('/status')
|
||||
@login_required
|
||||
def status():
|
||||
@@ -29,7 +40,7 @@ def status():
|
||||
if client:
|
||||
try:
|
||||
status_data = client.get_printer_status()
|
||||
job_data = client.get_job_info()
|
||||
job_data = _enrich_job_data(client.get_job_info())
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
else:
|
||||
@@ -37,6 +48,20 @@ def status():
|
||||
|
||||
return render_template('printer/status.html', status=status_data, job=job_data, error=error)
|
||||
|
||||
@printer_bp.route('/api/status_data')
|
||||
@login_required
|
||||
def api_status_data():
|
||||
client = get_octo_client()
|
||||
if client:
|
||||
try:
|
||||
status_data = client.get_printer_status()
|
||||
job_data = _enrich_job_data(client.get_job_info())
|
||||
return jsonify({'success': True, 'status': status_data, 'job': job_data})
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)})
|
||||
return jsonify({'success': False, 'error': 'OctoPrint is not configured.'})
|
||||
|
||||
|
||||
def get_gcode_dir():
|
||||
conf = SystemConfig.query.filter_by(key='gcode_upload_folder').first()
|
||||
if conf and conf.value and os.path.exists(conf.value):
|
||||
@@ -102,13 +127,45 @@ def prepare():
|
||||
|
||||
return render_template('printer/prepare.html', files=files, error=error)
|
||||
|
||||
|
||||
def check_printer_control_permission(client):
|
||||
from flask_login import current_user
|
||||
if current_user.is_admin:
|
||||
return True, None
|
||||
|
||||
try:
|
||||
status_data = client.get_printer_status()
|
||||
state = status_data.get('state', {}).get('text', '')
|
||||
active_states = ['Printing', 'Paused', 'Pausing', 'Resuming', 'Cancelling']
|
||||
if state not in active_states:
|
||||
return True, None
|
||||
|
||||
job_info = client.get_job_info()
|
||||
internal_name = job_info.get('job', {}).get('file', {}).get('name')
|
||||
if not internal_name:
|
||||
return False, "现在有任务正在运行,非管理员无法进行控制。"
|
||||
|
||||
from app.models import PrintFile
|
||||
pf = PrintFile.query.filter_by(filename=internal_name).first()
|
||||
if pf and pf.user_id == current_user.id:
|
||||
return True, None
|
||||
else:
|
||||
return False, "现在有任务正在运行,您无权进行此操作。只有管理员或任务发起者可以进行控制。"
|
||||
except Exception:
|
||||
pass
|
||||
return True, None
|
||||
|
||||
@printer_bp.route('/api/print_file', methods=['POST'])
|
||||
|
||||
@login_required
|
||||
def api_print_file():
|
||||
path = request.json.get('path')
|
||||
location = request.json.get('origin', 'local')
|
||||
client = get_octo_client()
|
||||
if client and path:
|
||||
allowed, err_msg = check_printer_control_permission(client)
|
||||
if not allowed:
|
||||
return jsonify({"success": False, "error": err_msg})
|
||||
try:
|
||||
client.select_file(location, path, print_after_select=True)
|
||||
return jsonify({"success": True})
|
||||
@@ -117,14 +174,34 @@ def api_print_file():
|
||||
return jsonify({"success": False, "error": "Not configured or missing path"})
|
||||
|
||||
@printer_bp.route('/control')
|
||||
@login_required
|
||||
def control():
|
||||
client = get_octo_client()
|
||||
webcam_url = None
|
||||
error = None
|
||||
if client:
|
||||
try:
|
||||
webcam_url = client.get_webcam_stream_url()
|
||||
raw_url = client.get_webcam_stream_url()
|
||||
# If it's an absolute url pointing to the base url, strip it or proxy it via octo_proxy
|
||||
from urllib.parse import urlparse, urlencode
|
||||
parsed_raw = urlparse(raw_url)
|
||||
base_config = SystemConfig.query.filter_by(key='octoprint_url').first()
|
||||
if base_config and base_config.value:
|
||||
base_url = base_config.value.rstrip('/')
|
||||
parsed_base = urlparse(base_url)
|
||||
# If they share the same host, replace with proxy
|
||||
# Usually OctoPrint webcam streams are on the same host or relative
|
||||
path = parsed_raw.path
|
||||
if path.startswith('/'):
|
||||
path = path[1:]
|
||||
query = parsed_raw.query
|
||||
|
||||
# build proxy url
|
||||
if query:
|
||||
webcam_url = url_for('printer.octo_proxy', path=path) + '?' + query
|
||||
else:
|
||||
webcam_url = url_for('printer.octo_proxy', path=path)
|
||||
else:
|
||||
webcam_url = raw_url
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
else:
|
||||
@@ -137,6 +214,9 @@ def api_command():
|
||||
cmd = request.json.get('command')
|
||||
client = get_octo_client()
|
||||
if client and cmd:
|
||||
allowed, err_msg = check_printer_control_permission(client)
|
||||
if not allowed:
|
||||
return jsonify({"success": False, "error": err_msg})
|
||||
try:
|
||||
if cmd == 'home':
|
||||
client.home_axes()
|
||||
@@ -246,7 +326,7 @@ def octo_embed():
|
||||
@printer_bp.route('/proxy/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
|
||||
@login_required
|
||||
def octo_proxy(path):
|
||||
if not current_user.is_admin:
|
||||
if current_user.is_guest:
|
||||
return "Unauthorized", 403
|
||||
|
||||
url_config = SystemConfig.query.filter_by(key='octoprint_url').first()
|
||||
|
||||
Reference in New Issue
Block a user