Unfavorite statuses

This commit is contained in:
Mouse Reeve 2020-03-21 15:21:27 -07:00
parent e0bd8200ad
commit 7455467c40
10 changed files with 143 additions and 19 deletions

View file

@ -5,4 +5,4 @@ from .collection import get_outbox, get_outbox_page, get_add, get_remove, \
from .create import get_create
from .follow import get_follow_request, get_unfollow, get_accept, get_reject
from .status import get_review, get_review_article, get_status, get_replies, \
get_favorite, get_add_tag, get_remove_tag, get_replies_page
get_favorite, get_unfavorite, get_add_tag, get_remove_tag, get_replies_page

View file

@ -77,6 +77,7 @@ def get_replies(status, replies):
def get_replies_page(status, replies):
''' actual reply list content '''
id_slug = status.absolute_id + '/replies?page=true&only_other_accounts=true'
items = []
for reply in replies:
@ -105,6 +106,22 @@ def get_favorite(favorite):
}
def get_unfavorite(favorite):
''' like a post '''
return {
'@context': 'https://www.w3.org/ns/activitystreams',
'id': '%s/undo' % favorite.absolute_id,
'type': 'Undo',
'actor': favorite.user.actor,
'object': {
'id': favorite.absolute_id,
'type': 'Like',
'actor': favorite.user.actor,
'object': favorite.status.absolute_id,
}
}
def get_add_tag(tag):
''' add activity for tagging a book '''
uuid = uuid4()

View file

@ -12,8 +12,7 @@ import requests
from fedireads import models
from fedireads import outgoing
from fedireads.status import create_review_from_activity, \
create_status_from_activity, create_tag, create_notification
from fedireads import status as status_builder
from fedireads.remote_user import get_or_create_remote_user
@ -39,7 +38,14 @@ def shared_inbox(request):
response = handle_incoming_follow(activity)
elif activity['type'] == 'Undo':
response = handle_incoming_undo(activity)
if not 'object' in activity:
return HttpResponseNotFound()
if activity['object']['type'] == 'Follow':
response = handle_incoming_undo(activity)
elif activity['object']['type'] == 'Like':
response = handle_incoming_unfavorite(activity)
else:
return HttpResponseNotFound()
elif activity['type'] == 'Create':
response = handle_incoming_create(activity)
@ -141,10 +147,18 @@ def handle_incoming_follow(activity):
return HttpResponse()
if not to_follow.manually_approves_followers:
create_notification(to_follow, 'FOLLOW', related_user=user)
status_builder.create_notification(
to_follow,
'FOLLOW',
related_user=user
)
outgoing.handle_outgoing_accept(user, to_follow, request)
else:
create_notification(to_follow, 'FOLLOW_REQUEST', related_user=user)
status_builder.create_notification(
to_follow,
'FOLLOW_REQUEST',
related_user=user
)
return HttpResponse()
@ -216,14 +230,20 @@ def handle_incoming_create(activity):
models.Review.objects.get(id=review_id)
else:
try:
create_review_from_activity(user, activity['object'])
status_builder.create_review_from_activity(
user,
activity['object']
)
except ValueError:
return HttpResponseBadRequest()
elif not user.local:
try:
status = create_status_from_activity(user, activity['object'])
status = status_builder.create_status_from_activity(
user,
activity['object']
)
if status and status.reply_parent:
create_notification(
status_builder.create_notification(
status.reply_parent.user,
'REPLY',
related_user=status.user,
@ -245,9 +265,9 @@ def handle_incoming_favorite(activity):
return HttpResponseNotFound()
if not liker.local:
status.favorites.add(liker)
status_builder.create_favorite_from_activity(liker, activity)
create_notification(
status_builder.create_notification(
status.user,
'FAVORITE',
related_user=liker,
@ -256,13 +276,26 @@ def handle_incoming_favorite(activity):
return HttpResponse()
def handle_incoming_unfavorite(activity):
''' approval of your good good post '''
try:
favorite_id = activity['object']['id']
fav = status_builder.get_favorite(favorite_id)
except models.Favorite.DoesNotExist:
return HttpResponseNotFound()
fav.delete()
return HttpResponse()
def handle_incoming_add(activity):
''' someone is tagging or shelving a book '''
if activity['object']['type'] == 'Tag':
user = get_or_create_remote_user(activity['actor'])
if not user.local:
book = activity['target']['id'].split('/')[-1]
create_tag(user, book, activity['object']['name'])
status_builder.create_tag(user, book, activity['object']['name'])
return HttpResponse()
return HttpResponse()
return HttpResponseNotFound()

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-03-21 21:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('fedireads', '0017_auto_20200314_2152'),
]
operations = [
migrations.AddField(
model_name='favorite',
name='remote_id',
field=models.CharField(max_length=255, null=True, unique=True),
),
]

View file

@ -65,6 +65,14 @@ class Favorite(FedireadsModel):
''' fav'ing a post '''
user = models.ForeignKey('User', on_delete=models.PROTECT)
status = models.ForeignKey('Status', on_delete=models.PROTECT)
remote_id = models.CharField(max_length=255, unique=True, null=True)
@property
def absolute_id(self):
''' constructs the absolute reference to any db object '''
if self.remote_id:
return self.remote_id
return super().absolute_id
class Meta:
unique_together = ('user', 'status')

View file

@ -228,3 +228,19 @@ def handle_outgoing_favorite(user, status):
recipients = get_recipients(user, 'direct', [status.user])
broadcast(user, fav_activity, recipients)
def handle_outgoing_unfavorite(user, status):
''' a user likes a status '''
try:
favorite = models.Favorite.objects.get(
status=status,
user=user
)
except models.Favorite.DoesNotExist:
# can't find that status, idk
return
fav_activity = activitypub.get_unfavorite(favorite)
recipients = get_recipients(user, 'direct', [status.user])
broadcast(user, fav_activity, recipients)

View file

@ -57,20 +57,44 @@ def create_status_from_activity(author, activity):
return status
def create_favorite_from_activity(user, activity):
status = get_status(activity['object'])
remote_id = activity['id']
try:
return models.Favorite.objects.create(
status=status,
user=user,
remote_id=remote_id,
)
except IntegrityError:
return models.Favorite.objects.get(status=status, user=user)
def get_status(absolute_id):
''' find a status in the database '''
return get_by_absolute_id(absolute_id, models.Status)
def get_favorite(absolute_id):
''' find a status in the database '''
return get_by_absolute_id(absolute_id, models.Favorite)
def get_by_absolute_id(absolute_id, model):
# check if it's a remote status
try:
return models.Status.objects.get(remote_id=absolute_id)
except models.Status.DoesNotExist:
return model.objects.get(remote_id=absolute_id)
except model.DoesNotExist:
pass
# try finding a local status with that id
local_id = absolute_id.split('/')[-1]
try:
possible_match = models.Status.objects.select_subclasses() \
.get(id=local_id)
except models.Status.DoesNotExist:
if hasattr(model.objects, 'select_subclasses'):
possible_match = model.objects.select_subclasses().get(id=local_id)
else:
possible_match = model.objects.get(id=local_id)
except model.DoesNotExist:
return None
# make sure it's not actually a remote status with an id that
@ -80,7 +104,6 @@ def get_status(absolute_id):
return None
def create_status(user, content, reply_parent=None, mention_books=None,
remote_id=None):
''' a status update '''

View file

@ -37,7 +37,7 @@
</span>
</button>
</form>
<form name="favorite" action="/favorite/{{ activity.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }} active {% if not request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}">
<form name="unfavorite" action="/unfavorite/{{ activity.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }} active {% if not request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}">
{% csrf_token %}
<button type="submit">
<span class="icon icon-heart">

View file

@ -69,6 +69,7 @@ urlpatterns = [
re_path(r'^untag/?$', actions.untag),
re_path(r'^comment/?$', actions.comment),
re_path(r'^favorite/(?P<status_id>\d+)/?$', actions.favorite),
re_path(r'^unfavorite/(?P<status_id>\d+)/?$', actions.unfavorite),
re_path(r'^shelve/?$', actions.shelve),
re_path(r'^follow/?$', actions.follow),
re_path(r'^unfollow/?$', actions.unfollow),

View file

@ -159,6 +159,14 @@ def favorite(request, status_id):
return redirect(request.headers.get('Referer', '/'))
@login_required
def unfavorite(request, status_id):
''' like a status '''
status = models.Status.objects.get(id=status_id)
outgoing.handle_outgoing_unfavorite(request.user, status)
return redirect(request.headers.get('Referer', '/'))
@login_required
def follow(request):
''' follow another user, here or abroad '''