Removes outgoing and view_actions

This commit is contained in:
Mouse Reeve 2021-01-13 13:36:01 -08:00
parent a385aa4cb5
commit 3e5ed19643
8 changed files with 199 additions and 169 deletions

View file

@ -2,10 +2,11 @@
import csv
import logging
from bookwyrm import outgoing
from bookwyrm.tasks import app
from bookwyrm import models
from bookwyrm.broadcast import broadcast
from bookwyrm.models import ImportJob, ImportItem
from bookwyrm.status import create_notification
from bookwyrm.tasks import app
logger = logging.getLogger(__name__)
@ -62,7 +63,7 @@ def import_data(job_id):
item.save()
# shelves book and handles reviews
outgoing.handle_imported_book(
handle_imported_book(
job.user, item, job.include_reviews, job.privacy)
else:
item.fail_reason = 'Could not find a match for book'
@ -71,3 +72,57 @@ def import_data(job_id):
create_notification(job.user, 'IMPORT', related_import=job)
job.complete = True
job.save()
def handle_imported_book(user, item, include_reviews, privacy):
''' process a goodreads csv and then post about it '''
if isinstance(item.book, models.Work):
item.book = item.book.default_edition
if not item.book:
return
existing_shelf = models.ShelfBook.objects.filter(
book=item.book, added_by=user).exists()
# shelve the book if it hasn't been shelved already
if item.shelf and not existing_shelf:
desired_shelf = models.Shelf.objects.get(
identifier=item.shelf,
user=user
)
shelf_book = models.ShelfBook.objects.create(
book=item.book, shelf=desired_shelf, added_by=user)
broadcast(user, shelf_book.to_add_activity(user), privacy=privacy)
for read in item.reads:
# check for an existing readthrough with the same dates
if models.ReadThrough.objects.filter(
user=user, book=item.book,
start_date=read.start_date,
finish_date=read.finish_date
).exists():
continue
read.book = item.book
read.user = user
read.save()
if include_reviews and (item.rating or item.review):
review_title = 'Review of {!r} on Goodreads'.format(
item.book.title,
) if item.review else ''
# we don't know the publication date of the review,
# but "now" is a bad guess
published_date_guess = item.date_read or item.date_added
review = models.Review.objects.create(
user=user,
book=item.book,
name=review_title,
content=item.review,
rating=item.rating,
published_date=published_date_guess,
privacy=privacy,
)
# we don't need to send out pure activities because non-bookwyrm
# instances don't need this data
broadcast(user, review.to_create_activity(user), privacy=privacy)

View file

@ -9,7 +9,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
import requests
from bookwyrm import activitypub, models, outgoing
from bookwyrm import activitypub, models, views
from bookwyrm import status as status_builder
from bookwyrm.tasks import app
from bookwyrm.signatures import Signature
@ -133,7 +133,7 @@ def handle_follow(activity):
related_user=relationship.user_subject
)
if not manually_approves:
outgoing.handle_accept(relationship)
views.handle_accept(relationship)
@app.task

View file

@ -1,161 +0,0 @@
''' handles all the activity coming out of the server '''
from django.db import transaction
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_GET
from requests import HTTPError
from bookwyrm import activitypub
from bookwyrm import models
from bookwyrm.connectors import get_data, ConnectorException
from bookwyrm.broadcast import broadcast
@csrf_exempt
@require_GET
def outbox(request, username):
''' outbox for the requested user '''
user = get_object_or_404(models.User, localname=username)
filter_type = request.GET.get('type')
if filter_type not in models.status_models:
filter_type = None
return JsonResponse(
user.to_outbox(**request.GET, filter_type=filter_type),
encoder=activitypub.ActivityEncoder
)
def handle_remote_webfinger(query):
''' webfingerin' other servers '''
user = None
# usernames could be @user@domain or user@domain
if not query:
return None
if query[0] == '@':
query = query[1:]
try:
domain = query.split('@')[1]
except IndexError:
return None
try:
user = models.User.objects.get(username=query)
except models.User.DoesNotExist:
url = 'https://%s/.well-known/webfinger?resource=acct:%s' % \
(domain, query)
try:
data = get_data(url)
except (ConnectorException, HTTPError):
return None
for link in data.get('links'):
if link.get('rel') == 'self':
try:
user = activitypub.resolve_remote_id(
models.User, link['href']
)
except KeyError:
return None
return user
def handle_follow(user, to_follow):
''' someone local wants to follow someone '''
relationship, _ = models.UserFollowRequest.objects.get_or_create(
user_subject=user,
user_object=to_follow,
)
activity = relationship.to_activity()
broadcast(user, activity, privacy='direct', direct_recipients=[to_follow])
def handle_unfollow(user, to_unfollow):
''' someone local wants to follow someone '''
relationship = models.UserFollows.objects.get(
user_subject=user,
user_object=to_unfollow
)
activity = relationship.to_undo_activity(user)
broadcast(user, activity, privacy='direct', direct_recipients=[to_unfollow])
to_unfollow.followers.remove(user)
def handle_accept(follow_request):
''' send an acceptance message to a follow request '''
user = follow_request.user_subject
to_follow = follow_request.user_object
with transaction.atomic():
relationship = models.UserFollows.from_request(follow_request)
follow_request.delete()
relationship.save()
activity = relationship.to_accept_activity()
broadcast(to_follow, activity, privacy='direct', direct_recipients=[user])
def handle_reject(follow_request):
''' a local user who managed follows rejects a follow request '''
user = follow_request.user_subject
to_follow = follow_request.user_object
activity = follow_request.to_reject_activity()
follow_request.delete()
broadcast(to_follow, activity, privacy='direct', direct_recipients=[user])
def handle_imported_book(user, item, include_reviews, privacy):
''' process a goodreads csv and then post about it '''
if isinstance(item.book, models.Work):
item.book = item.book.default_edition
if not item.book:
return
existing_shelf = models.ShelfBook.objects.filter(
book=item.book, added_by=user).exists()
# shelve the book if it hasn't been shelved already
if item.shelf and not existing_shelf:
desired_shelf = models.Shelf.objects.get(
identifier=item.shelf,
user=user
)
shelf_book = models.ShelfBook.objects.create(
book=item.book, shelf=desired_shelf, added_by=user)
broadcast(user, shelf_book.to_add_activity(user), privacy=privacy)
for read in item.reads:
# check for an existing readthrough with the same dates
if models.ReadThrough.objects.filter(
user=user, book=item.book,
start_date=read.start_date,
finish_date=read.finish_date
).exists():
continue
read.book = item.book
read.user = user
read.save()
if include_reviews and (item.rating or item.review):
review_title = 'Review of {!r} on Goodreads'.format(
item.book.title,
) if item.review else ''
# we don't know the publication date of the review,
# but "now" is a bad guess
published_date_guess = item.date_read or item.date_added
review = models.Review.objects.create(
user=user,
book=item.book,
name=review_title,
content=item.review,
rating=item.rating,
published_date=published_date_guess,
privacy=privacy,
)
# we don't need to send out pure activities because non-bookwyrm
# instances don't need this data
broadcast(user, review.to_create_activity(user), privacy=privacy)

View file

@ -3,7 +3,7 @@ from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, re_path
from bookwyrm import incoming, outgoing, settings, views, wellknown
from bookwyrm import incoming, settings, views, wellknown
from bookwyrm.utils import regex
user_path = r'^user/(?P<username>%s)' % regex.username
@ -30,7 +30,7 @@ urlpatterns = [
# federation endpoints
re_path(r'^inbox/?$', incoming.shared_inbox),
re_path(r'%s/inbox/?$' % local_user_path, incoming.inbox),
re_path(r'%s/outbox/?$' % local_user_path, outgoing.outbox),
re_path(r'%s/outbox/?$' % local_user_path, views.Outbox.as_view()),
# .well-known endpoints
re_path(r'^.well-known/webfinger/?$', wellknown.webfinger),

View file

@ -6,12 +6,13 @@ from .books import upload_cover, add_description, switch_edition, resolve_book
from .direct_message import DirectMessage
from .error import not_found_page, server_error_page
from .follow import follow, unfollow
from .follow import accept_follow_request, delete_follow_request
from .follow import accept_follow_request, delete_follow_request, handle_accept
from .import_data import Import, ImportStatus
from .interaction import Favorite, Unfavorite, Boost, Unboost
from .invite import ManageInvites, Invite
from .landing import About, Home, Feed, Discover
from .notifications import Notifications
from .outbox import Outbox
from .reading import edit_readthrough, create_readthrough, delete_readthrough
from .reading import start_reading, finish_reading
from .password import PasswordResetRequest, PasswordReset, ChangePassword

113
bookwyrm/views/follow.py Normal file
View file

@ -0,0 +1,113 @@
''' views for actions you can take in the application '''
from django.db import transaction
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect
from django.views.decorators.http import require_POST
from bookwyrm import models
from bookwyrm.broadcast import broadcast
from .helpers import get_user_from_username
@login_required
@require_POST
def follow(request):
''' follow another user, here or abroad '''
username = request.POST['user']
try:
to_follow = get_user_from_username(username)
except models.User.DoesNotExist:
return HttpResponseBadRequest()
relationship, _ = models.UserFollowRequest.objects.get_or_create(
user_subject=request.user,
user_object=to_follow,
)
activity = relationship.to_activity()
broadcast(
request.user, activity, privacy='direct', direct_recipients=[to_follow])
return redirect(to_follow.local_path)
@login_required
@require_POST
def unfollow(request):
''' unfollow a user '''
username = request.POST['user']
try:
to_unfollow = get_user_from_username(username)
except models.User.DoesNotExist:
return HttpResponseBadRequest()
relationship = models.UserFollows.objects.get(
user_subject=request.user,
user_object=to_unfollow
)
activity = relationship.to_undo_activity(request.user)
broadcast(
request.user, activity,
privacy='direct', direct_recipients=[to_unfollow])
to_unfollow.followers.remove(request.user)
return redirect(to_unfollow.local_path)
@login_required
@require_POST
def accept_follow_request(request):
''' a user accepts a follow request '''
username = request.POST['user']
try:
requester = get_user_from_username(username)
except models.User.DoesNotExist:
return HttpResponseBadRequest()
try:
follow_request = models.UserFollowRequest.objects.get(
user_subject=requester,
user_object=request.user
)
except models.UserFollowRequest.DoesNotExist:
# Request already dealt with.
return redirect(request.user.local_path)
handle_accept(follow_request)
return redirect(request.user.local_path)
def handle_accept(follow_request):
''' send an acceptance message to a follow request '''
user = follow_request.user_subject
to_follow = follow_request.user_object
with transaction.atomic():
relationship = models.UserFollows.from_request(follow_request)
follow_request.delete()
relationship.save()
activity = relationship.to_accept_activity()
broadcast(to_follow, activity, privacy='direct', direct_recipients=[user])
@login_required
@require_POST
def delete_follow_request(request):
''' a user rejects a follow request '''
username = request.POST['user']
try:
requester = get_user_from_username(username)
except models.User.DoesNotExist:
return HttpResponseBadRequest()
try:
follow_request = models.UserFollowRequest.objects.get(
user_subject=requester,
user_object=request.user
)
except models.UserFollowRequest.DoesNotExist:
return HttpResponseBadRequest()
activity = follow_request.to_reject_activity()
follow_request.delete()
broadcast(
request.user, activity, privacy='direct', direct_recipients=[requester])
return redirect('/user/%s' % request.user.localname)

22
bookwyrm/views/outbox.py Normal file
View file

@ -0,0 +1,22 @@
''' the good stuff! the books! '''
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from django.views import View
from bookwyrm import activitypub, models
# pylint: disable= no-self-use
class Outbox(View):
''' outbox '''
def get(self, request, username):
''' outbox for the requested user '''
user = get_object_or_404(models.User, localname=username)
filter_type = request.GET.get('type')
if filter_type not in models.status_models:
filter_type = None
return JsonResponse(
user.to_outbox(**request.GET, filter_type=filter_type),
encoder=activitypub.ActivityEncoder
)