2021-03-08 16:49:10 +00:00
|
|
|
""" views for actions you can take in the application """
|
2021-11-28 05:56:21 +00:00
|
|
|
import urllib.parse
|
|
|
|
import re
|
2021-01-13 21:36:01 +00:00
|
|
|
from django.contrib.auth.decorators import login_required
|
2021-09-27 23:04:40 +00:00
|
|
|
from django.shortcuts import get_object_or_404, redirect
|
2021-11-28 05:56:21 +00:00
|
|
|
from django.template.response import TemplateResponse
|
2021-01-13 21:36:01 +00:00
|
|
|
from django.views.decorators.http import require_POST
|
|
|
|
|
|
|
|
from bookwyrm import models
|
2022-03-24 20:10:49 +00:00
|
|
|
from bookwyrm.models.relationship import clear_cache
|
2021-11-28 10:38:28 +00:00
|
|
|
from .helpers import (
|
|
|
|
get_user_from_username,
|
|
|
|
handle_remote_webfinger,
|
|
|
|
subscribe_remote_webfinger,
|
2021-12-05 22:29:51 +00:00
|
|
|
WebFingerError,
|
2021-11-28 10:38:28 +00:00
|
|
|
)
|
2021-01-13 21:36:01 +00:00
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
|
2021-01-13 21:36:01 +00:00
|
|
|
@login_required
|
|
|
|
@require_POST
|
|
|
|
def follow(request):
|
2021-04-26 16:15:42 +00:00
|
|
|
"""follow another user, here or abroad"""
|
2021-03-08 16:49:10 +00:00
|
|
|
username = request.POST["user"]
|
2021-04-30 16:33:36 +00:00
|
|
|
to_follow = get_user_from_username(request.user, username)
|
2022-03-24 20:10:49 +00:00
|
|
|
clear_cache(request.user, to_follow)
|
2021-01-13 21:36:01 +00:00
|
|
|
|
2022-03-24 18:25:42 +00:00
|
|
|
follow_request, created = models.UserFollowRequest.objects.get_or_create(
|
|
|
|
user_subject=request.user,
|
|
|
|
user_object=to_follow,
|
|
|
|
)
|
2022-03-24 20:10:49 +00:00
|
|
|
|
2022-03-24 18:25:42 +00:00
|
|
|
if not created:
|
|
|
|
# this request probably failed to connect with the remote
|
|
|
|
# that means we should save to trigger a re-broadcast
|
|
|
|
follow_request.save()
|
2021-11-28 05:56:21 +00:00
|
|
|
|
2021-01-13 21:36:01 +00:00
|
|
|
return redirect(to_follow.local_path)
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_POST
|
|
|
|
def unfollow(request):
|
2021-04-26 16:15:42 +00:00
|
|
|
"""unfollow a user"""
|
2021-03-08 16:49:10 +00:00
|
|
|
username = request.POST["user"]
|
2021-04-30 16:33:36 +00:00
|
|
|
to_unfollow = get_user_from_username(request.user, username)
|
2021-01-13 21:36:01 +00:00
|
|
|
|
2021-03-13 22:55:09 +00:00
|
|
|
try:
|
|
|
|
models.UserFollows.objects.get(
|
|
|
|
user_subject=request.user, user_object=to_unfollow
|
|
|
|
).delete()
|
|
|
|
except models.UserFollows.DoesNotExist:
|
2022-03-24 20:10:49 +00:00
|
|
|
clear_cache(request.user, to_unfollow)
|
2021-03-13 22:55:09 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
models.UserFollowRequest.objects.get(
|
|
|
|
user_subject=request.user, user_object=to_unfollow
|
|
|
|
).delete()
|
|
|
|
except models.UserFollowRequest.DoesNotExist:
|
2022-03-24 20:10:49 +00:00
|
|
|
clear_cache(request.user, to_unfollow)
|
2021-03-13 22:55:09 +00:00
|
|
|
|
|
|
|
# this is handled with ajax so it shouldn't really matter
|
|
|
|
return redirect(request.headers.get("Referer", "/"))
|
2021-01-13 21:36:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_POST
|
|
|
|
def accept_follow_request(request):
|
2021-04-26 16:15:42 +00:00
|
|
|
"""a user accepts a follow request"""
|
2021-03-08 16:49:10 +00:00
|
|
|
username = request.POST["user"]
|
2021-04-30 16:33:36 +00:00
|
|
|
requester = get_user_from_username(request.user, username)
|
2021-01-13 21:36:01 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
follow_request = models.UserFollowRequest.objects.get(
|
2021-03-08 16:49:10 +00:00
|
|
|
user_subject=requester, user_object=request.user
|
2021-01-13 21:36:01 +00:00
|
|
|
)
|
|
|
|
except models.UserFollowRequest.DoesNotExist:
|
|
|
|
# Request already dealt with.
|
|
|
|
return redirect(request.user.local_path)
|
2021-02-07 03:12:49 +00:00
|
|
|
follow_request.accept()
|
2021-01-13 21:36:01 +00:00
|
|
|
|
|
|
|
return redirect(request.user.local_path)
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_POST
|
|
|
|
def delete_follow_request(request):
|
2021-04-26 16:15:42 +00:00
|
|
|
"""a user rejects a follow request"""
|
2021-03-08 16:49:10 +00:00
|
|
|
username = request.POST["user"]
|
2021-04-30 16:33:36 +00:00
|
|
|
requester = get_user_from_username(request.user, username)
|
2021-01-13 21:36:01 +00:00
|
|
|
|
2021-09-27 23:08:52 +00:00
|
|
|
follow_request = get_object_or_404(
|
|
|
|
models.UserFollowRequest, user_subject=requester, user_object=request.user
|
2021-09-27 23:04:40 +00:00
|
|
|
)
|
|
|
|
follow_request.raise_not_deletable(request.user)
|
2021-01-13 21:36:01 +00:00
|
|
|
|
|
|
|
follow_request.delete()
|
2021-09-18 18:32:00 +00:00
|
|
|
return redirect(f"/user/{request.user.localname}")
|
2021-11-28 05:56:21 +00:00
|
|
|
|
2021-11-28 10:38:28 +00:00
|
|
|
|
2021-11-28 05:56:21 +00:00
|
|
|
def ostatus_follow_request(request):
|
|
|
|
"""prepare an outgoing remote follow request"""
|
|
|
|
uri = urllib.parse.unquote(request.GET.get("acct"))
|
2021-11-28 10:38:28 +00:00
|
|
|
username_parts = re.search(
|
2021-11-29 08:45:52 +00:00
|
|
|
r"(?:^http(?:s?):\/\/)([\w\-\.]*)(?:.)*(?:(?:\/)([\w]*))", uri
|
2021-11-28 10:38:28 +00:00
|
|
|
)
|
2021-11-28 05:56:21 +00:00
|
|
|
account = f"{username_parts[2]}@{username_parts[1]}"
|
|
|
|
user = handle_remote_webfinger(account)
|
|
|
|
error = None
|
|
|
|
|
|
|
|
if user is None or user == "":
|
|
|
|
error = "ostatus_subscribe"
|
|
|
|
|
2021-11-29 07:08:25 +00:00
|
|
|
# don't do these checks for AnonymousUser before they sign in
|
2021-12-05 07:09:51 +00:00
|
|
|
if request.user.is_authenticated:
|
2021-11-29 07:08:25 +00:00
|
|
|
|
|
|
|
# you have blocked them so you probably don't want to follow
|
2021-11-29 08:53:13 +00:00
|
|
|
if hasattr(request.user, "blocks") and user in request.user.blocks.all():
|
2021-11-29 07:08:25 +00:00
|
|
|
error = "is_blocked"
|
|
|
|
# they have blocked you
|
2021-11-29 08:53:13 +00:00
|
|
|
if hasattr(user, "blocks") and request.user in user.blocks.all():
|
2021-11-29 07:08:25 +00:00
|
|
|
error = "has_blocked"
|
|
|
|
# you're already following them
|
2021-11-29 08:53:13 +00:00
|
|
|
if hasattr(user, "followers") and request.user in user.followers.all():
|
2021-11-29 07:08:25 +00:00
|
|
|
error = "already_following"
|
|
|
|
# you're not following yet but you already asked
|
|
|
|
if (
|
|
|
|
hasattr(user, "follower_requests")
|
|
|
|
and request.user in user.follower_requests.all()
|
|
|
|
):
|
|
|
|
error = "already_requested"
|
2021-11-28 05:56:21 +00:00
|
|
|
|
2021-11-28 10:38:28 +00:00
|
|
|
data = {"account": account, "user": user, "error": error}
|
2021-11-28 05:56:21 +00:00
|
|
|
|
|
|
|
return TemplateResponse(request, "ostatus/subscribe.html", data)
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
def ostatus_follow_success(request):
|
|
|
|
"""display success message for remote follow"""
|
|
|
|
user = get_user_from_username(request.user, request.GET.get("following"))
|
2021-11-28 10:38:28 +00:00
|
|
|
data = {"account": user.name, "user": user, "error": None}
|
2021-11-28 05:56:21 +00:00
|
|
|
return TemplateResponse(request, "ostatus/success.html", data)
|
|
|
|
|
2021-11-28 10:38:28 +00:00
|
|
|
|
2021-11-28 09:09:29 +00:00
|
|
|
def remote_follow_page(request):
|
2021-12-05 22:29:51 +00:00
|
|
|
"""display remote follow page"""
|
2021-11-28 09:09:29 +00:00
|
|
|
user = get_user_from_username(request.user, request.GET.get("user"))
|
2021-11-28 10:38:28 +00:00
|
|
|
data = {"user": user}
|
2021-11-28 09:09:29 +00:00
|
|
|
return TemplateResponse(request, "ostatus/remote_follow.html", data)
|
2021-11-28 05:56:21 +00:00
|
|
|
|
2021-11-28 10:38:28 +00:00
|
|
|
|
2021-11-28 09:09:29 +00:00
|
|
|
@require_POST
|
|
|
|
def remote_follow(request):
|
|
|
|
"""direct user to follow from remote account using ostatus subscribe protocol"""
|
|
|
|
remote_user = request.POST.get("remote_user")
|
2021-12-05 22:29:51 +00:00
|
|
|
try:
|
|
|
|
if remote_user[0] == "@":
|
|
|
|
remote_user = remote_user[1:]
|
|
|
|
remote_domain = remote_user.split("@")[1]
|
2021-12-06 07:18:12 +00:00
|
|
|
except (TypeError, IndexError):
|
2021-12-05 22:29:51 +00:00
|
|
|
remote_domain = None
|
|
|
|
|
|
|
|
wf_response = subscribe_remote_webfinger(remote_user)
|
2021-11-29 08:53:13 +00:00
|
|
|
user = get_object_or_404(models.User, id=request.POST.get("user"))
|
2021-12-05 22:29:51 +00:00
|
|
|
|
|
|
|
if wf_response is None:
|
|
|
|
data = {
|
|
|
|
"account": remote_user,
|
|
|
|
"user": user,
|
|
|
|
"error": "not_supported",
|
|
|
|
"remote_domain": remote_domain,
|
|
|
|
}
|
|
|
|
return TemplateResponse(request, "ostatus/subscribe.html", data)
|
|
|
|
|
2021-12-06 05:40:18 +00:00
|
|
|
if isinstance(wf_response, WebFingerError):
|
2021-12-05 22:29:51 +00:00
|
|
|
data = {
|
|
|
|
"account": remote_user,
|
|
|
|
"user": user,
|
|
|
|
"error": str(wf_response),
|
|
|
|
"remote_domain": remote_domain,
|
|
|
|
}
|
|
|
|
return TemplateResponse(request, "ostatus/subscribe.html", data)
|
|
|
|
|
|
|
|
url = wf_response.replace("{uri}", urllib.parse.quote(user.remote_id))
|
2021-11-28 09:09:29 +00:00
|
|
|
return redirect(url)
|