Group pastes from a same upload with the same slug.

This commit is contained in:
Julien Palard 2023-04-25 10:49:36 +02:00
parent 14c6436b23
commit 1b1c3a1a47
Signed by: mdk
GPG Key ID: 0EFC1AC1006886F8
9 changed files with 59 additions and 33 deletions

View File

@ -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()

View File

@ -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>

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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"),
]

View File

@ -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",

View File

@ -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, "")
return {"request" + ext: request}
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(
(
request.build_absolute_uri(
reverse("short_paste", kwargs={"slug": paste.slug})
),
paste.size,
paste.filename,
)
pastes.append(paste)
table = [
(
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()

View File

@ -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",

View File

@ -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")),
]