forked from mirrors/bookwyrm
Delete statuses
This commit is contained in:
parent
1705a550d4
commit
704e1092c4
8 changed files with 71 additions and 2 deletions
|
@ -4,6 +4,7 @@ import sys
|
|||
|
||||
from .base_activity import ActivityEncoder, Image, PublicKey, Signature
|
||||
from .note import Note, GeneratedNote, Article, Comment, Review, Quotation
|
||||
from .note import Tombstone
|
||||
from .interaction import Boost, Like
|
||||
from .ordered_collection import OrderedCollection, OrderedCollectionPage
|
||||
from .person import Person
|
||||
|
|
|
@ -4,6 +4,14 @@ from typing import Dict, List
|
|||
|
||||
from .base_activity import ActivityObject, Image
|
||||
|
||||
@dataclass(init=False)
|
||||
class Tombstone(ActivityObject):
|
||||
url: str
|
||||
published: str
|
||||
deleted: str
|
||||
type: str = 'Tombstone'
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class Note(ActivityObject):
|
||||
''' Note activity '''
|
||||
|
|
|
@ -22,6 +22,8 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
sensitive = models.BooleanField(default=False)
|
||||
# the created date can't be this, because of receiving federated posts
|
||||
published_date = models.DateTimeField(default=timezone.now)
|
||||
deleted = models.BooleanField(default=False)
|
||||
deleted_date = models.DateTimeField(default=timezone.now)
|
||||
favorites = models.ManyToManyField(
|
||||
'User',
|
||||
symmetrical=False,
|
||||
|
@ -104,6 +106,18 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
**kwargs
|
||||
)
|
||||
|
||||
def to_activity(self, **kwargs):
|
||||
''' return tombstone if the status is deleted '''
|
||||
if self.deleted:
|
||||
return activitypub.Tombstone(
|
||||
id=self.remote_id,
|
||||
url=self.remote_id,
|
||||
deleted=http_date(self.deleted_date.timestamp()),
|
||||
published=http_date(self.deleted_date.timestamp()),
|
||||
).serialize()
|
||||
return ActivitypubMixin.to_activity(self, **kwargs)
|
||||
|
||||
|
||||
class GeneratedStatus(Status):
|
||||
''' these are app-generated messages about user activity '''
|
||||
@property
|
||||
|
@ -112,7 +126,7 @@ class GeneratedStatus(Status):
|
|||
message = self.content
|
||||
books = ', '.join(
|
||||
'<a href="%s">"%s"</a>' % (self.book.local_id, self.book.title) \
|
||||
for book in self.mention_books
|
||||
for book in self.mention_books.all()
|
||||
)
|
||||
return '%s %s' % (message, books)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ from bookwyrm.status import create_review, create_status
|
|||
from bookwyrm.status import create_quotation, create_comment
|
||||
from bookwyrm.status import create_tag, create_notification, create_rating
|
||||
from bookwyrm.status import create_generated_note
|
||||
from bookwyrm.status import delete_status
|
||||
from bookwyrm.remote_user import get_or_create_remote_user
|
||||
|
||||
|
||||
|
@ -197,6 +198,12 @@ def handle_import_books(user, items):
|
|||
return None
|
||||
|
||||
|
||||
def handle_delete_status(user, status):
|
||||
''' delete a status and broadcast deletion to other servers '''
|
||||
delete_status(status)
|
||||
broadcast(user, status.to_activity())
|
||||
|
||||
|
||||
def handle_rate(user, book, rating):
|
||||
''' a review that's just a rating '''
|
||||
builder = create_rating
|
||||
|
|
|
@ -6,6 +6,11 @@ from bookwyrm.books_manager import get_or_create_book
|
|||
from bookwyrm.sanitize_html import InputHtmlParser
|
||||
|
||||
|
||||
def delete_status(status):
|
||||
''' replace the status with a tombstone '''
|
||||
status.deleted = True
|
||||
status.save()
|
||||
|
||||
def create_rating(user, book, rating):
|
||||
''' a review that's just a rating '''
|
||||
if not rating or rating < 1 or rating > 5:
|
||||
|
|
|
@ -25,6 +25,17 @@
|
|||
<span class="icon icon-public">
|
||||
<span class="is-sr-only">Public post</span>
|
||||
</span>
|
||||
{% if status.user == request.user %}
|
||||
<form name="delete-{{status.id}}" action="/delete-status" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="status" value="{{ status.id }}">
|
||||
<button type="submit">
|
||||
<span class="icon icon-cancel">
|
||||
<span class="is-sr-only">Delete post</span>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<a href="{{ status.remote_id }}">{{ status.published_date | naturaltime }}</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
@ -11,7 +11,7 @@ localname_regex = r'(?P<username>[\w\-_]+)'
|
|||
user_path = r'^user/%s' % username_regex
|
||||
local_user_path = r'^user/%s' % localname_regex
|
||||
|
||||
status_types = ['status', 'review', 'comment', 'quotation', 'boost']
|
||||
status_types = ['status', 'review', 'comment', 'quotation', 'boost', 'generatedstatus']
|
||||
status_path = r'%s/(%s)/(?P<status_id>\d+)' % \
|
||||
(local_user_path, '|'.join(status_types))
|
||||
|
||||
|
@ -107,6 +107,8 @@ urlpatterns = [
|
|||
re_path(r'^unfavorite/(?P<status_id>\d+)/?$', actions.unfavorite),
|
||||
re_path(r'^boost/(?P<status_id>\d+)/?$', actions.boost),
|
||||
|
||||
re_path(r'^delete-status/?$', actions.delete_status),
|
||||
|
||||
re_path(r'^shelve/?$', actions.shelve),
|
||||
|
||||
re_path(r'^follow/?$', actions.follow),
|
||||
|
|
|
@ -418,6 +418,27 @@ def boost(request, status_id):
|
|||
outgoing.handle_boost(request.user, status)
|
||||
return redirect(request.headers.get('Referer', '/'))
|
||||
|
||||
|
||||
@login_required
|
||||
def delete_status(request):
|
||||
''' delete and tombstone a status '''
|
||||
status_id = request.POST.get('status')
|
||||
if not status_id:
|
||||
return HttpResponseBadRequest()
|
||||
try:
|
||||
status = models.Status.objects.get(id=status_id)
|
||||
except models.Status.DoesNotExist:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
# don't let people delete other people's statuses
|
||||
if status.user != request.user:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
# perform deletion
|
||||
outgoing.handle_delete_status(request.user, status)
|
||||
return redirect(request.headers.get('Referer', '/'))
|
||||
|
||||
|
||||
@login_required
|
||||
def follow(request):
|
||||
''' follow another user, here or abroad '''
|
||||
|
|
Loading…
Reference in a new issue