Adds commenting

This commit is contained in:
Mouse Reeve 2020-02-17 21:39:08 -08:00
parent ff5217efd8
commit 9194b3c50d
8 changed files with 89 additions and 10 deletions

View file

@ -1,7 +1,7 @@
''' status serializers '''
def get_review(review):
''' fedireads json for book reviews '''
status = get_status_json(review)
status = get_status(review)
status['inReplyTo'] = review.book.absolute_id
status['fedireadsType'] = review.status_type,
status['name'] = review.name

View file

@ -40,8 +40,17 @@ class ReviewForm(ModelForm):
}
class CommentForm(ModelForm):
class Meta:
model = models.Status
fields = ['content']
help_texts = {f: None for f in fields}
labels = {'content': 'Comment'}
class EditUserForm(ModelForm):
class Meta:
model = models.User
fields = ['avatar', 'name', 'summary']
help_texts = {f: None for f in fields}

View file

@ -14,6 +14,7 @@ from fedireads import models
from fedireads import outgoing
from fedireads.status import create_review, create_status
from fedireads.remote_user import get_or_create_remote_user
from fedireads.settings import DOMAIN
@csrf_exempt
@ -133,6 +134,34 @@ def get_status(request, username, status_id):
return JsonResponse(activitypub.get_status(status))
@csrf_exempt
def get_replies(request, username, status_id):
''' ordered collection of replies to a status '''
if request.method != 'GET':
return HttpResponseBadRequest()
replies = models.Status.objects.filter(
reply_parent=status_id
).first()
path_id = 'https://%s/user/%s/status/%s/replies' % \
(DOMAIN, username, status_id)
replies_activity = {
'@context': 'https://www.w3.org/ns/activitystreams',
'id': path_id,
'type': 'Collection',
'first': {
'id': '%s?page=true' % path_id,
'type': 'CollectionPage',
'next': '%s?only_other_accounts=true&page=true' % path_id,
'partOf': path_id,
'items': [replies.activity]
}
}
return JsonResponse(replies_activity)
@csrf_exempt
def get_followers(request, username):
''' return a list of followers for an actor '''

View file

@ -4,9 +4,9 @@ from django.views.decorators.csrf import csrf_exempt
import requests
from urllib.parse import urlencode
from fedireads import activitypub
from fedireads import models
from fedireads.status import create_review, create_status
from fedireads import activitypub
from fedireads.remote_user import get_or_create_remote_user
from fedireads.broadcast import get_recipients, broadcast
@ -135,3 +135,14 @@ def handle_review(user, book, name, content, rating):
recipients = get_recipients(user, 'public')
broadcast(user, create_activity, recipients)
def handle_comment(user, review, content):
''' post a review '''
# validated and saves the comment in the database so it has an id
comment = create_status(user, content, reply_parent=review)
comment_activity = activitypub.get_status(comment)
create_activity = activitypub.get_create(user, comment_activity)
recipients = get_recipients(user, 'public')
broadcast(user, create_activity, recipients)

View file

@ -9,10 +9,7 @@ def create_review(user, possible_book, name, content, rating):
# throws a value error if the book is not found
book = get_or_create_book(possible_book)
# sanitize review html
parser = InputHtmlParser()
parser.feed(content)
content = parser.get_output()
content = sanitize(content)
# no ratings outside of 0-5
rating = rating if 0 <= rating <= 5 else 0
@ -41,8 +38,15 @@ def create_status(user, content, reply_parent=None, mention_books=None):
reply_parent=reply_parent,
)
if mention_books:
for book in mention_books:
status.mention_books.add(book)
return status
def sanitize(content):
''' remove invalid html from free text '''
parser = InputHtmlParser()
parser.feed(content)
return parser.get_output()

View file

@ -66,7 +66,15 @@
<p>{{ activity.rating | stars }}</p>
<p>{{ activity.content | safe }}</p>
</div>
<div class="interaction"><button>⭐️ Like</button></div>
<div class="interaction">
<button>⭐️ Like</button>
<form name="comment" action="/comment" method="post">
{% csrf_token %}
<input type="hidden" name="review" value="{{ activity.id }}"></input>
{{ comment_form.content }}
<button type="submit">Comment</button>
</form>
</div>
{% elif activity.status_type == 'Note' %}
posted</h2>
{{ activity.content | safe }}

View file

@ -24,7 +24,10 @@ urlpatterns = [
r'^user/(?P<username>\w+)/(status|review)/(?P<status_id>\d+)/activity/?$',
incoming.get_status
),
re_path(r'^user/(?P<username>\w+)/(status|review)/?$', incoming.get_following),
re_path(
r'^user/(?P<username>\w+)/(status|review)/(?P<status_id>\d+)/replies/?$',
incoming.get_replies
),
# TODO: shelves need pages in the UI and for their activitypub Collection
# .well-known endpoints
@ -47,6 +50,7 @@ urlpatterns = [
# internal action endpoints
re_path(r'^review/?$', views.review),
re_path(r'^comment/?$', views.comment),
re_path(
r'^shelve/(?P<username>\w+)/(?P<shelf_id>[\w-]+)/(?P<book_id>\d+)/?$',
views.shelve

View file

@ -43,6 +43,7 @@ def home(request):
'-created_date'
)[:10]
comment_form = forms.CommentForm()
data = {
'user': request.user,
'reading': reading,
@ -50,6 +51,7 @@ def home(request):
'recent_books': recent_books,
'user_books': user_books,
'activities': activities,
'comment_form': comment_form,
}
return TemplateResponse(request, 'feed.html', data)
@ -250,6 +252,18 @@ def review(request):
return redirect('/book/%s' % book_identifier)
def comment(request):
''' respond to a book review '''
form = forms.CommentForm(request.POST)
# this is a bit of a formality, the form is just one text field
if not form.is_valid():
return redirect('/')
review_id = request.POST['review']
parent = models.Review.objects.get(id=review_id)
outgoing.handle_comment(request.user, parent, form.data['content'])
return redirect('/')
@login_required
def follow(request):
''' follow another user, here or abroad '''