Merge branch 'main' into report-actions
This commit is contained in:
commit
a166af9990
88 changed files with 15768 additions and 326 deletions
|
@ -11,7 +11,23 @@ from django import forms
|
|||
import redis
|
||||
|
||||
from celerywyrm import settings
|
||||
from bookwyrm.tasks import app as celery, LOW, MEDIUM, HIGH, IMPORTS, BROADCAST
|
||||
from bookwyrm.tasks import (
|
||||
app as celery,
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
STREAMS,
|
||||
IMAGES,
|
||||
SUGGESTED_USERS,
|
||||
EMAIL,
|
||||
CONNECTORS,
|
||||
LISTS,
|
||||
INBOX,
|
||||
IMPORTS,
|
||||
IMPORT_TRIGGERED,
|
||||
BROADCAST,
|
||||
MISC,
|
||||
)
|
||||
|
||||
r = redis.from_url(settings.REDIS_BROKER_URL)
|
||||
|
||||
|
@ -41,8 +57,17 @@ class CeleryStatus(View):
|
|||
LOW: r.llen(LOW),
|
||||
MEDIUM: r.llen(MEDIUM),
|
||||
HIGH: r.llen(HIGH),
|
||||
STREAMS: r.llen(STREAMS),
|
||||
IMAGES: r.llen(IMAGES),
|
||||
SUGGESTED_USERS: r.llen(SUGGESTED_USERS),
|
||||
EMAIL: r.llen(EMAIL),
|
||||
CONNECTORS: r.llen(CONNECTORS),
|
||||
LISTS: r.llen(LISTS),
|
||||
INBOX: r.llen(INBOX),
|
||||
IMPORTS: r.llen(IMPORTS),
|
||||
IMPORT_TRIGGERED: r.llen(IMPORT_TRIGGERED),
|
||||
BROADCAST: r.llen(BROADCAST),
|
||||
MISC: r.llen(MISC),
|
||||
}
|
||||
# pylint: disable=broad-except
|
||||
except Exception as err:
|
||||
|
@ -88,8 +113,17 @@ class ClearCeleryForm(forms.Form):
|
|||
(LOW, "Low prioirty"),
|
||||
(MEDIUM, "Medium priority"),
|
||||
(HIGH, "High priority"),
|
||||
(STREAMS, "Streams"),
|
||||
(IMAGES, "Images"),
|
||||
(SUGGESTED_USERS, "Suggested users"),
|
||||
(EMAIL, "Email"),
|
||||
(CONNECTORS, "Connectors"),
|
||||
(LISTS, "Lists"),
|
||||
(INBOX, "Inbox"),
|
||||
(IMPORTS, "Imports"),
|
||||
(IMPORT_TRIGGERED, "Import triggered"),
|
||||
(BROADCAST, "Broadcasts"),
|
||||
(MISC, "Misc"),
|
||||
],
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
)
|
||||
|
|
|
@ -157,6 +157,7 @@ def add_authors(request, data):
|
|||
"""helper for adding authors"""
|
||||
add_author = [author for author in request.POST.getlist("add_author") if author]
|
||||
if not add_author:
|
||||
data["add_author"] = []
|
||||
return data
|
||||
|
||||
data["add_author"] = add_author
|
||||
|
|
|
@ -13,7 +13,7 @@ from django.views import View
|
|||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from bookwyrm import activitypub, models
|
||||
from bookwyrm.tasks import app, MEDIUM, HIGH
|
||||
from bookwyrm.tasks import app, INBOX
|
||||
from bookwyrm.signatures import Signature
|
||||
from bookwyrm.utils import regex
|
||||
|
||||
|
@ -59,11 +59,7 @@ class Inbox(View):
|
|||
return HttpResponse()
|
||||
return HttpResponse(status=401)
|
||||
|
||||
# Make activities relating to follow/unfollow a high priority
|
||||
high = ["Follow", "Accept", "Reject", "Block", "Unblock", "Undo"]
|
||||
|
||||
priority = HIGH if activity_json["type"] in high else MEDIUM
|
||||
sometimes_async_activity_task(activity_json, queue=priority)
|
||||
sometimes_async_activity_task(activity_json)
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
|
@ -101,7 +97,7 @@ def raise_is_blocked_activity(activity_json):
|
|||
raise PermissionDenied()
|
||||
|
||||
|
||||
def sometimes_async_activity_task(activity_json, queue=MEDIUM):
|
||||
def sometimes_async_activity_task(activity_json):
|
||||
"""Sometimes we can effectively respond to a request without queuing a new task,
|
||||
and whenever that is possible, we should do it."""
|
||||
activity = activitypub.parse(activity_json)
|
||||
|
@ -111,10 +107,10 @@ def sometimes_async_activity_task(activity_json, queue=MEDIUM):
|
|||
activity.action(allow_external_connections=False)
|
||||
except activitypub.ActivitySerializerError:
|
||||
# if that doesn't work, run it asynchronously
|
||||
activity_task.apply_async(args=(activity_json,), queue=queue)
|
||||
activity_task.apply_async(args=(activity_json,))
|
||||
|
||||
|
||||
@app.task(queue=MEDIUM)
|
||||
@app.task(queue=INBOX)
|
||||
def activity_task(activity_json):
|
||||
"""do something with this json we think is legit"""
|
||||
# lets see if the activitypub module can make sense of this json
|
||||
|
|
|
@ -74,6 +74,7 @@ class Register(View):
|
|||
password,
|
||||
localname=localname,
|
||||
local=True,
|
||||
allow_reactivation=settings.require_confirm_email,
|
||||
deactivation_reason="pending" if settings.require_confirm_email else None,
|
||||
is_active=not settings.require_confirm_email,
|
||||
preferred_timezone=preferred_timezone,
|
||||
|
@ -105,7 +106,9 @@ class ConfirmEmailCode(View):
|
|||
|
||||
# look up the user associated with this code
|
||||
try:
|
||||
user = models.User.objects.get(confirmation_code=code)
|
||||
user = models.User.objects.get(
|
||||
confirmation_code=code, deactivation_reason="pending"
|
||||
)
|
||||
except models.User.DoesNotExist:
|
||||
return TemplateResponse(
|
||||
request, "confirm_email/confirm_email.html", {"valid": False}
|
||||
|
|
|
@ -129,7 +129,7 @@ def sort_list(request, items):
|
|||
"""helper to handle the surprisingly involved sorting"""
|
||||
# sort_by shall be "order" unless a valid alternative is given
|
||||
sort_by = request.GET.get("sort_by", "order")
|
||||
if sort_by not in ("order", "title", "rating"):
|
||||
if sort_by not in ("order", "sort_title", "rating"):
|
||||
sort_by = "order"
|
||||
|
||||
# direction shall be "ascending" unless a valid alternative is given
|
||||
|
@ -139,7 +139,7 @@ def sort_list(request, items):
|
|||
|
||||
directional_sort_by = {
|
||||
"order": "order",
|
||||
"title": "book__title",
|
||||
"sort_title": "book__sort_title",
|
||||
"rating": "average_rating",
|
||||
}[sort_by]
|
||||
if direction == "descending":
|
||||
|
|
|
@ -203,7 +203,7 @@ def delete_readthrough(request):
|
|||
readthrough.raise_not_deletable(request.user)
|
||||
|
||||
readthrough.delete()
|
||||
return redirect("/")
|
||||
return redirect_to_referer(request)
|
||||
|
||||
|
||||
@login_required
|
||||
|
@ -214,4 +214,4 @@ def delete_progressupdate(request):
|
|||
update.raise_not_deletable(request.user)
|
||||
|
||||
update.delete()
|
||||
return redirect("/")
|
||||
return redirect_to_referer(request)
|
||||
|
|
|
@ -128,7 +128,7 @@ class Shelf(View):
|
|||
def sort_books(books, sort):
|
||||
"""Books in shelf sorting"""
|
||||
sort_fields = [
|
||||
"title",
|
||||
"sort_title",
|
||||
"author",
|
||||
"shelved_date",
|
||||
"start_date",
|
||||
|
|
|
@ -6,6 +6,7 @@ from urllib.parse import urlparse
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.validators import URLValidator
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, Http404
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
@ -57,6 +58,7 @@ class CreateStatus(View):
|
|||
return TemplateResponse(request, "compose.html", data)
|
||||
|
||||
# pylint: disable=too-many-branches
|
||||
@transaction.atomic
|
||||
def post(self, request, status_type, existing_status_id=None):
|
||||
"""create status of whatever type"""
|
||||
created = not existing_status_id
|
||||
|
@ -84,7 +86,6 @@ class CreateStatus(View):
|
|||
return redirect_to_referer(request)
|
||||
|
||||
status = form.save(request, commit=False)
|
||||
status.ready = False
|
||||
# save the plain, unformatted version of the status for future editing
|
||||
status.raw_content = status.content
|
||||
if hasattr(status, "quote"):
|
||||
|
@ -124,7 +125,6 @@ class CreateStatus(View):
|
|||
if hasattr(status, "quote"):
|
||||
status.quote = to_markdown(status.quote)
|
||||
|
||||
status.ready = True
|
||||
status.save(created=created)
|
||||
|
||||
# update a readthrough, if needed
|
||||
|
@ -310,6 +310,11 @@ def format_links(content):
|
|||
formatted_content += potential_link[0]
|
||||
potential_link = potential_link[1:-1]
|
||||
|
||||
ends_with_punctuation = _ends_with_punctuation(potential_link)
|
||||
if ends_with_punctuation:
|
||||
punctuation_glyph = potential_link[-1]
|
||||
potential_link = potential_link[0:-1]
|
||||
|
||||
try:
|
||||
# raises an error on anything that's not a valid link
|
||||
validator(potential_link)
|
||||
|
@ -329,6 +334,9 @@ def format_links(content):
|
|||
if wrapped:
|
||||
formatted_content += wrapper_close
|
||||
|
||||
if ends_with_punctuation:
|
||||
formatted_content += punctuation_glyph
|
||||
|
||||
return formatted_content
|
||||
|
||||
|
||||
|
@ -341,6 +349,15 @@ def _wrapped(text):
|
|||
return False
|
||||
|
||||
|
||||
def _ends_with_punctuation(text):
|
||||
"""check if a line of text ends with a punctuation glyph"""
|
||||
glyphs = [".", ",", ";", ":", "!", "?", "”", "’", '"', "»"]
|
||||
for glyph in glyphs:
|
||||
if text[-1] == glyph:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def to_markdown(content):
|
||||
"""catch links and convert to markdown"""
|
||||
content = format_links(content)
|
||||
|
|
|
@ -23,6 +23,9 @@ class User(View):
|
|||
"""profile page for a user"""
|
||||
user = get_user_from_username(request.user, username)
|
||||
|
||||
if not user.local and not request.user.is_authenticated:
|
||||
return redirect(user.remote_id)
|
||||
|
||||
if is_api_request(request):
|
||||
# we have a json request
|
||||
return ActivitypubResponse(user.to_activity())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue