kopia lustrzana https://gitlab.com/marnanel/chapeau
Partial checkin. Trying to generate the Create activity automatically when a Note (etc) is saved.
rodzic
488770e5ba
commit
e73a34f10b
|
@ -170,7 +170,8 @@ class Activity(models.Model):
|
|||
def activity_type(self):
|
||||
return self.f_type
|
||||
|
||||
def activity_form(self, *args, **kwargs):
|
||||
@property
|
||||
def activity_form(self):
|
||||
result = {
|
||||
'id': self.identifier,
|
||||
'type': self.get_f_type_display(),
|
||||
|
@ -287,11 +288,17 @@ class Activity(models.Model):
|
|||
raise ValueError("Remote activities must have an id")
|
||||
|
||||
fields = {
|
||||
'identifier': value.get('id', None),
|
||||
'f_type': value['type'],
|
||||
'active': True,
|
||||
}
|
||||
|
||||
for f,v in value.items():
|
||||
fields['f_'+f] = v
|
||||
|
||||
# XXX nasty temporary hack which will go away soon
|
||||
for name in ['f_to', 'f_cc']:
|
||||
if name in fields:
|
||||
del fields[name]
|
||||
|
||||
try:
|
||||
need_actor, need_object, need_target = cls.TYPES[value['type']]
|
||||
except KeyError:
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.1.5 on 2019-04-23 13:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0011_auto_20190418_1328'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ActivityModel',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -3,7 +3,54 @@ from django_kepi import object_type_registry
|
|||
from django_kepi.cache_model import Cache
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django_kepi.models import Activity
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(name='django_kepi')
|
||||
|
||||
#######################
|
||||
|
||||
class ActivityModel(models.Model):
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
we_are_new = self.pk is None
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
if we_are_new:
|
||||
logger.debug('New activity: %s',
|
||||
str(self.activity_form))
|
||||
logger.debug('We must create a Create wrapper for it.')
|
||||
|
||||
wrapper = Activity.create({
|
||||
'type': 'Create',
|
||||
'actor': self.activity_actor,
|
||||
'to': self.activity_to,
|
||||
'cc': self.activity_cc,
|
||||
'object': self.activity_id,
|
||||
})
|
||||
|
||||
wrapper.save()
|
||||
logger.debug('Created wrapper %s',
|
||||
str(wrapper.activity_form))
|
||||
|
||||
# XXX We copy "to" and "cc" per
|
||||
# https://www.w3.org/TR/activitypub/#object-without-create
|
||||
# which also requires us to copy
|
||||
# the two blind versions, and "audience".
|
||||
# We don't support those (atm), but
|
||||
# we should probably copy them anyway.
|
||||
|
||||
@property
|
||||
def activity_to(self):
|
||||
# FIXME
|
||||
return ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
@property
|
||||
def activity_cc(self):
|
||||
# FIXME
|
||||
return ["https://marnanel.org/users/marnanel/followers"]
|
||||
|
||||
#######################
|
||||
|
||||
class SomethingManager(models.Manager):
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
from django.test import TestCase
|
||||
from django_kepi.models import Activity
|
||||
from things_for_testing.models import ThingArticle, ThingUser
|
||||
from things_for_testing.models import ThingNote, ThingUser
|
||||
|
||||
FRED_URL = 'https://users.example.com/user/fred'
|
||||
|
||||
class TestActivity(TestCase):
|
||||
|
||||
def test_parameters(self):
|
||||
|
||||
return # XXX
|
||||
|
||||
with self.assertRaisesMessage(ValueError, "is not an Activity type"):
|
||||
Activity.create({
|
||||
"id": "https://example.com/id/1",
|
||||
|
@ -17,7 +21,7 @@ class TestActivity(TestCase):
|
|||
"type": "Create",
|
||||
"actor": "https://example.com/user/fred",
|
||||
"object": {
|
||||
"type": "Article",
|
||||
"type": "Note",
|
||||
},
|
||||
},
|
||||
sender="https://remote.example.com")
|
||||
|
@ -30,3 +34,11 @@ class TestActivity(TestCase):
|
|||
|
||||
fred = ThingUser(name="fred")
|
||||
fred.save()
|
||||
|
||||
def test_note_creation(self):
|
||||
|
||||
note = ThingNote(
|
||||
title='Hello world',
|
||||
owner=FRED_URL,
|
||||
)
|
||||
note.save()
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 2.1.5 on 2019-04-23 13:08
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('things_for_testing', '0005_auto_20181029_0852'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name='ThingArticle',
|
||||
new_name='ThingNote',
|
||||
),
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 2.1.5 on 2019-04-23 13:33
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0012_activitymodel'),
|
||||
('things_for_testing', '0006_auto_20190423_1308'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='thingnote',
|
||||
name='id',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='thingnote',
|
||||
name='activitymodel_ptr',
|
||||
field=models.OneToOneField(auto_created=True, default=0, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='django_kepi.ActivityModel'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.1.5 on 2019-04-23 14:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('things_for_testing', '0007_auto_20190423_1333'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='thingnote',
|
||||
name='owner',
|
||||
field=models.URLField(default=0, max_length=256),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -32,10 +32,6 @@ class ThingUser(models.Model):
|
|||
'favourite_colour': self.favourite_colour,
|
||||
}
|
||||
|
||||
@property
|
||||
def implements_activity_type(self):
|
||||
return 'Person'
|
||||
|
||||
@property
|
||||
def activity_id(self):
|
||||
return self.url
|
||||
|
@ -60,27 +56,33 @@ class ThingUser(models.Model):
|
|||
result.save()
|
||||
return result
|
||||
|
||||
@implements_activity_type('Article')
|
||||
class ThingArticle(models.Model):
|
||||
@implements_activity_type('Note')
|
||||
class ThingNote(kepi_models.ActivityModel):
|
||||
|
||||
title = models.CharField(max_length=256)
|
||||
ftype = 'Article'
|
||||
ftype = 'Note'
|
||||
|
||||
remote_url = models.URLField(max_length=256,
|
||||
null=True, default=None)
|
||||
|
||||
owner = models.URLField(max_length=256)
|
||||
|
||||
@property
|
||||
def activity_actor(self):
|
||||
return self.owner
|
||||
|
||||
@property
|
||||
def activity_form(self):
|
||||
return {
|
||||
'id': self.activity_id,
|
||||
'type': 'Article',
|
||||
'type': 'Note',
|
||||
'title': self.title,
|
||||
}
|
||||
|
||||
@property
|
||||
def activity_id(self):
|
||||
return 'https://articles.example.com/{}'.format(
|
||||
self.title,
|
||||
self.title.replace(' ','-').lower(),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
@ -100,4 +102,3 @@ class ThingArticle(models.Model):
|
|||
)
|
||||
result.save()
|
||||
return result
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue