From 7ed2e310c02d3b175d2a3566374f09c313cba350 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 28 Nov 2020 13:40:09 -0800 Subject: [PATCH] User origin ids for books and authors --- bookwyrm/activitypub/base_activity.py | 10 +++++++--- bookwyrm/models/author.py | 23 +++++++++++++++++++++++ bookwyrm/models/book.py | 9 +++++---- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index 620579a0..b9b6b9b4 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -222,14 +222,18 @@ class ActivityObject: def resolve_remote_id(model, remote_id, refresh=False): ''' look up the remote_id in the database or load it remotely ''' - result = model.objects + objects = model.objects if hasattr(model.objects, 'select_subclasses'): - result = result.select_subclasses() + objects = objects.select_subclasses() # first, check for an existing copy in the database - result = result.filter( + result = objects.filter( remote_id=remote_id ).first() + if not result and hasattr(model, 'origin_id'): + result = objects.filter( + origin_id=remote_id + ).first() if result and not refresh: return result diff --git a/bookwyrm/models/author.py b/bookwyrm/models/author.py index 1d701797..0a934e45 100644 --- a/bookwyrm/models/author.py +++ b/bookwyrm/models/author.py @@ -1,8 +1,12 @@ ''' database schema for info about authors ''' +from uuid import uuid4 +import re + from django.db import models from django.utils import timezone from bookwyrm import activitypub +from bookwyrm.settings import DOMAIN from bookwyrm.utils.fields import ArrayField from .base_model import ActivitypubMixin, ActivityMapping, BookWyrmModel @@ -27,6 +31,25 @@ class Author(ActivitypubMixin, BookWyrmModel): ) bio = models.TextField(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: + self.remote_id = self.get_remote_id() + + if not self.id: + # force set the remote id to a local version + self.origin_id = self.remote_id + self.remote_id = self.get_remote_id() + return super().save(*args, **kwargs) + + def get_remote_id(self): + ''' editions and works both use "book" instead of model_name ''' + uuid = str(uuid4())[:8] + # in Book, the title is used to make the url more readable, but + # since an author's name can change, I didn't want to lock in a + # potential deadname (or maiden name) in the urk. + return 'https://%s/author/%s' % (DOMAIN, uuid) + @property def display_name(self): ''' Helper to return a displayable name''' diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index d5e811bb..d3460aac 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -1,4 +1,5 @@ ''' database schema for books and shelves ''' +from uuid import uuid4 import re from django.db import models @@ -100,14 +101,14 @@ class Book(ActivitypubMixin, BookWyrmModel): if not self.id: # force set the remote id to a local version self.origin_id = self.remote_id - saved = super().save(*args, **kwargs) - saved.remote_id = self.get_remote_id() - return saved.save() + self.remote_id = self.get_remote_id() return super().save(*args, **kwargs) def get_remote_id(self): ''' editions and works both use "book" instead of model_name ''' - return 'https://%s/book/%d' % (DOMAIN, self.id) + uuid = str(uuid4())[:8] + clean_title = re.sub(r'[\W-]', '', self.title.replace(' ', '-')).lower() + return 'https://%s/author/%s-%s' % (DOMAIN, clean_title, uuid) def __repr__(self): return "<{} key={!r} title={!r}>".format(