mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-26 03:21:05 +00:00
Receive and save incoming images
This commit is contained in:
parent
88e4705717
commit
ad7ce6595b
7 changed files with 62 additions and 29 deletions
|
@ -5,7 +5,8 @@ import sys
|
|||
from .base_activity import ActivityEncoder, Image, PublicKey, Signature
|
||||
from .base_activity import Link, Mention
|
||||
from .base_activity import ActivitySerializerError
|
||||
from .base_activity import tag_formatter, image_formatter
|
||||
from .base_activity import tag_formatter
|
||||
from .base_activity import image_formatter, image_attachments_formatter
|
||||
from .note import Note, GeneratedNote, Article, Comment, Review, Quotation
|
||||
from .note import Tombstone
|
||||
from .interaction import Boost, Like
|
||||
|
|
|
@ -5,7 +5,8 @@ from uuid import uuid4
|
|||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db.models.fields.related_descriptors \
|
||||
import ForwardManyToOneDescriptor, ManyToManyDescriptor
|
||||
import ForwardManyToOneDescriptor, ManyToManyDescriptor, \
|
||||
ReverseManyToOneDescriptor
|
||||
from django.db.models.fields.files import ImageFileDescriptor
|
||||
import requests
|
||||
|
||||
|
@ -95,6 +96,7 @@ class ActivityObject:
|
|||
model_fields = [m.name for m in model._meta.get_fields()]
|
||||
mapped_fields = {}
|
||||
many_to_many_fields = {}
|
||||
one_to_many_fields = {}
|
||||
image_fields = {}
|
||||
|
||||
for mapping in model.activity_mappings:
|
||||
|
@ -107,15 +109,20 @@ class ActivityObject:
|
|||
value = getattr(self, mapping.activity_key)
|
||||
model_field = getattr(model, mapping.model_key)
|
||||
|
||||
# remote_id -> foreign key resolver
|
||||
if isinstance(model_field, ForwardManyToOneDescriptor) and value:
|
||||
fk_model = model_field.field.related_model
|
||||
value = resolve_foreign_key(fk_model, value)
|
||||
|
||||
formatted_value = mapping.model_formatter(value)
|
||||
if isinstance(model_field, ManyToManyDescriptor):
|
||||
if isinstance(model_field, ForwardManyToOneDescriptor) and \
|
||||
formatted_value:
|
||||
# foreign key remote id reolver
|
||||
fk_model = model_field.field.related_model
|
||||
reference = resolve_foreign_key(fk_model, formatted_value)
|
||||
mapped_fields[mapping.model_key] = reference
|
||||
elif isinstance(model_field, ManyToManyDescriptor):
|
||||
many_to_many_fields[mapping.model_key] = formatted_value
|
||||
elif isinstance(model_field, ReverseManyToOneDescriptor):
|
||||
# attachments on statuses, for example
|
||||
one_to_many_fields[mapping.model_key] = formatted_value
|
||||
elif isinstance(model_field, ImageFileDescriptor):
|
||||
# image fields need custom handling
|
||||
image_fields[mapping.model_key] = formatted_value
|
||||
else:
|
||||
mapped_fields[mapping.model_key] = formatted_value
|
||||
|
@ -137,6 +144,18 @@ class ActivityObject:
|
|||
# add images
|
||||
for (model_key, value) in image_fields.items():
|
||||
getattr(instance, model_key).save(*value, save=True)
|
||||
|
||||
# add one to many fields
|
||||
for (model_key, values) in one_to_many_fields.items():
|
||||
items = []
|
||||
for item in values:
|
||||
# the reference id wasn't available at creation time
|
||||
setattr(item, instance.__class__.__name__.lower(), instance)
|
||||
item.save()
|
||||
items.append(item)
|
||||
if items:
|
||||
getattr(instance, model_key).set(items)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
|
@ -167,15 +186,14 @@ def resolve_foreign_key(model, remote_id):
|
|||
return result
|
||||
|
||||
|
||||
def tag_formatter(tags):
|
||||
def tag_formatter(tags, tag_type):
|
||||
''' helper function to extract foreign keys from tag activity json '''
|
||||
items = []
|
||||
types = {
|
||||
'Book': models.Book,
|
||||
'Mention': models.User,
|
||||
}
|
||||
for tag in tags:
|
||||
tag_type = tag.get('type')
|
||||
for tag in [t for t in tags if t.get('type') == tag_type]:
|
||||
if not tag_type in types:
|
||||
continue
|
||||
remote_id = tag.get('href')
|
||||
|
@ -203,3 +221,14 @@ def image_formatter(image_json):
|
|||
image_name = str(uuid4()) + '.' + url.split('.')[-1]
|
||||
image_content = ContentFile(response.content)
|
||||
return [image_name, image_content]
|
||||
|
||||
|
||||
def image_attachments_formatter(images_json):
|
||||
''' deserialize a list of images '''
|
||||
attachments = []
|
||||
for image in images_json:
|
||||
attachment = models.Attachment()
|
||||
image_field = image_formatter(image)
|
||||
attachment.image.save(*image_field, save=False)
|
||||
attachments.append(attachment)
|
||||
return attachments
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 3.0.7 on 2020-11-24 00:41
|
||||
# Generated by Django 3.0.7 on 2020-11-24 17:46
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
@ -19,7 +19,7 @@ class Migration(migrations.Migration):
|
|||
('updated_date', models.DateTimeField(auto_now=True)),
|
||||
('remote_id', models.CharField(max_length=255, null=True)),
|
||||
('image', models.ImageField(blank=True, null=True, upload_to='status/')),
|
||||
('status', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='bookwyrm.Status')),
|
||||
('status', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='bookwyrm.Status')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
|
|
|
@ -7,7 +7,7 @@ from .connector import Connector
|
|||
from .relationship import UserFollows, UserFollowRequest, UserBlocks
|
||||
from .shelf import Shelf, ShelfBook
|
||||
from .status import Status, GeneratedNote, Review, Comment, Quotation
|
||||
from .status import Favorite, Boost, Notification, ReadThrough
|
||||
from .status import Attachment, Favorite, Boost, Notification, ReadThrough
|
||||
from .tag import Tag
|
||||
from .user import User
|
||||
from .federated_server import FederatedServer
|
||||
|
|
|
@ -276,10 +276,5 @@ def image_formatter(image, default_path=None):
|
|||
|
||||
|
||||
def image_attachments_formatter(images):
|
||||
''' create a list of image attachemnts '''
|
||||
if not isinstance(images, list):
|
||||
images = [images]
|
||||
attachments = []
|
||||
for image in images:
|
||||
attachments.append(image_formatter(image))
|
||||
return attachments
|
||||
''' create a list of image attachments '''
|
||||
return [image_formatter(i) for i in images]
|
||||
|
|
|
@ -100,7 +100,9 @@ class Book(ActivitypubMixin, BookWyrmModel):
|
|||
ActivityMapping('editions', 'editions_path'),
|
||||
ActivityMapping(
|
||||
'attachment', 'cover',
|
||||
image_attachments_formatter
|
||||
# this expects an iterable and the field is just an image
|
||||
lambda x: image_attachments_formatter([x]),
|
||||
lambda x: activitypub.image_attachments_formatter(x)[0]
|
||||
),
|
||||
]
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from model_utils.managers import InheritanceManager
|
|||
from bookwyrm import activitypub
|
||||
from .base_model import ActivitypubMixin, OrderedCollectionPageMixin
|
||||
from .base_model import ActivityMapping, BookWyrmModel, PrivacyLevels
|
||||
from .base_model import tag_formatter
|
||||
from .base_model import tag_formatter, image_attachments_formatter
|
||||
|
||||
|
||||
class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||
|
@ -80,13 +80,18 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
ActivityMapping(
|
||||
'tag', 'mention_books',
|
||||
lambda x: tag_formatter(x, 'title', 'Book'),
|
||||
activitypub.tag_formatter
|
||||
lambda x: activitypub.tag_formatter(x, 'Book')
|
||||
),
|
||||
ActivityMapping(
|
||||
'tag', 'mention_users',
|
||||
lambda x: tag_formatter(x, 'username', 'Mention'),
|
||||
activitypub.tag_formatter
|
||||
lambda x: activitypub.tag_formatter(x, 'Mention')
|
||||
),
|
||||
ActivityMapping(
|
||||
'attachment', 'attachments',
|
||||
lambda x: image_attachments_formatter(x.all()),
|
||||
activitypub.image_attachments_formatter
|
||||
)
|
||||
]
|
||||
|
||||
# serializing to bookwyrm expanded activitypub
|
||||
|
@ -140,9 +145,10 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
|
||||
def save(self, *args, **kwargs):
|
||||
''' update user active time '''
|
||||
if self.user.local:
|
||||
self.user.last_active_date = timezone.now()
|
||||
self.user.save()
|
||||
super().save(*args, **kwargs)
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class Attachment(BookWyrmModel):
|
||||
|
@ -150,7 +156,7 @@ class Attachment(BookWyrmModel):
|
|||
status = models.ForeignKey(
|
||||
'Status',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='items'
|
||||
related_name='attachments'
|
||||
)
|
||||
image = models.ImageField(upload_to='status/', null=True, blank=True)
|
||||
|
||||
|
|
Loading…
Reference in a new issue