262 lines
7.7 KiB
Python
262 lines
7.7 KiB
Python
"""API that doesn't necessarily provide a gui interface."""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import html
|
|
import random
|
|
import urllib
|
|
import subprocess
|
|
|
|
from io import StringIO
|
|
from django.shortcuts import render
|
|
from django.http import HttpResponse, HttpRequest
|
|
from django.core.exceptions import PermissionDenied
|
|
|
|
from rest_framework.parsers import JSONParser, FileUploadParser
|
|
from rest_framework.renderers import JSONRenderer
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from .forms import UploadFileForm, UploadMarkdownForm, TodoForm
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from .models import MarkdownModel, NotificationModel
|
|
|
|
from todo.models import Todo
|
|
|
|
|
|
def index(request):
|
|
return render(request, "index/index.html", {})
|
|
|
|
|
|
def test(request):
|
|
return HttpResponse("test")
|
|
|
|
|
|
def addition(request):
|
|
"""Add a and b numbers together."""
|
|
a = int(request.GET.get("a"))
|
|
b = int(request.GET.get("b"))
|
|
return HttpResponse(str(a + b))
|
|
|
|
|
|
def random_req(request):
|
|
"""Return a random number."""
|
|
return HttpResponse(random.randint(0, 1000))
|
|
|
|
|
|
class ExampleView(APIView):
|
|
"""A view that can accept POST requests with JSON content."""
|
|
|
|
parser_classes = [JSONParser]
|
|
|
|
def post(self, request, format=None):
|
|
print("receiving stuff")
|
|
print(request.data)
|
|
return Response({"received data": request.data})
|
|
|
|
|
|
class FileUploadView(APIView):
|
|
"""A view that can receive files."""
|
|
|
|
parser_classes = [FileUploadParser]
|
|
|
|
def put(self, request, filename, format=None):
|
|
print(request.data)
|
|
# file_obj = request.data['file']
|
|
|
|
# print('received your file')
|
|
# print(file_obj)
|
|
# ...
|
|
# do some stuff with uploaded file
|
|
# ...
|
|
return Response(status=204)
|
|
|
|
# @csrf_exempt
|
|
# def as_view(self, *args, **kwargs):
|
|
# super().as_view(self, *args, **kwargs)
|
|
|
|
|
|
@csrf_exempt
|
|
def upload_file(request):
|
|
"""Another view that can receive files."""
|
|
if request.method == "POST":
|
|
print("pass")
|
|
form = UploadFileForm(request.POST, request.FILES)
|
|
if form.is_valid():
|
|
print(request.FILES["file"])
|
|
# handle_uploaded_file(request.FILES['file'])
|
|
return HttpResponseRedirect("/success/url/")
|
|
else:
|
|
print("did not pass")
|
|
form = UploadFileForm()
|
|
return HttpResponse("response")
|
|
# return render(request, 'upload.html', {'form': form})
|
|
|
|
|
|
@csrf_exempt
|
|
def upload_markdown(request):
|
|
"""Markdown Uploader"""
|
|
print("received markdown")
|
|
if request.method == "POST":
|
|
form = UploadMarkdownForm(request.POST, request.FILES)
|
|
file = str(form.files["file"])
|
|
filepath = f"{os.getcwd()}/media/article/{file}"
|
|
print("trying to post:", filepath)
|
|
content = form.files["file"].file.read().decode("utf-8")
|
|
lines = content.split("\n")
|
|
if lines[0].startswith("#!"):
|
|
lines = lines[1:]
|
|
content = "\n".join(lines).strip()
|
|
with open(filepath, "w") as f:
|
|
f.write(content)
|
|
if form.is_valid():
|
|
print(form)
|
|
form.save()
|
|
return HttpResponse("success")
|
|
else:
|
|
return HttpResponse("invalid form")
|
|
elif request.method == "GET":
|
|
form = UploadMarkdownForm()
|
|
context = {
|
|
"form": form,
|
|
}
|
|
return render(request, "api/upload.html", context)
|
|
return HttpResponse("only get and post methods are allowed")
|
|
|
|
|
|
def view_markdown(request):
|
|
context = {"markdown_object": MarkdownModel.objects.all()[0]}
|
|
return render(request, "api/view-markdown.html", context)
|
|
|
|
|
|
users = {}
|
|
|
|
|
|
@csrf_exempt
|
|
def login(request):
|
|
"""Log api user view."""
|
|
print(request.POST)
|
|
user = request.POST["user"]
|
|
password = request.POST["password"]
|
|
print(user, password)
|
|
print(os.environ["WEBSITE_USER"], os.environ["WEBSITE_PASSWORD"])
|
|
if (user, password) != (os.environ["WEBSITE_USER"], os.environ["WEBSITE_PASSWORD"]):
|
|
raise PermissionDenied
|
|
token = int(hash(random.random()) / 1000)
|
|
print(f"python-shell: {user} logs with {token}\n")
|
|
users[token] = dict(locals={}, python=False, name=user)
|
|
return HttpResponse('{"token":' + str(token) + "}")
|
|
|
|
|
|
class Capturing(list):
|
|
"""Capture print output and store it."""
|
|
|
|
def __enter__(self):
|
|
self._stdout = sys.stdout
|
|
sys.stdout = self._stringio = StringIO()
|
|
return self
|
|
|
|
def __exit__(self, *args):
|
|
self.extend(self._stringio.getvalue().splitlines())
|
|
del self._stringio # free up some memory
|
|
sys.stdout = self._stdout
|
|
|
|
|
|
@csrf_exempt
|
|
def python(request, cmd: str):
|
|
"""Python view."""
|
|
cmd = html.unescape(cmd)
|
|
token = int(request.POST["token"])
|
|
user = users[token]
|
|
locals_ = user["locals"]
|
|
print(f"python: {user['name']} runs \"{cmd}\" given {locals_}")
|
|
try:
|
|
with Capturing() as out:
|
|
exec(cmd, globals(), locals_)
|
|
if not out:
|
|
try:
|
|
with Capturing() as out:
|
|
exec(f"print({cmd})", globals(), locals_)
|
|
except:
|
|
out = []
|
|
print(f"which returns {out}\n")
|
|
text = "\n".join([f"{line}" for line in out])
|
|
return HttpResponse(urllib.parse.quote(text))
|
|
except:
|
|
text = "\n".join([f"{line}" for line in out])
|
|
return HttpResponse(urllib.parse.quote(text), status=500)
|
|
|
|
|
|
@csrf_exempt
|
|
def todo_index(request: HttpRequest):
|
|
"""View todos or post new todo."""
|
|
if request.method == "GET":
|
|
todos = Todo.objects.all()
|
|
print(todos)
|
|
# serializer = SnippetSerializer(snippets, many=True)
|
|
# return JsonResponse(serializer.data, safe=False)
|
|
content = json.dumps(list(todos))
|
|
return HttpResponse(content)
|
|
|
|
elif request.method == "POST":
|
|
print(request)
|
|
form = TodoForm(request)
|
|
if form.is_valid():
|
|
form.save()
|
|
return HttpResponse("ok", status=200)
|
|
return HttpResponse("not", status=500)
|
|
# data = JSONParser().parse(request)
|
|
# print(data)
|
|
# serializer = SnippetSerializer(data=data)
|
|
# if serializer.is_valid():
|
|
# serializer.save()
|
|
# return JsonResponse(serializer.data, status=200)
|
|
# return JsonResponse(serializer.errors, status=400)
|
|
|
|
|
|
@csrf_exempt
|
|
def todo(request: HttpRequest, id: int):
|
|
"""View, update or delete existing todo."""
|
|
todo = Todo.objects.filter(id=id)
|
|
if request.method == "GET":
|
|
content = json.dumps(todo.__dict__)
|
|
return HttpResponse(content, mimetype="application/x-json")
|
|
|
|
elif request.method == "POST":
|
|
pass
|
|
data = JSONParser().parse(request)
|
|
return data
|
|
|
|
# return Json
|
|
|
|
|
|
@csrf_exempt
|
|
def port(request: HttpRequest, n: int = 1):
|
|
"""Return a random available port within a given range."""
|
|
port_min = os.environ.get("PORT_MIN") or 8000
|
|
port_max = os.environ.get("PORT_MAX") or 8099
|
|
cmd = f'bash -c "comm -23 <(seq {port_min} {port_max} '
|
|
cmd += "| sort) <(ss -Htan | awk '{print $4}' "
|
|
cmd += f"| cut -d':' -f2 | sort -u) | shuf | head -n {n}\""
|
|
print(cmd)
|
|
result = subprocess.check_output(cmd, shell=True)
|
|
print(result)
|
|
return HttpResponse(result)
|
|
|
|
@csrf_exempt
|
|
def notify(request: HttpRequest):
|
|
"""Notify me with a get request container
|
|
a get variable `message`."""
|
|
message = request.GET.get("message")
|
|
return HttpResponse("")
|
|
|
|
@csrf_exempt
|
|
def notifications(request: HttpRequest):
|
|
"""Return the list of notifications."""
|
|
notifications = NotificationModel.objects.filter(seen=False)
|
|
for notification in notifications:
|
|
notification.seen = True
|
|
notification.save()
|
|
return JsonResponse(notifications)
|