Merge pull request #412 from mouse-reeve/jankiness

Jankiness
This commit is contained in:
Mouse Reeve 2020-12-20 13:00:43 -08:00 committed by GitHub
commit 62d3faa797
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 72 additions and 35 deletions

View file

@ -18,13 +18,13 @@ class PublicKey(ActivityObject):
class Person(ActivityObject): class Person(ActivityObject):
''' actor activitypub json ''' ''' actor activitypub json '''
preferredUsername: str preferredUsername: str
name: str
inbox: str inbox: str
outbox: str outbox: str
followers: str followers: str
summary: str
publicKey: PublicKey publicKey: PublicKey
endpoints: Dict endpoints: Dict
name: str = None
summary: str = None
icon: Image = field(default_factory=lambda: {}) icon: Image = field(default_factory=lambda: {})
bookwyrmUser: bool = False bookwyrmUser: bool = False
manuallyApprovesFollowers: str = False manuallyApprovesFollowers: str = False

View file

@ -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),
),
]

View file

@ -28,11 +28,10 @@ class Author(ActivitypubMixin, BookWyrmModel):
bio = fields.HtmlField(null=True, blank=True) bio = fields.HtmlField(null=True, blank=True)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
''' can't be abstract for query reasons, but you shouldn't USE it ''' ''' handle remote vs origin ids '''
if self.id and not self.remote_id: if self.id:
self.remote_id = self.get_remote_id() self.remote_id = self.get_remote_id()
else:
if not self.id:
self.origin_id = self.remote_id self.origin_id = self.remote_id
self.remote_id = None self.remote_id = None
return super().save(*args, **kwargs) return super().save(*args, **kwargs)

View file

@ -83,10 +83,9 @@ class Book(ActivitypubMixin, BookWyrmModel):
if not isinstance(self, Edition) and not isinstance(self, Work): if not isinstance(self, Edition) and not isinstance(self, Work):
raise ValueError('Books should be added as Editions or Works') 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() self.remote_id = self.get_remote_id()
else:
if not self.id:
self.origin_id = self.remote_id self.origin_id = self.remote_id
self.remote_id = None self.remote_id = None
return super().save(*args, **kwargs) return super().save(*args, **kwargs)

View file

@ -1,5 +1,7 @@
''' models for storing different kinds of Activities ''' ''' models for storing different kinds of Activities '''
from dataclasses import MISSING from dataclasses import MISSING
import re
from django.apps import apps from django.apps import apps
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models
@ -155,7 +157,7 @@ class Comment(Status):
@property @property
def pure_content(self): def pure_content(self):
''' indicate the book in question for mastodon (or w/e) users ''' ''' indicate the book in question for mastodon (or w/e) users '''
return '<p>%s</p><p>(comment on <a href="%s">"%s"</a>)</p>' % \ return '%s<p>(comment on <a href="%s">"%s"</a>)</p>' % \
(self.content, self.book.remote_id, self.book.title) (self.content, self.book.remote_id, self.book.title)
activity_serializer = activitypub.Comment activity_serializer = activitypub.Comment
@ -171,8 +173,10 @@ class Quotation(Status):
@property @property
def pure_content(self): def pure_content(self):
''' indicate the book in question for mastodon (or w/e) users ''' ''' indicate the book in question for mastodon (or w/e) users '''
return '<p>"%s"<br>-- <a href="%s">"%s"</a></p><p>%s</p>' % ( quote = re.sub(r'^<p>', '<p>"', self.quote)
self.quote, quote = re.sub(r'</p>$', '"</p>', quote)
return '%s <p>-- <a href="%s">"%s"</a></p>%s' % (
quote,
self.book.remote_id, self.book.remote_id,
self.book.title, self.book.title,
self.content, self.content,

View file

@ -42,7 +42,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
blank=True, blank=True,
) )
outbox = fields.RemoteIdField(unique=True) outbox = fields.RemoteIdField(unique=True)
summary = fields.HtmlField(default='') summary = fields.HtmlField(null=True, blank=True)
local = models.BooleanField(default=False) local = models.BooleanField(default=False)
bookwyrm_user = fields.BooleanField(default=True) bookwyrm_user = fields.BooleanField(default=True)
localname = models.CharField( localname = models.CharField(
@ -51,7 +51,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
unique=True unique=True
) )
# name is your display name, which you can change at will # 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( avatar = fields.ImageField(
upload_to='avatars/', blank=True, null=True, upload_to='avatars/', blank=True, null=True,
activitypub_field='icon', alt_field='alt_text') activitypub_field='icon', alt_field='alt_text')
@ -100,7 +100,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
@property @property
def display_name(self): def display_name(self):
''' show the cleanest version of the user's name possible ''' ''' show the cleanest version of the user's name possible '''
if self.name != '': if self.name and self.name != '':
return self.name return self.name
return self.localname or self.username return self.localname or self.username

View file

@ -221,8 +221,6 @@ def handle_status(user, form):
matches = [] matches = []
for match in re.finditer(regex.username, status.content): for match in re.finditer(regex.username, status.content):
username = match.group().strip().split('@')[1:] username = match.group().strip().split('@')[1:]
print(match.group())
print(len(username))
if len(username) == 1: if len(username) == 1:
# this looks like a local user (@user), fill in the domain # this looks like a local user (@user), fill in the domain
username.append(DOMAIN) username.append(DOMAIN)
@ -251,9 +249,9 @@ def handle_status(user, form):
r'<a href="%s">%s</a>\g<1>' % (url, username), r'<a href="%s">%s</a>\g<1>' % (url, username),
content) content)
if not isinstance(status, models.GeneratedNote): if not isinstance(status, models.GeneratedNote):
status.content = to_markown(content) status.content = to_markdown(content)
if hasattr(status, 'quote'): if hasattr(status, 'quote'):
status.quote = to_markown(status.quote) status.quote = to_markdown(status.quote)
status.save() status.save()
# notify reply parent or tagged users # notify reply parent or tagged users
@ -272,7 +270,7 @@ def handle_status(user, form):
broadcast(user, remote_activity, software='other') broadcast(user, remote_activity, software='other')
def to_markown(content): def to_markdown(content):
''' catch links and convert to markdown ''' ''' catch links and convert to markdown '''
content = re.sub( content = re.sub(
r'([^(href=")])(https?:\/\/([A-Za-z\.\-_\/]+' \ r'([^(href=")])(https?:\/\/([A-Za-z\.\-_\/]+' \

View file

@ -6,18 +6,18 @@
{% if trimmed != full %} {% if trimmed != full %}
<div> <div>
<input type="radio" name="show-hide-{{ uuid }}" id="show-{{ uuid }}" class="toggle-control" checked> <input type="radio" name="show-hide-{{ uuid }}" id="show-{{ uuid }}" class="toggle-control" checked>
<blockquote class="content toggle-content hidden">{{ trimmed }} <blockquote class="content toggle-content hidden">{{ trimmed | to_markdown | safe }}
<label class="button is-small" for="hide-{{ uuid }}"><div role="button" tabindex="0">show more</div></label> <label class="button is-small" for="hide-{{ uuid }}"><div role="button" tabindex="0">show more</div></label>
</blockquote> </blockquote>
</div> </div>
<div> <div>
<input type="radio" name="show-hide-{{ uuid }}" id="hide-{{ uuid }}" class="toggle-control"> <input type="radio" name="show-hide-{{ uuid }}" id="hide-{{ uuid }}" class="toggle-control">
<blockquote class="content toggle-content hidden">{{ full }} <blockquote class="content toggle-content hidden">{{ full | to_markdown | safe }}
<label class="button is-small" for="show-{{ uuid }}"><div role="button" tabindex="0">show less</div></label> <label class="button is-small" for="show-{{ uuid }}"><div role="button" tabindex="0">show less</div></label>
</blockquote> </blockquote>
</div> </div>
{% else %} {% else %}
<blockquote class="content">{{ full }}</blockquote> <blockquote class="content">{{ full | to_markdown | safe }}</blockquote>
{% endif %} {% endif %}
{% endwith %} {% endwith %}

View file

@ -23,7 +23,14 @@
<div class="column"> <div class="column">
{% if user.summary %} {% if user.summary %}
<blockquote><span class="icon icon-quote-open"></span>{{ user.summary | safe }}</blockquote> <div class="columns">
<div class="column is-narrow">
<span class="icon icon-quote-open"></span>
</div>
<div class="column">
<blockquote>{{ user.summary | to_markdown | safe }}</blockquote>
</div>
</div>
{% endif %} {% endif %}
</div> </div>
</div> </div>

View file

@ -7,6 +7,7 @@ from django import template
from django.utils import timezone from django.utils import timezone
from bookwyrm import models from bookwyrm import models
from bookwyrm.outgoing import to_markdown
register = template.Library() register = template.Library()
@ -132,6 +133,13 @@ def time_since(date):
return '%ds' % delta.seconds 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) @register.simple_tag(takes_context=True)
def active_shelf(context, book): def active_shelf(context, book):
''' check what shelf a user has a book on, if any ''' ''' check what shelf a user has a book on, if any '''

View file

@ -103,7 +103,7 @@ class BaseActivity(TestCase):
def test_to_model_simple_fields(self): def test_to_model_simple_fields(self):
''' test setting simple fields ''' ''' test setting simple fields '''
self.assertEqual(self.user.name, '') self.assertIsNone(self.user.name)
activity = activitypub.Person( activity = activitypub.Person(
id=self.user.remote_id, id=self.user.remote_id,

View file

@ -167,8 +167,7 @@ class Status(TestCase):
self.assertEqual(activity['type'], 'Note') self.assertEqual(activity['type'], 'Note')
self.assertEqual( self.assertEqual(
activity['content'], activity['content'],
'<p>test content</p><p>' \ 'test content<p>(comment on <a href="%s">"Test Edition"</a>)</p>' %
'(comment on <a href="%s">"Test Edition"</a>)</p>' %
self.book.remote_id) self.book.remote_id)
self.assertEqual(activity['attachment'][0].type, 'Image') self.assertEqual(activity['attachment'][0].type, 'Image')
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
@ -198,8 +197,8 @@ class Status(TestCase):
self.assertEqual(activity['type'], 'Note') self.assertEqual(activity['type'], 'Note')
self.assertEqual( self.assertEqual(
activity['content'], activity['content'],
'<p>"a sickening sense"<br>-- <a href="%s">"Test Edition"</a></p>' \ 'a sickening sense <p>-- <a href="%s">"Test Edition"</a></p>' \
'<p>test content</p>' % self.book.remote_id) 'test content' % self.book.remote_id)
self.assertEqual(activity['attachment'][0].type, 'Image') self.assertEqual(activity['attachment'][0].type, 'Image')
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \ self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
(settings.DOMAIN, self.book.cover.url)) (settings.DOMAIN, self.book.cover.url))

View file

@ -464,7 +464,7 @@ class Incoming(TestCase):
'data/ap_user.json') 'data/ap_user.json')
userdata = json.loads(datafile.read_bytes()) userdata = json.loads(datafile.read_bytes())
del userdata['icon'] del userdata['icon']
self.assertEqual(self.local_user.name, '') self.assertIsNone(self.local_user.name)
incoming.handle_update_user({'object': userdata}) incoming.handle_update_user({'object': userdata})
user = models.User.objects.get(id=self.local_user.id) user = models.User.objects.get(id=self.local_user.id)
self.assertEqual(user.name, 'MOUSE?? MOUSE!!') self.assertEqual(user.name, 'MOUSE?? MOUSE!!')

View file

@ -17,10 +17,8 @@ from django.template.response import TemplateResponse
from django.utils import timezone from django.utils import timezone
from django.views.decorators.http import require_GET, require_POST 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.broadcast import broadcast
from bookwyrm import forms, models, outgoing
from bookwyrm import goodreads_import
from bookwyrm.emailing import password_reset_email from bookwyrm.emailing import password_reset_email
from bookwyrm.settings import DOMAIN from bookwyrm.settings import DOMAIN
from bookwyrm.views import get_user_from_username from bookwyrm.views import get_user_from_username
@ -244,7 +242,7 @@ def edit_book(request, book_id):
'form': form 'form': form
} }
return TemplateResponse(request, 'edit_book.html', data) return TemplateResponse(request, 'edit_book.html', data)
form.save() book = form.save()
outgoing.handle_update_book(request.user, book) outgoing.handle_update_book(request.user, book)
return redirect('/book/%s' % book.id) return redirect('/book/%s' % book.id)

View file

@ -684,7 +684,8 @@ def author_page(request, author_id):
if is_api_request(request): if is_api_request(request):
return JsonResponse(author.to_activity(), encoder=ActivityEncoder) 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 = { data = {
'title': author.name, 'title': author.name,
'author': author, 'author': author,