Group pastes from a same upload with the same slug.
This commit is contained in:
parent
14c6436b23
commit
1b1c3a1a47
|
@ -3,6 +3,7 @@ from datetime import datetime, timedelta
|
|||
import shortuuid
|
||||
from django.core.validators import MaxLengthValidator
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
@ -25,15 +26,35 @@ class Paste(models.Model):
|
|||
"""Computes size."""
|
||||
self.size = len(self.content)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("short_paste", kwargs={"slug": self.slug})
|
||||
|
||||
def incr_viewcount(self):
|
||||
"""Increment view counter."""
|
||||
self.viewcount = self.viewcount + 1
|
||||
self.save()
|
||||
|
||||
def __str__(self):
|
||||
excerpt = repr(self.content[:100]) + ("..." if len(self.content) > 100 else "")
|
||||
excerpt = repr(self.content.split("\n")[0][:100]) + (
|
||||
"..." if len(self.content) > 100 else ""
|
||||
)
|
||||
return f"{self.slug} - {excerpt}"
|
||||
|
||||
@classmethod
|
||||
def choose_prefix(cls, filenames):
|
||||
"""Find a prefix free for all the given filenames.
|
||||
|
||||
Such as <prefix>/filename is unused.
|
||||
"""
|
||||
while True:
|
||||
uuid = shortuuid.uuid()
|
||||
for i in range(4, len(uuid) + 1):
|
||||
potential_uuid = uuid[:i]
|
||||
for filename in filenames:
|
||||
slug = f"{potential_uuid}/{filename}"
|
||||
if not any(cls.objects.filter(slug=slug) for filename in filenames):
|
||||
return potential_uuid
|
||||
|
||||
def choose_slug(self):
|
||||
while True:
|
||||
uuid = shortuuid.uuid()
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{% load i18n %}{% load compress %}<!doctype html>
|
||||
{% load i18n compress static %}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
{% compress css %}
|
||||
<link href="/static/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="/static/css/pygments-highlight.css" rel="stylesheet">
|
||||
<link href="{% static 'css/font-awesome.min.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'css/pygments-highlight.css' %}" rel="stylesheet">
|
||||
{% endcompress %}
|
||||
{% block extrastyle %}{% endblock %}
|
||||
<title>{% block title %}{{ DISPLAY_NAME }}{% endblock %}</title>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% block extrastyle %}
|
||||
<link href="/static/css/github-markdown.css" rel="stylesheet">
|
||||
<link href="{% static 'css/github-markdown.css' %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block title %}{{ filename }}{% endblock %}
|
||||
{% block content %}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% block extrastyle %}
|
||||
<link href="/static/css/pasteque.css" rel="stylesheet">
|
||||
<link href="{% static 'css/pasteque.css' %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block title %}{{ filename }}{% endblock %}
|
||||
{% block content %}
|
||||
|
|
|
@ -6,6 +6,6 @@ from webtools import settings
|
|||
|
||||
urlpatterns = [
|
||||
path("", views.index, name="index"),
|
||||
path("static/<path>", serve, {"document_root": settings.STATIC_ROOT}),
|
||||
path("<slug>", views.show, name="short_paste"),
|
||||
path("::/static/<path>", serve, {"document_root": settings.STATIC_ROOT}),
|
||||
path("<path:slug>", views.show, name="short_paste"),
|
||||
]
|
||||
|
|
|
@ -10,7 +10,6 @@ from markdown.extensions.codehilite import CodeHiliteExtension
|
|||
from pygments.formatters import HtmlFormatter
|
||||
from pygments.lexers import get_lexer_by_name, get_lexer_for_filename
|
||||
|
||||
|
||||
ALLOWED_TAGS = [
|
||||
# Bleach Defaults
|
||||
"a",
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
from functools import lru_cache
|
||||
from mimetypes import common_types, types_map
|
||||
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.template import RequestContext, loader
|
||||
from django.urls import reverse
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from tabulate import tabulate
|
||||
|
||||
|
@ -14,7 +13,8 @@ from webtools import settings
|
|||
|
||||
NON_STANDARD_TYPES_INV = {value: key for key, value in common_types.items()}
|
||||
STANDARD_TYPES_INV = {value: key for key, value in types_map.items()}
|
||||
TYPES_INV = NON_STANDARD_TYPES_INV | STANDARD_TYPES_INV
|
||||
HARDCODED_TYPES_INV = {"text/plain": ".txt"}
|
||||
TYPES_INV = NON_STANDARD_TYPES_INV | STANDARD_TYPES_INV | HARDCODED_TYPES_INV
|
||||
|
||||
|
||||
def get_files(request):
|
||||
|
@ -24,7 +24,9 @@ def get_files(request):
|
|||
return request.FILES
|
||||
content_type = request.headers.get("content-type", "")
|
||||
ext = TYPES_INV.get(content_type, "")
|
||||
if ext:
|
||||
return {"request" + ext: request}
|
||||
return {"": request}
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
|
@ -35,36 +37,37 @@ def index(request):
|
|||
if request.headers.get("Expect") == "100-continue":
|
||||
return HttpResponse("")
|
||||
pastes = []
|
||||
for filename, the_file in get_files(request).items():
|
||||
files = get_files(request)
|
||||
prefix = Paste.choose_prefix(list(files.keys()))
|
||||
for filename, the_file in files.items():
|
||||
filename = filename.replace("\\", "/")
|
||||
paste = Paste(
|
||||
filename=filename.split("/")[-1].split("\\")[-1],
|
||||
slug=f"{prefix}/{filename}".rstrip("/"),
|
||||
filename=filename.split("/")[-1],
|
||||
content=the_file.read().decode("UTF-8"),
|
||||
)
|
||||
paste.choose_slug()
|
||||
paste.compute_size()
|
||||
paste.save()
|
||||
pastes.append(
|
||||
pastes.append(paste)
|
||||
|
||||
table = [
|
||||
(
|
||||
request.build_absolute_uri(
|
||||
reverse("short_paste", kwargs={"slug": paste.slug})
|
||||
),
|
||||
request.build_absolute_uri(paste.get_absolute_url()),
|
||||
paste.size,
|
||||
paste.filename,
|
||||
)
|
||||
)
|
||||
|
||||
if not pastes:
|
||||
return HttpResponse("error: Please provide a file.")
|
||||
|
||||
for paste in pastes
|
||||
]
|
||||
return HttpResponse(
|
||||
tabulate(pastes, headers=("URL", "size", "filename"), tablefmt="github") + "\n",
|
||||
tabulate(table, headers=("URL", "size", "filename"), tablefmt="github") + "\n",
|
||||
content_type="text/plain",
|
||||
)
|
||||
|
||||
|
||||
def show(request, slug):
|
||||
"""Display paste."""
|
||||
|
||||
if slug.startswith("::"):
|
||||
raise Http404()
|
||||
paste = get_object_or_404(Paste, slug=slug)
|
||||
paste.incr_viewcount()
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ MEDIA_URL = ""
|
|||
COMPRESS_ROOT = os.path.join(SITE_ROOT, "static")
|
||||
MEDIA_ROOT = os.path.join(SITE_ROOT, "assets")
|
||||
STATIC_ROOT = os.path.join(SITE_ROOT, "static")
|
||||
STATIC_URL = "/static/"
|
||||
STATIC_URL = "/::/static/"
|
||||
STATICFILES_FINDERS = (
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
|
|
|
@ -2,6 +2,6 @@ from django.contrib import admin
|
|||
from django.urls import path, include
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('', include('paste.urls')),
|
||||
path("::/admin/", admin.site.urls),
|
||||
path("", include("paste.urls")),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue