diff --git a/bookwyrm/activitypub/person.py b/bookwyrm/activitypub/person.py index 88349c02c..7e7d027eb 100644 --- a/bookwyrm/activitypub/person.py +++ b/bookwyrm/activitypub/person.py @@ -18,13 +18,13 @@ class PublicKey(ActivityObject): class Person(ActivityObject): ''' actor activitypub json ''' preferredUsername: str - name: str inbox: str outbox: str followers: str - summary: str publicKey: PublicKey endpoints: Dict + name: str = None + summary: str = None icon: Image = field(default_factory=lambda: {}) bookwyrmUser: bool = False manuallyApprovesFollowers: str = False diff --git a/bookwyrm/migrations/0027_auto_20201220_2007.py b/bookwyrm/migrations/0027_auto_20201220_2007.py new file mode 100644 index 000000000..a3ad4dda3 --- /dev/null +++ b/bookwyrm/migrations/0027_auto_20201220_2007.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.7 on 2020-12-20 20:07 + +import bookwyrm.models.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0026_status_content_warning'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='name', + field=bookwyrm.models.fields.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='user', + name='summary', + field=bookwyrm.models.fields.HtmlField(blank=True, null=True), + ), + ] diff --git a/bookwyrm/models/author.py b/bookwyrm/models/author.py index 47714d4ec..911cc109d 100644 --- a/bookwyrm/models/author.py +++ b/bookwyrm/models/author.py @@ -28,11 +28,10 @@ class Author(ActivitypubMixin, BookWyrmModel): bio = fields.HtmlField(null=True, blank=True) def save(self, *args, **kwargs): - ''' can't be abstract for query reasons, but you shouldn't USE it ''' - if self.id and not self.remote_id: + ''' handle remote vs origin ids ''' + if self.id: self.remote_id = self.get_remote_id() - - if not self.id: + else: self.origin_id = self.remote_id self.remote_id = None return super().save(*args, **kwargs) diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index e4f1f29b1..0a3265915 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -83,10 +83,9 @@ class Book(ActivitypubMixin, BookWyrmModel): if not isinstance(self, Edition) and not isinstance(self, Work): raise ValueError('Books should be added as Editions or Works') - if self.id and not self.remote_id: + if self.id: self.remote_id = self.get_remote_id() - - if not self.id: + else: self.origin_id = self.remote_id self.remote_id = None return super().save(*args, **kwargs) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 3162c22b7..3654e5543 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -1,5 +1,7 @@ ''' models for storing different kinds of Activities ''' from dataclasses import MISSING +import re + from django.apps import apps from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models @@ -155,7 +157,7 @@ class Comment(Status): @property def pure_content(self): ''' indicate the book in question for mastodon (or w/e) users ''' - return '

%s

(comment on "%s")

' % \ + return '%s

(comment on "%s")

' % \ (self.content, self.book.remote_id, self.book.title) activity_serializer = activitypub.Comment @@ -171,8 +173,10 @@ class Quotation(Status): @property def pure_content(self): ''' indicate the book in question for mastodon (or w/e) users ''' - return '

"%s"
-- "%s"

%s

' % ( - self.quote, + quote = re.sub(r'^

', '

"', self.quote) + quote = re.sub(r'

$', '"

', quote) + return '%s

-- "%s"

%s' % ( + quote, self.book.remote_id, self.book.title, self.content, diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index ce50fc092..30eeffbc8 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -42,7 +42,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): blank=True, ) outbox = fields.RemoteIdField(unique=True) - summary = fields.HtmlField(default='') + summary = fields.HtmlField(null=True, blank=True) local = models.BooleanField(default=False) bookwyrm_user = fields.BooleanField(default=True) localname = models.CharField( @@ -51,7 +51,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): unique=True ) # name is your display name, which you can change at will - name = fields.CharField(max_length=100, default='') + name = fields.CharField(max_length=100, null=True, blank=True) avatar = fields.ImageField( upload_to='avatars/', blank=True, null=True, activitypub_field='icon', alt_field='alt_text') @@ -100,7 +100,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): @property def display_name(self): ''' show the cleanest version of the user's name possible ''' - if self.name != '': + if self.name and self.name != '': return self.name return self.localname or self.username diff --git a/bookwyrm/outgoing.py b/bookwyrm/outgoing.py index 7daa74de3..13df90263 100644 --- a/bookwyrm/outgoing.py +++ b/bookwyrm/outgoing.py @@ -221,8 +221,6 @@ def handle_status(user, form): matches = [] for match in re.finditer(regex.username, status.content): username = match.group().strip().split('@')[1:] - print(match.group()) - print(len(username)) if len(username) == 1: # this looks like a local user (@user), fill in the domain username.append(DOMAIN) @@ -251,9 +249,9 @@ def handle_status(user, form): r'%s\g<1>' % (url, username), content) if not isinstance(status, models.GeneratedNote): - status.content = to_markown(content) + status.content = to_markdown(content) if hasattr(status, 'quote'): - status.quote = to_markown(status.quote) + status.quote = to_markdown(status.quote) status.save() # notify reply parent or tagged users @@ -272,7 +270,7 @@ def handle_status(user, form): broadcast(user, remote_activity, software='other') -def to_markown(content): +def to_markdown(content): ''' catch links and convert to markdown ''' content = re.sub( r'([^(href=")])(https?:\/\/([A-Za-z\.\-_\/]+' \ diff --git a/bookwyrm/templates/snippets/trimmed_text.html b/bookwyrm/templates/snippets/trimmed_text.html index b3207a92e..e8a1fa755 100644 --- a/bookwyrm/templates/snippets/trimmed_text.html +++ b/bookwyrm/templates/snippets/trimmed_text.html @@ -6,18 +6,18 @@ {% if trimmed != full %}
-
-
{% else %} -
{{ full }}
+
{{ full | to_markdown | safe }}
{% endif %} {% endwith %} diff --git a/bookwyrm/templates/snippets/user_header.html b/bookwyrm/templates/snippets/user_header.html index f4f9733fa..c06465e80 100644 --- a/bookwyrm/templates/snippets/user_header.html +++ b/bookwyrm/templates/snippets/user_header.html @@ -23,7 +23,14 @@
{% if user.summary %} -
{{ user.summary | safe }}
+
+
+ +
+
+
{{ user.summary | to_markdown | safe }}
+
+
{% endif %}
diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index 91934d48d..61b097bd2 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -7,6 +7,7 @@ from django import template from django.utils import timezone from bookwyrm import models +from bookwyrm.outgoing import to_markdown register = template.Library() @@ -132,6 +133,13 @@ def time_since(date): return '%ds' % delta.seconds +@register.filter(name="to_markdown") +def get_markdown(content): + ''' convert markdown to html ''' + if content: + return to_markdown(content) + return None + @register.simple_tag(takes_context=True) def active_shelf(context, book): ''' check what shelf a user has a book on, if any ''' diff --git a/bookwyrm/tests/activitypub/test_base_activity.py b/bookwyrm/tests/activitypub/test_base_activity.py index 87420aa70..4cdc2c70f 100644 --- a/bookwyrm/tests/activitypub/test_base_activity.py +++ b/bookwyrm/tests/activitypub/test_base_activity.py @@ -103,7 +103,7 @@ class BaseActivity(TestCase): def test_to_model_simple_fields(self): ''' test setting simple fields ''' - self.assertEqual(self.user.name, '') + self.assertIsNone(self.user.name) activity = activitypub.Person( id=self.user.remote_id, diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index b9a6d6c97..d98b8b18d 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -167,8 +167,7 @@ class Status(TestCase): self.assertEqual(activity['type'], 'Note') self.assertEqual( activity['content'], - '

test content

' \ - '(comment on "Test Edition")

' % + 'test content

(comment on "Test Edition")

' % self.book.remote_id) self.assertEqual(activity['attachment'][0].type, 'Image') self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ @@ -198,8 +197,8 @@ class Status(TestCase): self.assertEqual(activity['type'], 'Note') self.assertEqual( activity['content'], - '

"a sickening sense"
-- "Test Edition"

' \ - '

test content

' % self.book.remote_id) + 'a sickening sense

-- "Test Edition"

' \ + 'test content' % self.book.remote_id) self.assertEqual(activity['attachment'][0].type, 'Image') self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ (settings.DOMAIN, self.book.cover.url)) diff --git a/bookwyrm/tests/test_incoming.py b/bookwyrm/tests/test_incoming.py index 2cc4c1f44..7e58da867 100644 --- a/bookwyrm/tests/test_incoming.py +++ b/bookwyrm/tests/test_incoming.py @@ -464,7 +464,7 @@ class Incoming(TestCase): 'data/ap_user.json') userdata = json.loads(datafile.read_bytes()) del userdata['icon'] - self.assertEqual(self.local_user.name, '') + self.assertIsNone(self.local_user.name) incoming.handle_update_user({'object': userdata}) user = models.User.objects.get(id=self.local_user.id) self.assertEqual(user.name, 'MOUSE?? MOUSE!!') diff --git a/bookwyrm/view_actions.py b/bookwyrm/view_actions.py index 1df1dcbaf..c3e4d2be7 100644 --- a/bookwyrm/view_actions.py +++ b/bookwyrm/view_actions.py @@ -17,10 +17,8 @@ from django.template.response import TemplateResponse from django.utils import timezone from django.views.decorators.http import require_GET, require_POST -from bookwyrm import books_manager +from bookwyrm import books_manager, forms, models, outgoing, goodreads_import from bookwyrm.broadcast import broadcast -from bookwyrm import forms, models, outgoing -from bookwyrm import goodreads_import from bookwyrm.emailing import password_reset_email from bookwyrm.settings import DOMAIN from bookwyrm.views import get_user_from_username @@ -244,7 +242,7 @@ def edit_book(request, book_id): 'form': form } return TemplateResponse(request, 'edit_book.html', data) - form.save() + book = form.save() outgoing.handle_update_book(request.user, book) return redirect('/book/%s' % book.id) diff --git a/bookwyrm/views.py b/bookwyrm/views.py index c27391cc2..8e40f3623 100644 --- a/bookwyrm/views.py +++ b/bookwyrm/views.py @@ -684,7 +684,8 @@ def author_page(request, author_id): if is_api_request(request): return JsonResponse(author.to_activity(), encoder=ActivityEncoder) - books = models.Work.objects.filter(authors=author) + books = models.Work.objects.filter( + Q(authors=author) | Q(editions__authors=author)).distinct() data = { 'title': author.name, 'author': author,