def octoprint_http_tunnel(request, pk): # We need to catch the moment when tunnel page loads, # and redirect to v2 url if plugin version is compatible. if request.path == tunnel_views.URL_PREFIX.format(pk=pk) + '/': get_printer_or_404(pk, request) version = (cache.printer_settings_get(pk) or {}).get('tsd_plugin_version', '') if tunnelv2_views.is_plugin_version_supported(version): return tunnelv2_views.redirect_to_tunnel_url(request, pk) return tunnel_views.octoprint_http_tunnel(request, pk)
def tunnel(request, pk, template_dir=None): get_printer_or_404(pk, request) version = (cache.printer_settings_get(pk) or {}).get('tsd_plugin_version', '') is_v1 = version and not is_plugin_version_supported(version) return render( request, get_template_path('tunnel', template_dir), {"v1": is_v1}, )
def response_from_printer(self, request): printer = get_printer_or_404(request.GET.get('printer_id'), request) return Response( self.serializer_class( SharedResource.objects.select_related('printer').filter( printer=printer), many=True).data)
def create(self, request): printer = get_printer_or_404(request.GET.get('printer_id'), request) # When the GET API is slow, the user may try to turn on the sharing toggle when it's on already SharedResource.objects.get_or_create( printer=printer, defaults={'share_token': hexlify(os.urandom(18)).decode()}) return self.response_from_printer(request)
def send_webhook_test(self, request, pk=None): printer = get_printer_or_404(pk, request) req = requests.post(url=settings.EXT_3D_GEEKS_ENDPOINT, json=dict(token=printer.service_token, event="test")) req.raise_for_status() return Response(dict(status='okay'))
def integration(request, pk): printer = get_printer_or_404(pk, request) if request.method == "POST": if request.POST.get('enable') == 't' and not printer.service_token: printer.service_token = hexlify(os.urandom(24)).decode() printer.save() elif request.POST.get('enable') == 'f': printer.service_token = None printer.save() messages.success( request, "3D Geeks integration has been turned off successfully.") return render(request, 'printer_integration.html', {'printer': printer})
def create(self, request): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) validated_data = serializer.validated_data printer = get_printer_or_404(validated_data['target_printer_id'], request) app_name = validated_data['app_name'] if not app_name or app_name == OctoPrintTunnel.INTERNAL_APP: raise PermissionDenied tunnel = OctoPrintTunnel.create(printer, app_name) tunnel_endpoint = tunnel.get_basicauth_url(request, tunnel.plain_basicauth_password) return Response({'tunnel_endpoint': tunnel_endpoint}, status=status.HTTP_201_CREATED)
def share_printer(request, pk, template_dir=None): printer = get_printer_or_404(pk, request) if request.method == "POST": if request.POST.get('shared') == 'on': if not hasattr(printer, 'sharedresource'): SharedResource.objects.create(printer=printer, share_token=hexlify( os.urandom(18)).decode()) else: SharedResource.objects.filter(printer=printer).delete() messages.success( request, 'You have disabled printer feed sharing. Previous shareable link has now been revoked.' ) return render(request, get_template_path('share_printer', template_dir), dict(printer=printer, user=request.user))
def mute_current_print(self, request, pk=None): printer = get_printer_or_404(pk, request) printer.mute_current_print(request.GET.get('mute_alert', 'false').lower() == 'true') return self.send_command_response(printer, True)
def octoprint_http_tunnel(request, pk): get_printer_or_404(pk, request) if request.user.tunnel_usage_over_cap(): return HttpResponse( '<html><body><center><h1>Over Free Limit</h1><hr><h3 style="color: red;">Your month-to-date usage of OctoPrint Tunneling is over the free limit. Support this project and get unlimited tunneling by <a target="_blank" href="https://app.thespaghettidetective.com/ent_pub/pricing/">upgrading to The Spaghetti Detective Pro plan</a>, or wait for the reset of free limit at the start of the next month.</h3></center></body></html>', status=412) prefix = URL_PREFIX.format(pk=pk) method = request.method.lower() path = request.get_full_path()[len(prefix):] IGNORE_HEADERS = [ 'HTTP_HOST', 'HTTP_ORIGIN', 'HTTP_REFERER', 'HTTP_COOKIE', ] # Recreate http headers, because django put headers in request.META as "HTTP_XXX_XXX". Is there a better way? req_headers = { k[5:].replace("_", " ").title().replace(" ", "-"): v for (k, v) in request.META.items() if k.startswith("HTTP") and not k.startswith('HTTP_X_') and k not in IGNORE_HEADERS } if 'CONTENT_TYPE' in request.META: req_headers['Content-Type'] = request.META['CONTENT_TYPE'] ref = f'{pk}.{method}.{time.time()}.{path}' channels.send_msg_to_printer( pk, { "http.tunnel": { "ref": ref, "method": method, "headers": req_headers, "path": path, "data": request.body }, 'as_binary': True, }) data = cache.octoprinttunnel_http_response_get(ref) if data is None: return HttpResponse( '<html><body><center><h1>Timed Out</h1><hr><h3 style="color: red;">Either your OctoPrint is offline, or The Spaghetti Detective plugin version is lower than 1.4.0.</h3></center></body></html>', status=504) content_type = data['response']['headers'].get('Content-Type') or None resp = HttpResponse( status=data["response"]["status"], content_type=content_type, ) for k, v in data['response']['headers'].items(): if k in ['Content-Length', 'Content-Encoding']: continue if k == 'Etag': v = fix_etag(v) resp[k] = v url_path = urllib.parse.urlparse(path).path if data['response'].get('compressed', False): content = zlib.decompress(data['response']['content']) else: content = data['response']['content'] cache.octoprinttunnel_update_stats(request.user.id, len(content)) if content_type and content_type.startswith('text/html'): content = rewrite_html(prefix, ensure_bytes(content)) elif url_path.endswith('jquery.js') or url_path.endswith('jquery.min.js'): content = inject_ajax_prefilter(prefix, content) elif url_path.endswith('socket.js'): content = re.sub(_R_SOCKJS_TRANSPORTS, _rewrite_sockjs_transports, ensure_bytes(content)) elif url_path.endswith('packed_client.js'): content = re.sub(_R_SOCKJS_TRANSPORTS, _rewrite_sockjs_transports, ensure_bytes(content)) elif url_path.endswith('packed_libs.js'): content = re.sub(_R_WS_CONNECT_PATH, _rewrite_ws_connect_path, ensure_bytes(content)) content = inject_ajax_prefilter(prefix, content) elif url_path.endswith('sockjs.js'): content = re.sub(_R_WS_CONNECT_PATH, _rewrite_ws_connect_path, ensure_bytes(content)) elif url_path.endswith('sockjs.min.js'): content = re.sub(_R_WS_CONNECT_PATH, _rewrite_ws_connect_path, ensure_bytes(content)) resp.write(content) return resp
def redirect_to_tunnel_url(request, pk): printer = get_printer_or_404(pk, request) pt = OctoPrintTunnel.get_or_create_for_internal_use(printer) url = pt.get_internal_tunnel_url(request) return HttpResponseRedirect(url)
def partial_update(self, request, pk=None): self.get_queryset().filter(pk=pk).update(**request.data) printer = get_printer_or_404(pk, request) printer.send_should_watch_status() return self.send_command_response(printer, True)
def cancel_print(self, request, pk=None): printer = get_printer_or_404(pk, request) succeeded = printer.cancel_print(initiator='api') return self.send_command_response(printer, succeeded)
def create(self, request): printer = get_printer_or_404(request.GET.get('printer_id'), request) SharedResource.objects.create(printer=printer, share_token=hexlify( os.urandom(18)).decode()) return self.response_from_printer(request)
def acknowledge_alert(self, request, pk=None): printer = get_printer_or_404(pk, request) printer.acknowledge_alert(request.GET.get('alert_overwrite')) return self.send_command_response(printer, True)
def send_command(self, request, pk=None): printer = get_printer_or_404(pk, request) printer.send_octoprint_command(request.data['cmd'], request.data['args']) return self.send_command_response(printer, True)
def delete_printer(request, pk=None): printer = get_printer_or_404(pk, request, with_archived=True) printer.delete() messages.success(request, f'{printer.name} has been deleted!') return redirect('/printers/')
def resume_print(self, request, pk=None): printer = get_printer_or_404(pk, request) succeeded = printer.resume_print() return self.send_command_response(printer, succeeded)
def tunnel(request, pk, template_dir=None): get_printer_or_404(pk, request) return render( request, get_template_path('tunnel', template_dir), )