Merge branch 'main' into production

This commit is contained in:
Mouse Reeve 2020-12-20 13:15:27 -08:00
commit 255261dc3d
15 changed files with 72 additions and 35 deletions

View file

@ -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

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)
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)

View file

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

View file

@ -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 '<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)
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 '<p>"%s"<br>-- <a href="%s">"%s"</a></p><p>%s</p>' % (
self.quote,
quote = re.sub(r'^<p>', '<p>"', 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.title,
self.content,

View file

@ -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

View file

@ -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'<a href="%s">%s</a>\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\.\-_\/]+' \

View file

@ -6,18 +6,18 @@
{% if trimmed != full %}
<div>
<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>
</blockquote>
</div>
<div>
<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>
</blockquote>
</div>
{% else %}
<blockquote class="content">{{ full }}</blockquote>
<blockquote class="content">{{ full | to_markdown | safe }}</blockquote>
{% endif %}
{% endwith %}

View file

@ -23,7 +23,14 @@
<div class="column">
{% 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 %}
</div>
</div>

View file

@ -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 '''

View file

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

View file

@ -167,8 +167,7 @@ class Status(TestCase):
self.assertEqual(activity['type'], 'Note')
self.assertEqual(
activity['content'],
'<p>test content</p><p>' \
'(comment on <a href="%s">"Test Edition"</a>)</p>' %
'test content<p>(comment on <a href="%s">"Test Edition"</a>)</p>' %
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'],
'<p>"a sickening sense"<br>-- <a href="%s">"Test Edition"</a></p>' \
'<p>test content</p>' % self.book.remote_id)
'a sickening sense <p>-- <a href="%s">"Test Edition"</a></p>' \
'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))

View file

@ -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!!')

View file

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

View file

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