Adds commenting
This commit is contained in:
parent
ff5217efd8
commit
9194b3c50d
@ -1,7 +1,7 @@
|
|||||||
''' status serializers '''
|
''' status serializers '''
|
||||||
def get_review(review):
|
def get_review(review):
|
||||||
''' fedireads json for book reviews '''
|
''' fedireads json for book reviews '''
|
||||||
status = get_status_json(review)
|
status = get_status(review)
|
||||||
status['inReplyTo'] = review.book.absolute_id
|
status['inReplyTo'] = review.book.absolute_id
|
||||||
status['fedireadsType'] = review.status_type,
|
status['fedireadsType'] = review.status_type,
|
||||||
status['name'] = review.name
|
status['name'] = review.name
|
||||||
|
@ -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 EditUserForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.User
|
model = models.User
|
||||||
fields = ['avatar', 'name', 'summary']
|
fields = ['avatar', 'name', 'summary']
|
||||||
help_texts = {f: None for f in fields}
|
help_texts = {f: None for f in fields}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ from fedireads import models
|
|||||||
from fedireads import outgoing
|
from fedireads import outgoing
|
||||||
from fedireads.status import create_review, create_status
|
from fedireads.status import create_review, create_status
|
||||||
from fedireads.remote_user import get_or_create_remote_user
|
from fedireads.remote_user import get_or_create_remote_user
|
||||||
|
from fedireads.settings import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@ -133,6 +134,34 @@ def get_status(request, username, status_id):
|
|||||||
return JsonResponse(activitypub.get_status(status))
|
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
|
@csrf_exempt
|
||||||
def get_followers(request, username):
|
def get_followers(request, username):
|
||||||
''' return a list of followers for an actor '''
|
''' return a list of followers for an actor '''
|
||||||
|
@ -4,9 +4,9 @@ from django.views.decorators.csrf import csrf_exempt
|
|||||||
import requests
|
import requests
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
|
from fedireads import activitypub
|
||||||
from fedireads import models
|
from fedireads import models
|
||||||
from fedireads.status import create_review, create_status
|
from fedireads.status import create_review, create_status
|
||||||
from fedireads import activitypub
|
|
||||||
from fedireads.remote_user import get_or_create_remote_user
|
from fedireads.remote_user import get_or_create_remote_user
|
||||||
from fedireads.broadcast import get_recipients, broadcast
|
from fedireads.broadcast import get_recipients, broadcast
|
||||||
|
|
||||||
@ -135,3 +135,14 @@ def handle_review(user, book, name, content, rating):
|
|||||||
recipients = get_recipients(user, 'public')
|
recipients = get_recipients(user, 'public')
|
||||||
broadcast(user, create_activity, recipients)
|
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)
|
||||||
|
|
||||||
|
@ -9,10 +9,7 @@ def create_review(user, possible_book, name, content, rating):
|
|||||||
# throws a value error if the book is not found
|
# throws a value error if the book is not found
|
||||||
book = get_or_create_book(possible_book)
|
book = get_or_create_book(possible_book)
|
||||||
|
|
||||||
# sanitize review html
|
content = sanitize(content)
|
||||||
parser = InputHtmlParser()
|
|
||||||
parser.feed(content)
|
|
||||||
content = parser.get_output()
|
|
||||||
|
|
||||||
# no ratings outside of 0-5
|
# no ratings outside of 0-5
|
||||||
rating = rating if 0 <= rating <= 5 else 0
|
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,
|
reply_parent=reply_parent,
|
||||||
)
|
)
|
||||||
|
|
||||||
for book in mention_books:
|
if mention_books:
|
||||||
status.mention_books.add(book)
|
for book in mention_books:
|
||||||
|
status.mention_books.add(book)
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize(content):
|
||||||
|
''' remove invalid html from free text '''
|
||||||
|
parser = InputHtmlParser()
|
||||||
|
parser.feed(content)
|
||||||
|
return parser.get_output()
|
||||||
|
@ -66,7 +66,15 @@
|
|||||||
<p>{{ activity.rating | stars }}</p>
|
<p>{{ activity.rating | stars }}</p>
|
||||||
<p>{{ activity.content | safe }}</p>
|
<p>{{ activity.content | safe }}</p>
|
||||||
</div>
|
</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' %}
|
{% elif activity.status_type == 'Note' %}
|
||||||
posted</h2>
|
posted</h2>
|
||||||
{{ activity.content | safe }}
|
{{ activity.content | safe }}
|
||||||
|
@ -24,7 +24,10 @@ urlpatterns = [
|
|||||||
r'^user/(?P<username>\w+)/(status|review)/(?P<status_id>\d+)/activity/?$',
|
r'^user/(?P<username>\w+)/(status|review)/(?P<status_id>\d+)/activity/?$',
|
||||||
incoming.get_status
|
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
|
# TODO: shelves need pages in the UI and for their activitypub Collection
|
||||||
|
|
||||||
# .well-known endpoints
|
# .well-known endpoints
|
||||||
@ -47,6 +50,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# internal action endpoints
|
# internal action endpoints
|
||||||
re_path(r'^review/?$', views.review),
|
re_path(r'^review/?$', views.review),
|
||||||
|
re_path(r'^comment/?$', views.comment),
|
||||||
re_path(
|
re_path(
|
||||||
r'^shelve/(?P<username>\w+)/(?P<shelf_id>[\w-]+)/(?P<book_id>\d+)/?$',
|
r'^shelve/(?P<username>\w+)/(?P<shelf_id>[\w-]+)/(?P<book_id>\d+)/?$',
|
||||||
views.shelve
|
views.shelve
|
||||||
|
@ -43,6 +43,7 @@ def home(request):
|
|||||||
'-created_date'
|
'-created_date'
|
||||||
)[:10]
|
)[:10]
|
||||||
|
|
||||||
|
comment_form = forms.CommentForm()
|
||||||
data = {
|
data = {
|
||||||
'user': request.user,
|
'user': request.user,
|
||||||
'reading': reading,
|
'reading': reading,
|
||||||
@ -50,6 +51,7 @@ def home(request):
|
|||||||
'recent_books': recent_books,
|
'recent_books': recent_books,
|
||||||
'user_books': user_books,
|
'user_books': user_books,
|
||||||
'activities': activities,
|
'activities': activities,
|
||||||
|
'comment_form': comment_form,
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, 'feed.html', data)
|
return TemplateResponse(request, 'feed.html', data)
|
||||||
|
|
||||||
@ -250,6 +252,18 @@ def review(request):
|
|||||||
return redirect('/book/%s' % book_identifier)
|
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
|
@login_required
|
||||||
def follow(request):
|
def follow(request):
|
||||||
''' follow another user, here or abroad '''
|
''' follow another user, here or abroad '''
|
||||||
|
Loading…
x
Reference in New Issue
Block a user