326 lines
12 KiB
Python
326 lines
12 KiB
Python
from django.contrib.auth.decorators import login_required
|
|
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
|
from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from catalog.models import Item
|
|
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
|
from mastodon.api import share_collection
|
|
from users.models import User
|
|
from users.models.apidentity import APIdentity
|
|
from users.views import render_user_blocked, render_user_not_found
|
|
|
|
from ..forms import *
|
|
from ..models import *
|
|
from .common import render_relogin, target_identity_required
|
|
|
|
|
|
@login_required
|
|
def add_to_collection(request: AuthedHttpRequest, item_uuid):
|
|
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
|
if request.method == "GET":
|
|
collections = Collection.objects.filter(owner=request.user.identity)
|
|
return render(
|
|
request,
|
|
"add_to_collection.html",
|
|
{
|
|
"item": item,
|
|
"collections": collections,
|
|
},
|
|
)
|
|
else:
|
|
cid = int(request.POST.get("collection_id", default=0))
|
|
if not cid:
|
|
cid = Collection.objects.create(
|
|
owner=request.user.identity, title=f"{request.user.display_name}的收藏单"
|
|
).id
|
|
collection = Collection.objects.get(owner=request.user.identity, id=cid)
|
|
collection.append_item(item, note=request.POST.get("note"))
|
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
|
|
|
|
def collection_retrieve(request: AuthedHttpRequest, collection_uuid):
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_visible_to(request.user):
|
|
raise PermissionDenied()
|
|
follower_count = collection.likes.all().count()
|
|
following = (
|
|
Like.user_liked_piece(request.user.identity, collection)
|
|
if request.user.is_authenticated
|
|
else False
|
|
)
|
|
featured_since = (
|
|
collection.featured_since(request.user.identity)
|
|
if request.user.is_authenticated
|
|
else None
|
|
)
|
|
available_as_featured = (
|
|
request.user.is_authenticated
|
|
and (following or request.user.identity == collection.owner)
|
|
and not featured_since
|
|
and collection.members.all().exists()
|
|
)
|
|
stats = {}
|
|
if featured_since:
|
|
stats = collection.get_stats(request.user.identity)
|
|
stats["wishlist_deg"] = (
|
|
round(stats["wishlist"] / stats["total"] * 360) if stats["total"] else 0
|
|
)
|
|
stats["progress_deg"] = (
|
|
round(stats["progress"] / stats["total"] * 360) if stats["total"] else 0
|
|
)
|
|
stats["complete_deg"] = (
|
|
round(stats["complete"] / stats["total"] * 360) if stats["total"] else 0
|
|
)
|
|
return render(
|
|
request,
|
|
"collection.html",
|
|
{
|
|
"collection": collection,
|
|
"follower_count": follower_count,
|
|
"following": following,
|
|
"stats": stats,
|
|
"available_as_featured": available_as_featured,
|
|
"featured_since": featured_since,
|
|
"editable": collection.is_editable_by(request.user),
|
|
},
|
|
)
|
|
|
|
|
|
@login_required
|
|
def collection_add_featured(request: AuthedHttpRequest, collection_uuid):
|
|
if request.method != "POST":
|
|
raise BadRequest()
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_visible_to(request.user):
|
|
raise PermissionDenied()
|
|
FeaturedCollection.objects.update_or_create(
|
|
owner=request.user.identity, target=collection
|
|
)
|
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
|
|
|
|
@login_required
|
|
def collection_remove_featured(request: AuthedHttpRequest, collection_uuid):
|
|
if request.method != "POST":
|
|
raise BadRequest()
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_visible_to(request.user):
|
|
raise PermissionDenied()
|
|
fc = FeaturedCollection.objects.filter(
|
|
owner=request.user.identity, target=collection
|
|
).first()
|
|
if fc:
|
|
fc.delete()
|
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
|
|
|
|
@login_required
|
|
def collection_share(request: AuthedHttpRequest, collection_uuid):
|
|
collection = (
|
|
get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if collection_uuid
|
|
else None
|
|
)
|
|
if collection and not collection.is_visible_to(request.user):
|
|
raise PermissionDenied()
|
|
if request.method == "GET":
|
|
return render(request, "collection_share.html", {"collection": collection})
|
|
elif request.method == "POST":
|
|
visibility = int(request.POST.get("visibility", default=0))
|
|
comment = request.POST.get("comment")
|
|
if share_collection(collection, comment, request.user, visibility):
|
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
else:
|
|
return render_relogin(request)
|
|
else:
|
|
raise BadRequest()
|
|
|
|
|
|
def collection_retrieve_items(
|
|
request: AuthedHttpRequest, collection_uuid, edit=False, msg=None
|
|
):
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_visible_to(request.user):
|
|
raise PermissionDenied()
|
|
form = CollectionForm(instance=collection)
|
|
return render(
|
|
request,
|
|
"collection_items.html",
|
|
{
|
|
"collection": collection,
|
|
"form": form,
|
|
"collection_edit": edit or request.GET.get("edit"),
|
|
"msg": msg,
|
|
},
|
|
)
|
|
|
|
|
|
@login_required
|
|
def collection_append_item(request: AuthedHttpRequest, collection_uuid):
|
|
if request.method != "POST":
|
|
raise BadRequest()
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_editable_by(request.user):
|
|
raise PermissionDenied()
|
|
|
|
url = request.POST.get("url")
|
|
note = request.POST.get("note")
|
|
item = Item.get_by_url(url)
|
|
if item:
|
|
collection.append_item(item, note=note)
|
|
collection.save()
|
|
msg = None
|
|
else:
|
|
msg = _("条目链接无法识别,请输入本站已有条目的链接。")
|
|
return collection_retrieve_items(request, collection_uuid, True, msg)
|
|
|
|
|
|
@login_required
|
|
def collection_remove_item(request: AuthedHttpRequest, collection_uuid, item_uuid):
|
|
if request.method != "POST":
|
|
raise BadRequest()
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
|
if not collection.is_editable_by(request.user):
|
|
raise PermissionDenied()
|
|
collection.remove_item(item)
|
|
return collection_retrieve_items(request, collection_uuid, True)
|
|
|
|
|
|
@login_required
|
|
def collection_move_item(
|
|
request: AuthedHttpRequest, direction, collection_uuid, item_uuid
|
|
):
|
|
if request.method != "POST":
|
|
raise BadRequest()
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_editable_by(request.user):
|
|
raise PermissionDenied()
|
|
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
|
if direction == "up":
|
|
collection.move_up_item(item)
|
|
else:
|
|
collection.move_down_item(item)
|
|
return collection_retrieve_items(request, collection_uuid, True)
|
|
|
|
|
|
@login_required
|
|
def collection_update_member_order(request: AuthedHttpRequest, collection_uuid):
|
|
if request.method != "POST":
|
|
raise BadRequest()
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_editable_by(request.user):
|
|
raise PermissionDenied()
|
|
ids = request.POST.get("member_ids", "").strip()
|
|
if not ids:
|
|
raise BadRequest()
|
|
ordered_member_ids = [int(i) for i in ids.split(",")]
|
|
collection.update_member_order(ordered_member_ids)
|
|
return collection_retrieve_items(request, collection_uuid, True)
|
|
|
|
|
|
@login_required
|
|
def collection_update_item_note(request: AuthedHttpRequest, collection_uuid, item_uuid):
|
|
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if not collection.is_editable_by(request.user):
|
|
raise PermissionDenied()
|
|
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
|
if not collection.is_editable_by(request.user):
|
|
raise PermissionDenied()
|
|
if request.method == "POST":
|
|
collection.update_item_metadata(
|
|
item, {"note": request.POST.get("note", default="")}
|
|
)
|
|
return collection_retrieve_items(request, collection_uuid, True)
|
|
elif request.method == "GET":
|
|
member = collection.get_member_for_item(item)
|
|
return render(
|
|
request,
|
|
"collection_update_item_note.html",
|
|
{"collection": collection, "item": item, "note": member.note},
|
|
)
|
|
else:
|
|
raise BadRequest()
|
|
|
|
|
|
@login_required
|
|
def collection_edit(request: AuthedHttpRequest, collection_uuid=None):
|
|
collection = (
|
|
get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
|
|
if collection_uuid
|
|
else None
|
|
)
|
|
if collection and not collection.is_editable_by(request.user):
|
|
raise PermissionDenied()
|
|
if request.method == "GET":
|
|
form = CollectionForm(instance=collection) if collection else CollectionForm()
|
|
if request.GET.get("title"):
|
|
form.instance.title = request.GET.get("title")
|
|
return render(
|
|
request,
|
|
"collection_edit.html",
|
|
{
|
|
"form": form,
|
|
"collection": collection,
|
|
"user": collection.owner.user if collection else request.user,
|
|
"identity": collection.owner if collection else request.user.identity,
|
|
},
|
|
)
|
|
elif request.method == "POST":
|
|
form = (
|
|
CollectionForm(request.POST, request.FILES, instance=collection)
|
|
if collection
|
|
else CollectionForm(request.POST)
|
|
)
|
|
if form.is_valid():
|
|
if not collection:
|
|
form.instance.owner = request.user.identity
|
|
form.save()
|
|
return redirect(
|
|
reverse("journal:collection_retrieve", args=[form.instance.uuid])
|
|
)
|
|
else:
|
|
raise BadRequest()
|
|
else:
|
|
raise BadRequest()
|
|
|
|
|
|
@login_required
|
|
@target_identity_required
|
|
def user_collection_list(request: AuthedHttpRequest, user_name):
|
|
target = request.target_identity
|
|
collections = Collection.objects.filter(owner=target).filter(
|
|
q_owned_piece_visible_to_user(request.user, target)
|
|
)
|
|
return render(
|
|
request,
|
|
"user_collection_list.html",
|
|
{
|
|
"user": target.user,
|
|
"identity": target,
|
|
"collections": collections,
|
|
},
|
|
)
|
|
|
|
|
|
@login_required
|
|
@target_identity_required
|
|
def user_liked_collection_list(request: AuthedHttpRequest, user_name):
|
|
target = request.target_identity
|
|
collections = Collection.objects.filter(likes__owner=target)
|
|
if target.user != request.user:
|
|
collections = collections.filter(q_piece_visible_to_user(request.user))
|
|
return render(
|
|
request,
|
|
"user_collection_list.html",
|
|
{
|
|
"user": target.user,
|
|
"identity": target,
|
|
"collections": collections,
|
|
"liked": True,
|
|
},
|
|
)
|