140 lines
6.3 KiB
Python
140 lines
6.3 KiB
Python
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
from django.shortcuts import render, get_object_or_404
|
|
from django.urls import reverse_lazy
|
|
from django.utils import timezone
|
|
from bootstrap_modal_forms.generic import BSModalCreateView, BSModalLoginView
|
|
from .forms import CustomUserCreationForm, CustomAuthenticationForm
|
|
from django.views.generic.edit import FormView
|
|
from django.views.generic.list import ListView
|
|
from django.views.generic.detail import DetailView
|
|
from django.views import View
|
|
from .forms import FileFieldForm
|
|
from .models import Module, Version, Dependency
|
|
from PDMI import settings
|
|
from packaging.specifiers import SpecifierSet
|
|
from django.http import HttpResponse, JsonResponse
|
|
from django.utils import timezone
|
|
from markdownx.utils import markdownify
|
|
import os
|
|
import zipfile
|
|
import toml
|
|
import shutil
|
|
import magic
|
|
|
|
REQUIRED_FIELDS = ['name', 'description', 'version', 'bot_version']
|
|
|
|
class SignUpView(BSModalCreateView):
|
|
form_class = CustomUserCreationForm
|
|
template_name = 'store/signup_modal.html'
|
|
success_message = 'Success: Sign up succeeded. You can now Log in.'
|
|
success_url = reverse_lazy('store_front_page')
|
|
|
|
|
|
class CustomLoginView(BSModalLoginView):
|
|
authentication_form = CustomAuthenticationForm
|
|
template_name = 'store/login_modal.html'
|
|
success_message = 'Success: You were successfully logged in.'
|
|
extra_content = dict(success_url=reverse_lazy('index'))
|
|
|
|
class ModuleListView(ListView):
|
|
model = Module
|
|
paginate_by = 100
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['now'] = timezone.now()
|
|
return context
|
|
|
|
class ModuleDetailView(View):
|
|
def get(self, request, pk, req_ver="latest"):
|
|
module = get_object_or_404(Module, id=pk)
|
|
versions = Version.objects.filter(module=module)
|
|
deps = []
|
|
for version in versions:
|
|
deps.append(Dependency.objects.filter(version=version))
|
|
if req_ver == "latest":
|
|
view_version = Version.objects.filter(module=module).order_by('-id')[0]
|
|
else:
|
|
view_version = Version.objects.get(module=module, ver=req_ver)
|
|
return render(request, 'store/module_detail.html', {
|
|
'module': module,
|
|
'versions': versions,
|
|
'dependencies': deps,
|
|
'view_version': view_version,
|
|
'mdreadme': markdownify(view_version.readme),
|
|
})
|
|
|
|
|
|
class UploadView(LoginRequiredMixin, FormView):
|
|
form_class = FileFieldForm
|
|
template_name = 'store/upload.html'
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
form_class = self.get_form_class()
|
|
form = self.get_form(form_class)
|
|
files = request.FILES.getlist('file')
|
|
if form.is_valid():
|
|
for file in files:
|
|
zip_path = os.path.join(settings.MEDIA_ROOT, file.name)
|
|
extract_path = os.path.splitext(zip_path)[0]
|
|
with open(zip_path, "wb+") as f: # Writing archive
|
|
for chunk in file.chunks():
|
|
f.write(chunk)
|
|
# Check if uploaded file is a zip archive
|
|
if magic.from_file(zip_path, mime=True) != 'application/zip':
|
|
print(magic.from_file(zip_path))
|
|
os.remove(zip_path)
|
|
return JsonResponse({'error': 'You must upload a zip archive.'}, status=500)
|
|
|
|
with zipfile.ZipFile(zip_path, 'r') as zip: # Unzip archive
|
|
zip.extractall(extract_path)
|
|
with open(os.path.join(extract_path, 'infos.toml'), 'r') as f:
|
|
# Reading and parsing toml file
|
|
module_info = toml.loads(f.read())
|
|
if os.path.isfile(os.path.join(extract_path, 'README.md')):
|
|
with open(os.path.join(extract_path, 'README.md'), 'r') as f:
|
|
# Reading README.md file
|
|
readme = f.read()
|
|
else:
|
|
readme = "No readme provided."
|
|
for required_field in REQUIRED_FIELDS:
|
|
if not required_field in module_info.keys():
|
|
return JsonResponse({'error': f'Field {required_field}\
|
|
is missing in infos.toml.'}, status=500)
|
|
shutil.rmtree(extract_path)
|
|
os.remove(zip_path)
|
|
if Module.objects.filter(name=module_info['name'].lower(),
|
|
creator=request.user):
|
|
# If module exists
|
|
module = Module.objects.get(name=module_info['name'].lower(),
|
|
creator=request.user)
|
|
else:
|
|
# Else, creating module
|
|
module = Module(name=module_info['name'].lower(),
|
|
desc=module_info['description'],
|
|
creator=request.user)
|
|
if Version.objects.filter(module=module, ver=module_info['version']).exists():
|
|
# If version already exists, edit existing version
|
|
version = Version.objects.get(
|
|
module=module, ver=module_info['version'])
|
|
version.file = file
|
|
version.metamodule = module_info['metamodule']
|
|
version.bot_ver = module_info['bot_version']
|
|
version.readme = readme
|
|
else:
|
|
version = Version(module=module, ver=module_info['version'],
|
|
bot_ver=module_info['bot_version'],
|
|
metamodule=module_info['metamodule'],
|
|
file=file, readme=readme)
|
|
module.save()
|
|
version.save()
|
|
for dependency in module_info['dependencies']:
|
|
if not Dependency.objects.filter(version=version, dep_module=dependency,
|
|
dep_version=module_info['dependencies'][dependency]).exists():
|
|
dep = Dependency(version=version, dep_module=dependency,
|
|
dep_version=module_info['dependencies'][dependency])
|
|
dep.save()
|
|
return JsonResponse({'form': True})
|
|
else:
|
|
return JsonResponse({'form': False})
|