mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-15 21:31:26 +00:00
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 .base_activity import ActivityEncoder, Image, PublicKey, Signature
|
||||||
from .note import Note, GeneratedNote, Article, Comment, Review, Quotation
|
from .note import Note, GeneratedNote, Article, Comment, Review, Quotation
|
||||||
|
from .note import Tombstone
|
||||||
from .interaction import Boost, Like
|
from .interaction import Boost, Like
|
||||||
from .ordered_collection import OrderedCollection, OrderedCollectionPage
|
from .ordered_collection import OrderedCollection, OrderedCollectionPage
|
||||||
from .person import Person
|
from .person import Person
|
||||||
|
|
|
@ -4,6 +4,14 @@ from typing import Dict, List
|
||||||
|
|
||||||
from .base_activity import ActivityObject, Image
|
from .base_activity import ActivityObject, Image
|
||||||
|
|
||||||
|
@dataclass(init=False)
|
||||||
|
class Tombstone(ActivityObject):
|
||||||
|
url: str
|
||||||
|
published: str
|
||||||
|
deleted: str
|
||||||
|
type: str = 'Tombstone'
|
||||||
|
|
||||||
|
|
||||||
@dataclass(init=False)
|
@dataclass(init=False)
|
||||||
class Note(ActivityObject):
|
class Note(ActivityObject):
|
||||||
''' Note activity '''
|
''' Note activity '''
|
||||||
|
|
|
@ -22,6 +22,8 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||||
sensitive = models.BooleanField(default=False)
|
sensitive = models.BooleanField(default=False)
|
||||||
# the created date can't be this, because of receiving federated posts
|
# the created date can't be this, because of receiving federated posts
|
||||||
published_date = models.DateTimeField(default=timezone.now)
|
published_date = models.DateTimeField(default=timezone.now)
|
||||||
|
deleted = models.BooleanField(default=False)
|
||||||
|
deleted_date = models.DateTimeField(default=timezone.now)
|
||||||
favorites = models.ManyToManyField(
|
favorites = models.ManyToManyField(
|
||||||
'User',
|
'User',
|
||||||
symmetrical=False,
|
symmetrical=False,
|
||||||
|
@ -104,6 +106,18 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||||
**kwargs
|
**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):
|
class GeneratedStatus(Status):
|
||||||
''' these are app-generated messages about user activity '''
|
''' these are app-generated messages about user activity '''
|
||||||
@property
|
@property
|
||||||
|
@ -112,7 +126,7 @@ class GeneratedStatus(Status):
|
||||||
message = self.content
|
message = self.content
|
||||||
books = ', '.join(
|
books = ', '.join(
|
||||||
'<a href="%s">"%s"</a>' % (self.book.local_id, self.book.title) \
|
'<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)
|
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_quotation, create_comment
|
||||||
from bookwyrm.status import create_tag, create_notification, create_rating
|
from bookwyrm.status import create_tag, create_notification, create_rating
|
||||||
from bookwyrm.status import create_generated_note
|
from bookwyrm.status import create_generated_note
|
||||||
|
from bookwyrm.status import delete_status
|
||||||
from bookwyrm.remote_user import get_or_create_remote_user
|
from bookwyrm.remote_user import get_or_create_remote_user
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,6 +198,12 @@ def handle_import_books(user, items):
|
||||||
return None
|
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):
|
def handle_rate(user, book, rating):
|
||||||
''' a review that's just a rating '''
|
''' a review that's just a rating '''
|
||||||
builder = create_rating
|
builder = create_rating
|
||||||
|
|
|
@ -6,6 +6,11 @@ from bookwyrm.books_manager import get_or_create_book
|
||||||
from bookwyrm.sanitize_html import InputHtmlParser
|
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):
|
def create_rating(user, book, rating):
|
||||||
''' a review that's just a rating '''
|
''' a review that's just a rating '''
|
||||||
if not rating or rating < 1 or rating > 5:
|
if not rating or rating < 1 or rating > 5:
|
||||||
|
|
|
@ -25,6 +25,17 @@
|
||||||
<span class="icon icon-public">
|
<span class="icon icon-public">
|
||||||
<span class="is-sr-only">Public post</span>
|
<span class="is-sr-only">Public post</span>
|
||||||
</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>
|
<a href="{{ status.remote_id }}">{{ status.published_date | naturaltime }}</a>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -11,7 +11,7 @@ localname_regex = r'(?P<username>[\w\-_]+)'
|
||||||
user_path = r'^user/%s' % username_regex
|
user_path = r'^user/%s' % username_regex
|
||||||
local_user_path = r'^user/%s' % localname_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+)' % \
|
status_path = r'%s/(%s)/(?P<status_id>\d+)' % \
|
||||||
(local_user_path, '|'.join(status_types))
|
(local_user_path, '|'.join(status_types))
|
||||||
|
|
||||||
|
@ -107,6 +107,8 @@ urlpatterns = [
|
||||||
re_path(r'^unfavorite/(?P<status_id>\d+)/?$', actions.unfavorite),
|
re_path(r'^unfavorite/(?P<status_id>\d+)/?$', actions.unfavorite),
|
||||||
re_path(r'^boost/(?P<status_id>\d+)/?$', actions.boost),
|
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'^shelve/?$', actions.shelve),
|
||||||
|
|
||||||
re_path(r'^follow/?$', actions.follow),
|
re_path(r'^follow/?$', actions.follow),
|
||||||
|
|
|
@ -418,6 +418,27 @@ def boost(request, status_id):
|
||||||
outgoing.handle_boost(request.user, status)
|
outgoing.handle_boost(request.user, status)
|
||||||
return redirect(request.headers.get('Referer', '/'))
|
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
|
@login_required
|
||||||
def follow(request):
|
def follow(request):
|
||||||
''' follow another user, here or abroad '''
|
''' follow another user, here or abroad '''
|
||||||
|
|
Loading…
Reference in a new issue