Convert activitypub Image into model ImageField

This commit is contained in:
Mouse Reeve 2020-11-23 13:43:46 -08:00
parent 5526b4773e
commit e2debd855c
4 changed files with 37 additions and 26 deletions

View File

@ -4,7 +4,8 @@ import sys
from .base_activity import ActivityEncoder, Image, PublicKey, Signature from .base_activity import ActivityEncoder, Image, PublicKey, Signature
from .base_activity import Link, Mention from .base_activity import Link, Mention
from .base_activity import ActivitySerializerError, tag_formatter from .base_activity import ActivitySerializerError
from .base_activity import tag_formatter, image_formatter
from .note import Note, GeneratedNote, Article, Comment, Review, Quotation from .note import Note, GeneratedNote, Article, Comment, Review, Quotation
from .note import Tombstone from .note import Tombstone
from .interaction import Boost, Like from .interaction import Boost, Like

View File

@ -1,11 +1,15 @@
''' basics for an activitypub serializer ''' ''' basics for an activitypub serializer '''
from dataclasses import dataclass, fields, MISSING from dataclasses import dataclass, fields, MISSING
from json import JSONEncoder from json import JSONEncoder
from uuid import uuid4
from bookwyrm import books_manager, models from django.core.files.base import ContentFile
from django.db.models.fields.related_descriptors \ from django.db.models.fields.related_descriptors \
import ForwardManyToOneDescriptor, ManyToManyDescriptor import ForwardManyToOneDescriptor, ManyToManyDescriptor
from django.db.models.fields.files import ImageFileDescriptor
import requests
from bookwyrm import books_manager, models
class ActivitySerializerError(ValueError): class ActivitySerializerError(ValueError):
@ -91,6 +95,7 @@ class ActivityObject:
model_fields = [m.name for m in model._meta.get_fields()] model_fields = [m.name for m in model._meta.get_fields()]
mapped_fields = {} mapped_fields = {}
many_to_many_fields = {} many_to_many_fields = {}
image_fields = {}
for mapping in model.activity_mappings: for mapping in model.activity_mappings:
if mapping.model_key not in model_fields: if mapping.model_key not in model_fields:
@ -110,12 +115,13 @@ class ActivityObject:
formatted_value = mapping.model_formatter(value) formatted_value = mapping.model_formatter(value)
if isinstance(model_field, ManyToManyDescriptor): if isinstance(model_field, ManyToManyDescriptor):
many_to_many_fields[mapping.model_key] = formatted_value many_to_many_fields[mapping.model_key] = formatted_value
elif isinstance(model_field, ImageFileDescriptor):
image_fields[mapping.model_key] = formatted_value
else: else:
mapped_fields[mapping.model_key] = formatted_value mapped_fields[mapping.model_key] = formatted_value
# updating an existing model isntance
if instance: if instance:
# updating an existing model isntance
for k, v in mapped_fields.items(): for k, v in mapped_fields.items():
setattr(instance, k, v) setattr(instance, k, v)
instance.save() instance.save()
@ -123,9 +129,14 @@ class ActivityObject:
# creating a new model instance # creating a new model instance
instance = model.objects.create(**mapped_fields) instance = model.objects.create(**mapped_fields)
# add many-to-many fields
for (model_key, values) in many_to_many_fields.items(): for (model_key, values) in many_to_many_fields.items():
getattr(instance, model_key).set(values) getattr(instance, model_key).set(values)
instance.save() instance.save()
# add images
for (model_key, value) in image_fields.items():
getattr(instance, model_key).save(*value, save=True)
return instance return instance
@ -174,3 +185,21 @@ def tag_formatter(tags):
continue continue
items.append(item) items.append(item)
return items return items
def image_formatter(image_json):
''' helper function to load images and format them for a model '''
url = image_json.get('url')
if not url:
return None
try:
response = requests.get(url)
except ConnectionError:
return None
if not response.ok:
return None
image_name = str(uuid4()) + '.' + url.split('.')[-1]
image_content = ContentFile(response.content)
return [image_name, image_content]

View File

@ -114,7 +114,8 @@ class User(OrderedCollectionPageMixin, AbstractUser):
), ),
ActivityMapping( ActivityMapping(
'icon', 'avatar', 'icon', 'avatar',
lambda x: image_formatter(x, '/static/images/default_avi.jpg') lambda x: image_formatter(x, '/static/images/default_avi.jpg'),
activitypub.image_formatter
), ),
ActivityMapping( ActivityMapping(
'manuallyApprovesFollowers', 'manuallyApprovesFollowers',

View File

@ -25,11 +25,6 @@ def get_or_create_remote_user(actor):
user = create_remote_user(data) user = create_remote_user(data)
user.federated_server = get_or_create_remote_server(actor_parts.netloc) user.federated_server = get_or_create_remote_server(actor_parts.netloc)
user.save() user.save()
avatar = get_avatar(data)
if avatar:
user.avatar.save(*avatar)
if user.bookwyrm_user: if user.bookwyrm_user:
get_remote_reviews.delay(user.id) get_remote_reviews.delay(user.id)
return user return user
@ -69,21 +64,6 @@ def refresh_remote_user(user):
activity.to_model(models.User, instance=user) activity.to_model(models.User, instance=user)
def get_avatar(data):
''' find the icon attachment and load the image from the remote sever '''
icon_blob = data.get('icon')
if not icon_blob or not icon_blob.get('url'):
return None
response = requests.get(icon_blob['url'])
if not response.ok:
return None
image_name = str(uuid4()) + '.' + icon_blob['url'].split('.')[-1]
image_content = ContentFile(response.content)
return [image_name, image_content]
@app.task @app.task
def get_remote_reviews(user_id): def get_remote_reviews(user_id):
''' ingest reviews by a new remote bookwyrm user ''' ''' ingest reviews by a new remote bookwyrm user '''