mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-10-31 22:19:00 +00:00
Merge branch 'main' into production
This commit is contained in:
commit
255261dc3d
15 changed files with 72 additions and 35 deletions
|
@ -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
|
||||
|
|
24
bookwyrm/migrations/0027_auto_20201220_2007.py
Normal file
24
bookwyrm/migrations/0027_auto_20201220_2007.py
Normal 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),
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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\.\-_\/]+' \
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 '''
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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!!')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue