kopia lustrzana https://gitlab.com/marnanel/chapeau
Removing d_k/types.py and doing the whole thing via polymorphic models.
Model names are their ActivityPub types. As a result, Thing is renamed to Object.2019-08-17
rodzic
6c3e8edc55
commit
31c1eb6fd5
|
@ -2,24 +2,24 @@ from django.contrib import admin
|
|||
from polymorphic.admin import *
|
||||
from django_kepi.models import *
|
||||
|
||||
class ThingChildAdmin(PolymorphicChildModelAdmin):
|
||||
base_model = Thing
|
||||
class ObjectChildAdmin(PolymorphicChildModelAdmin):
|
||||
base_model = Object
|
||||
|
||||
@admin.register(Actor)
|
||||
class ActorChildAdmin(ThingChildAdmin):
|
||||
class ActorChildAdmin(ObjectChildAdmin):
|
||||
base_model = Actor
|
||||
|
||||
@admin.register(Item)
|
||||
class ItemChildAdmin(ThingChildAdmin):
|
||||
class ItemChildAdmin(ObjectChildAdmin):
|
||||
base_model = Item
|
||||
|
||||
@admin.register(Activity)
|
||||
class ActivityChildAdmin(ThingChildAdmin):
|
||||
class ActivityChildAdmin(ObjectChildAdmin):
|
||||
base_model = Activity
|
||||
|
||||
@admin.register(Thing)
|
||||
class ThingParentAdmin(PolymorphicParentModelAdmin):
|
||||
base_model = Thing
|
||||
@admin.register(Object)
|
||||
class ObjectParentAdmin(PolymorphicParentModelAdmin):
|
||||
base_model = Object
|
||||
child_models = (
|
||||
Actor,
|
||||
Item,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import django_kepi.types as types
|
||||
from django_kepi.models import *
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(name='django_kepi')
|
||||
|
@ -19,7 +19,7 @@ def create(
|
|||
value, is_local_user, run_side_effects)
|
||||
|
||||
if value is None:
|
||||
logger.warn(" -- it's ludicrous to create an object with no value")
|
||||
logger.warn(" -- it's ludicrous to create an Object with no value")
|
||||
return None
|
||||
|
||||
# Remove the "f_" prefix, which exists so that we can write
|
||||
|
@ -33,40 +33,28 @@ def create(
|
|||
|
||||
for k,v in value.copy().items():
|
||||
if not isinstance(k, str):
|
||||
logger.warn('Things can only have keys which are strings: %s',
|
||||
logger.warn('Objects can only have keys which are strings: %s',
|
||||
str(k))
|
||||
continue
|
||||
|
||||
if 'type' not in value:
|
||||
logger.warn("Things must have a type; dropping message")
|
||||
logger.warn("Objects must have a type; dropping message")
|
||||
return None
|
||||
|
||||
value['type'] = value['type'].title()
|
||||
|
||||
if 'id' in value:
|
||||
if is_local_user:
|
||||
logger.warn('Removing "id" field at Thing creation')
|
||||
logger.warn('Removing "id" field at local Object creation')
|
||||
del value['id']
|
||||
else:
|
||||
if not is_local_user:
|
||||
logger.warn("Remote things must have an id; dropping message")
|
||||
logger.warn("Remote Objects must have an id; dropping message")
|
||||
return None
|
||||
|
||||
try:
|
||||
type_spec = types.ACTIVITYPUB_TYPES[value['type']]
|
||||
except KeyError:
|
||||
logger.info('Unknown thing type: %s; dropping message',
|
||||
value['type'])
|
||||
return None
|
||||
|
||||
if 'class' not in type_spec:
|
||||
logger.info('Type %s can\'t be instantiated',
|
||||
value['type'])
|
||||
return None
|
||||
|
||||
try:
|
||||
import django_kepi.models as kepi_models
|
||||
cls = getattr(locals()['kepi_models'], type_spec['class'])
|
||||
cls = getattr(locals()['kepi_models'], value['type'])
|
||||
except KeyError:
|
||||
# shouldn't happen!
|
||||
logger.warn("The class '%s' wasn't exported properly",
|
||||
|
@ -74,11 +62,7 @@ def create(
|
|||
return None
|
||||
|
||||
logger.debug('Class for %s is %s', value['type'], cls)
|
||||
|
||||
########################
|
||||
|
||||
# XXX Check what fields we need, based on type_spec.
|
||||
# XXX implement this.
|
||||
del value['type']
|
||||
|
||||
########################
|
||||
|
||||
|
|
|
@ -278,8 +278,8 @@ def deliver(
|
|||
incoming = False,
|
||||
):
|
||||
try:
|
||||
activity = django_kepi.models.Thing.objects.get(number=activity_id)
|
||||
except django_kepi.models.Thing.DoesNotExist:
|
||||
activity = django_kepi.models.Object.objects.get(number=activity_id)
|
||||
except django_kepi.models.Object.DoesNotExist:
|
||||
logger.warn("Can't deliver activity %s because it doesn't exist",
|
||||
activity_id)
|
||||
return None
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
import logging
|
||||
from django.conf import settings
|
||||
import datetime
|
||||
|
||||
logger = logging.getLogger(name='django_kepi')
|
||||
|
||||
def _embellish_Note(thing, user=None):
|
||||
|
||||
if 'summary' not in thing:
|
||||
thing['summary'] = None
|
||||
if 'sensitive' not in thing:
|
||||
thing['sensitive'] = False
|
||||
if 'attachment' not in thing:
|
||||
thing['attachment'] = []
|
||||
if 'tag' not in thing:
|
||||
thing['tag'] = []
|
||||
if 'to' not in thing:
|
||||
thing['to'] = ['https://www.w3.org/ns/activitystreams#Public']
|
||||
if 'cc' not in thing:
|
||||
thing['cc'] = [user.activity_followers]
|
||||
if 'attributedTo' not in thing:
|
||||
thing['attributedTo'] = user.activity_id
|
||||
|
||||
## Conversation structure
|
||||
|
||||
if 'inReplyTo' not in thing:
|
||||
thing['inReplyTo'] = None
|
||||
|
||||
# XXX Not sure about the 'conversation' tag.
|
||||
# See https://github.com/tootsuite/mastodon/issues/4213 .
|
||||
|
||||
## Content map
|
||||
|
||||
if 'contentMap' not in thing and 'content' in thing:
|
||||
thing['contentMap'] = {
|
||||
settings.LANGUAGE_CODE: thing['content'],
|
||||
}
|
||||
elif 'content' not in thing and 'contentMap' in thing:
|
||||
# just pick one
|
||||
thing['content'] = thing['contentMap'].values()[0]
|
||||
|
||||
## Atom feeds
|
||||
|
||||
if 'atomUri' not in thing:
|
||||
thing['atomUri'] = thing['url']
|
||||
if 'inReplyToUri' not in thing:
|
||||
thing['inReplyToAtomUri'] = thing['inReplyTo']
|
||||
|
||||
## All done
|
||||
|
||||
return thing
|
||||
|
||||
def embellish(thing, user=None):
|
||||
|
||||
if 'type' not in thing:
|
||||
logger.debug('embellish: object does not contain a type: %s',
|
||||
str(thing))
|
||||
raise ValueError('object does not contain a type!')
|
||||
|
||||
f_type = thing['type']
|
||||
logger.debug('embellish: received thing of type %s', f_type)
|
||||
|
||||
###### general embellishments
|
||||
|
||||
if 'id' not in thing:
|
||||
logger.debug('embellish: object does not contain a type: %s',
|
||||
str(thing))
|
||||
raise ValueError('object does not contain an id!')
|
||||
|
||||
if 'url' not in thing:
|
||||
thing['url'] = thing['id']
|
||||
|
||||
if 'published' not in thing:
|
||||
thing['published'] = datetime.datetime.now().isoformat(
|
||||
timespec='seconds',
|
||||
)+'Z'
|
||||
|
||||
###### special embellishments per "type"
|
||||
|
||||
if f_type=='Note':
|
||||
thing = _embellish_Note(thing, user)
|
||||
else:
|
||||
logger.warn('don\'t know how to embellish things of type %s',
|
||||
f_type)
|
||||
|
||||
return thing
|
|
@ -74,7 +74,7 @@ def find_local(path,
|
|||
def find_remote(url,
|
||||
do_not_fetch=False):
|
||||
|
||||
from django_kepi.models.thing import Thing
|
||||
from django_kepi.models.thing import Object
|
||||
|
||||
logger.debug('%s: find remote', url)
|
||||
|
||||
|
@ -89,14 +89,14 @@ def find_remote(url,
|
|||
# We fetched it in the past.
|
||||
|
||||
try:
|
||||
result = Thing.objects.get(
|
||||
result = Object.objects.get(
|
||||
remote_url = url,
|
||||
)
|
||||
logger.debug('%s: already fetched, and it\'s %s',
|
||||
url, result)
|
||||
|
||||
return result
|
||||
except Thing.DoesNotExist:
|
||||
except Object.DoesNotExist:
|
||||
logger.debug('%s: we already know it wasn\'t there',
|
||||
url)
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class Command(BaseCommand):
|
|||
# This can certainly be optimised a lot
|
||||
|
||||
count = 0
|
||||
for thing in django_kepi.models.Thing.objects.all():
|
||||
for thing in django_kepi.models.Object.objects.all():
|
||||
|
||||
usable = True
|
||||
for f,v in filters:
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-02 15:53
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CachedRemoteText',
|
||||
fields=[
|
||||
('address', models.URLField(primary_key=True, serialize=False)),
|
||||
('content', models.TextField(default=None, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Following',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('follower', models.URLField(max_length=255)),
|
||||
('following', models.URLField(max_length=255)),
|
||||
('pending', models.BooleanField(default=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='IncomingMessage',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('received_date', models.DateTimeField(auto_now_add=True)),
|
||||
('content_type', models.CharField(default='', max_length=255)),
|
||||
('date', models.CharField(default='', max_length=255)),
|
||||
('digest', models.CharField(default='', max_length=255)),
|
||||
('host', models.CharField(default='', max_length=255)),
|
||||
('path', models.CharField(default='', max_length=255)),
|
||||
('signature', models.CharField(default='', max_length=255)),
|
||||
('body', models.TextField(default='')),
|
||||
('waiting_for', models.URLField(default=None, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Thing',
|
||||
fields=[
|
||||
('number', models.CharField(default='', max_length=8, primary_key=True, serialize=False, unique=True)),
|
||||
('f_type', models.CharField(choices=[('Accept', 'Accept'), ('Add', 'Add'), ('Create', 'Create'), ('Delete', 'Delete'), ('Follow', 'Follow'), ('Like', 'Like'), ('Reject', 'Reject'), ('Remove', 'Remove'), ('Undo', 'Undo'), ('Update', 'Update')], max_length=255)),
|
||||
('remote_url', models.URLField(default=None, max_length=255, null=True, unique=True)),
|
||||
('f_actor', models.URLField(blank=True, max_length=255)),
|
||||
('f_name', models.CharField(blank=True, max_length=255)),
|
||||
('active', models.BooleanField(default=True)),
|
||||
('other_fields', models.TextField(default='')),
|
||||
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_django_kepi.thing_set+', to='contenttypes.ContentType')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Activity',
|
||||
fields=[
|
||||
('thing_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='django_kepi.Thing')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('django_kepi.thing',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Actor',
|
||||
fields=[
|
||||
('thing_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='django_kepi.Thing')),
|
||||
('privateKey', models.TextField()),
|
||||
('publicKey', models.TextField()),
|
||||
('auto_follow', models.BooleanField(default=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('django_kepi.thing',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Item',
|
||||
fields=[
|
||||
('thing_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='django_kepi.Thing')),
|
||||
('f_content', models.CharField(blank=True, max_length=255)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('django_kepi.thing',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Audience',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('field', models.PositiveSmallIntegerField(choices=[(1, 'audience'), (2, 'to'), (4, 'cc'), (114, 'bto'), (116, 'bcc')])),
|
||||
('recipient', models.CharField(max_length=255)),
|
||||
('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='django_kepi.Thing')),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-03 15:59
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Mention',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('from_status', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='django_kepi.Item')),
|
||||
('to_actor', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='django_kepi.Actor')),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -1,24 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-04 14:04
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0002_mention'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Fetch',
|
||||
fields=[
|
||||
('url', models.URLField(primary_key=True, serialize=False)),
|
||||
('date', models.DateField(default=datetime.datetime)),
|
||||
],
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='CachedRemoteText',
|
||||
),
|
||||
]
|
|
@ -1,19 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-04 14:10
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0003_auto_20190704_1404'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='fetch',
|
||||
name='date',
|
||||
field=models.DateTimeField(default=datetime.datetime),
|
||||
),
|
||||
]
|
|
@ -1,24 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-08 17:51
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0004_auto_20190704_1410'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='f_attributedTo',
|
||||
field=models.CharField(blank=True, max_length=255),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='fetch',
|
||||
name='date',
|
||||
field=models.DateTimeField(default=datetime.datetime.now),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-09 04:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0005_auto_20190708_1751'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='mention',
|
||||
name='to_actor',
|
||||
field=models.CharField(max_length=255),
|
||||
),
|
||||
]
|
|
@ -1,19 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-11 11:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0006_auto_20190709_0441'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='actor',
|
||||
name='f_preferredUsername',
|
||||
field=models.CharField(default='', max_length=255),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-11 17:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0007_actor_f_preferredusername'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='thing',
|
||||
name='f_type',
|
||||
field=models.CharField(choices=[('Accept', 'Accept'), ('Activity', 'Activity'), ('Actor', 'Actor'), ('Add', 'Add'), ('Announce', 'Announce'), ('Application', 'Application'), ('Article', 'Article'), ('Audio', 'Audio'), ('Create', 'Create'), ('Delete', 'Delete'), ('Document', 'Document'), ('Event', 'Event'), ('Follow', 'Follow'), ('Group', 'Group'), ('Image', 'Image'), ('Like', 'Like'), ('Note', 'Note'), ('Object', 'Object'), ('Organization', 'Organization'), ('Page', 'Page'), ('Person', 'Person'), ('Place', 'Place'), ('Profile', 'Profile'), ('Reject', 'Reject'), ('Relationship', 'Relationship'), ('Remove', 'Remove'), ('Service', 'Service'), ('Undo', 'Undo'), ('Update', 'Update'), ('Video', 'Video')], max_length=255),
|
||||
),
|
||||
]
|
|
@ -1,37 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-11 17:08
|
||||
|
||||
from django.db import migrations, models
|
||||
import django_kepi.models.thing
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0008_auto_20190711_1703'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='thing',
|
||||
name='f_actor',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='thing',
|
||||
name='f_name',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='thing',
|
||||
name='number',
|
||||
field=models.CharField(default=django_kepi.models.thing._new_number, max_length=8, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='thing',
|
||||
name='other_fields',
|
||||
field=models.TextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='thing',
|
||||
name='remote_url',
|
||||
field=models.URLField(blank=True, default=None, max_length=255, null=True, unique=True),
|
||||
),
|
||||
]
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-11 17:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0009_auto_20190711_1708'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='actor',
|
||||
name='privateKey',
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='actor',
|
||||
name='publicKey',
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
]
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-18 12:19
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0010_auto_20190711_1711'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='actor',
|
||||
old_name='privateKey',
|
||||
new_name='f_privateKey',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='actor',
|
||||
old_name='publicKey',
|
||||
new_name='f_publicKey',
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-18 13:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0011_auto_20190718_1219'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='incomingmessage',
|
||||
name='is_local_user',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-21 16:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0012_incomingmessage_is_local_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='thing',
|
||||
name='f_actor',
|
||||
field=models.CharField(blank=True, default=None, max_length=255, null=True),
|
||||
),
|
||||
]
|
|
@ -1,34 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-26 15:15
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0013_thing_f_actor'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Collection',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.URLField(max_length=255)),
|
||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='django_kepi.Actor')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CollectionMember',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('member', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='django_kepi.Thing')),
|
||||
('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='django_kepi.Collection')),
|
||||
],
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='collection',
|
||||
constraint=models.UniqueConstraint(fields=('owner', 'name'), name='owner and name'),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-26 16:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0014_auto_20190726_1515'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='incomingmessage',
|
||||
name='target_collection',
|
||||
field=models.CharField(default='', max_length=255),
|
||||
),
|
||||
]
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-07-30 15:29
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0015_incomingmessage_target_collection'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='incomingmessage',
|
||||
name='target_collection',
|
||||
),
|
||||
]
|
|
@ -1,31 +0,0 @@
|
|||
# Generated by Django 2.2.1 on 2019-08-05 00:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_kepi', '0016_remove_incomingmessage_target_collection'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='thing',
|
||||
name='other_fields',
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ThingField',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('field', models.CharField(max_length=255)),
|
||||
('value', models.CharField(blank=True, default=None, max_length=255, null=True)),
|
||||
('parent', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='django_kepi.Thing')),
|
||||
],
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='thingfield',
|
||||
constraint=models.UniqueConstraint(fields=('parent', 'field'), name='parent_field'),
|
||||
),
|
||||
]
|
|
@ -1,22 +1,27 @@
|
|||
from .thing import Thing, ThingField
|
||||
from .activity import Activity
|
||||
from .actor import Actor
|
||||
from .thing import Object
|
||||
from .thingfield import ThingField
|
||||
from .activity import Activity, Create, Update, Delete, Follow, Add, Remove, \
|
||||
Like, Undo, Accept, Reject, Announce
|
||||
from .actor import Actor, Application, Group, Organization, Person, Service
|
||||
from .audience import Audience, AUDIENCE_FIELD_NAMES
|
||||
from .following import Following
|
||||
from .mention import Mention
|
||||
from .item import Item
|
||||
from .item import Item, Article, Audio, Document, Event, Image, Note, Page, \
|
||||
Place, Profile, Relationship, Video
|
||||
from .collection import Collection, CollectionMember
|
||||
|
||||
__all__ = [
|
||||
'Thing',
|
||||
'Object',
|
||||
'ThingField',
|
||||
'Activity',
|
||||
'Actor',
|
||||
'Activity', 'Create', 'Update', 'Delete', 'Follow', 'Add', 'Remove', \
|
||||
'Like', 'Undo', 'Accept', 'Reject', 'Announce', 'Actor',
|
||||
'Application', 'Group', 'Organization', 'Person', 'Service',
|
||||
'Audience',
|
||||
'AUDIENCE_FIELD_NAMES',
|
||||
'Following',
|
||||
'Mention',
|
||||
'Item',
|
||||
'Item', 'Article', 'Audio', 'Document', 'Event', 'Image', 'Note', \
|
||||
'Page', 'Place', 'Profile', 'Relationship', 'Video',
|
||||
'Collection',
|
||||
'CollectionMember',
|
||||
]
|
||||
|
|
|
@ -5,7 +5,7 @@ logger = logging.getLogger(name='django_kepi')
|
|||
|
||||
######################
|
||||
|
||||
class Activity(thing.Thing):
|
||||
class Activity(thing.Object):
|
||||
|
||||
@property
|
||||
def activity_form(self):
|
||||
|
@ -38,3 +38,39 @@ class Activity(thing.Thing):
|
|||
|
||||
outbox = find_local(outbox_url,
|
||||
object_to_store=self)
|
||||
|
||||
##############################
|
||||
|
||||
class Create(Activity):
|
||||
pass
|
||||
|
||||
class Update(Activity):
|
||||
pass
|
||||
|
||||
class Delete(Activity):
|
||||
pass
|
||||
|
||||
class Follow(Activity):
|
||||
pass
|
||||
|
||||
class Add(Activity):
|
||||
pass
|
||||
|
||||
class Remove(Activity):
|
||||
pass
|
||||
|
||||
class Like(Activity):
|
||||
pass
|
||||
|
||||
class Undo(Activity):
|
||||
pass
|
||||
|
||||
class Accept(Activity):
|
||||
pass
|
||||
|
||||
class Reject(Activity):
|
||||
pass
|
||||
|
||||
class Announce(Activity):
|
||||
# aka "boost"
|
||||
pass
|
||||
|
|
|
@ -8,9 +8,9 @@ logger = logging.getLogger(name='django_kepi')
|
|||
|
||||
######################
|
||||
|
||||
class Actor(thing.Thing):
|
||||
class Actor(thing.Object):
|
||||
"""
|
||||
An Actor is a kind of Thing representing a person,
|
||||
An Actor is a kind of Object representing a person,
|
||||
an organisation, a bot, or anything else that can
|
||||
post stuff and interact with other Actors.
|
||||
|
||||
|
@ -76,3 +76,20 @@ class Actor(thing.Thing):
|
|||
return self.list_path(name)
|
||||
|
||||
return super().__getitem__(name)
|
||||
|
||||
##############################
|
||||
|
||||
class Application(Actor):
|
||||
pass
|
||||
|
||||
class Group(Actor):
|
||||
pass
|
||||
|
||||
class Organization(Actor):
|
||||
pass
|
||||
|
||||
class Person(Actor):
|
||||
pass
|
||||
|
||||
class Service(Actor):
|
||||
pass
|
||||
|
|
|
@ -28,7 +28,7 @@ AUDIENCE_FIELD_NAMES = dict([(v,f) for (f,v) in FIELD_CHOICES])
|
|||
class Audience(models.Model):
|
||||
|
||||
parent = models.ForeignKey(
|
||||
'django_kepi.Thing',
|
||||
'django_kepi.Object',
|
||||
on_delete = models.CASCADE,
|
||||
)
|
||||
|
||||
|
@ -56,7 +56,7 @@ class Audience(models.Model):
|
|||
field, value):
|
||||
|
||||
"""
|
||||
Add new Audiences for a given Thing.
|
||||
Add new Audiences for a given Object.
|
||||
"value" is a list of strings.
|
||||
|
||||
This function only adds Audiences of
|
||||
|
|
|
@ -133,7 +133,7 @@ class CollectionMember(models.Model):
|
|||
)
|
||||
|
||||
member = models.ForeignKey(
|
||||
'django_kepi.Thing',
|
||||
'django_kepi.Object',
|
||||
on_delete = models.DO_NOTHING,
|
||||
)
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ logger = logging.getLogger(name='django_kepi')
|
|||
|
||||
######################
|
||||
|
||||
class Item(thing.Thing):
|
||||
class Item(thing.Object):
|
||||
|
||||
f_content = models.CharField(
|
||||
max_length=255,
|
||||
|
@ -118,3 +118,40 @@ class Item(thing.Thing):
|
|||
def conversation(self):
|
||||
# FIXME I really don't understand conversation values
|
||||
return None
|
||||
|
||||
##############################
|
||||
|
||||
class Article(Item):
|
||||
pass
|
||||
|
||||
class Audio(Item):
|
||||
pass
|
||||
|
||||
class Document(Item):
|
||||
pass
|
||||
|
||||
class Event(Item):
|
||||
pass
|
||||
|
||||
class Image(Item):
|
||||
pass
|
||||
|
||||
class Note(Item):
|
||||
# Why isn't it a subclass of Document?
|
||||
pass
|
||||
|
||||
class Page(Item):
|
||||
# i.e. a web page
|
||||
pass
|
||||
|
||||
class Place(Item):
|
||||
pass
|
||||
|
||||
class Profile(Item):
|
||||
pass
|
||||
|
||||
class Relationship(Item):
|
||||
pass
|
||||
|
||||
class Video(Item):
|
||||
pass
|
||||
|
|
|
@ -10,22 +10,17 @@ import random
|
|||
import json
|
||||
import datetime
|
||||
import warnings
|
||||
from django_kepi.types import ACTIVITYPUB_TYPES
|
||||
|
||||
logger = logging.getLogger(name='django_kepi')
|
||||
|
||||
######################
|
||||
|
||||
ACTIVITY_TYPES = sorted(ACTIVITYPUB_TYPES.keys())
|
||||
|
||||
ACTIVITY_TYPE_CHOICES = [(x,x) for x in ACTIVITY_TYPES]
|
||||
|
||||
def _new_number():
|
||||
return '%08x' % (random.randint(0, 0xffffffff),)
|
||||
|
||||
######################
|
||||
|
||||
class Thing(PolymorphicModel):
|
||||
class Object(PolymorphicModel):
|
||||
|
||||
number = models.CharField(
|
||||
max_length=8,
|
||||
|
@ -34,11 +29,6 @@ class Thing(PolymorphicModel):
|
|||
default=_new_number,
|
||||
)
|
||||
|
||||
f_type = models.CharField(
|
||||
max_length=255,
|
||||
choices=ACTIVITY_TYPE_CHOICES,
|
||||
)
|
||||
|
||||
f_actor = models.CharField(
|
||||
max_length=255,
|
||||
default=None,
|
||||
|
@ -131,14 +121,14 @@ class Thing(PolymorphicModel):
|
|||
return result
|
||||
|
||||
@property
|
||||
def activity_type(self):
|
||||
return self.f_type
|
||||
def f_type(self):
|
||||
return self.__class__.__name__
|
||||
|
||||
@property
|
||||
def activity_form(self):
|
||||
result = {
|
||||
'id': self.url,
|
||||
'type': self.get_f_type_display(),
|
||||
'type': self.f_type,
|
||||
}
|
||||
|
||||
for name in dir(self):
|
||||
|
@ -283,7 +273,7 @@ class Thing(PolymorphicModel):
|
|||
|
||||
try:
|
||||
self.delete()
|
||||
except AssertionError:
|
||||
except:
|
||||
logger.info(' -- deletion failed, probably because of '+\
|
||||
'https://code.djangoproject.com/ticket/23076')
|
||||
|
||||
|
@ -336,8 +326,8 @@ def _normalise_type_for_thing(v):
|
|||
return v # also booleans
|
||||
elif isinstance(v, list):
|
||||
return v # and lists as well
|
||||
elif isinstance(v, Thing):
|
||||
return v.url # Things can deal with themselves
|
||||
elif isinstance(v, Object):
|
||||
return v.url # Objects can deal with themselves
|
||||
|
||||
# okay, it's something weird
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class ThingField(models.Model):
|
|||
)
|
||||
|
||||
parent = models.ForeignKey(
|
||||
'django_kepi.Thing',
|
||||
'django_kepi.Object',
|
||||
on_delete = models.DO_NOTHING,
|
||||
)
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import logging
|
|||
from django.conf import settings
|
||||
from django_kepi.find import find
|
||||
from django_kepi.delivery import deliver
|
||||
from django_kepi.types import ACTIVITYPUB_TYPES
|
||||
|
||||
logger = logging.getLogger(name='django_kepi')
|
||||
|
||||
|
@ -85,35 +84,16 @@ def reject(activity):
|
|||
|
||||
def create(activity):
|
||||
|
||||
import django_kepi.models as kepi_models
|
||||
from django_kepi.create import create as kepi_create
|
||||
|
||||
raw_material = dict([('f_'+f, v)
|
||||
for f,v in activity['object'].items()])
|
||||
|
||||
if 'f_type' not in raw_material:
|
||||
logger.warn('Attempt to use Create to create '+\
|
||||
'something without a type. '+\
|
||||
'Deleting original Create.')
|
||||
if issubclass(getattr(kepi_models,
|
||||
raw_material['f_type']),
|
||||
kepi_models.Activity):
|
||||
|
||||
return False
|
||||
|
||||
if raw_material['f_type'] not in ACTIVITYPUB_TYPES:
|
||||
logger.warn('Attempt to use Create to create '+\
|
||||
'an object of type %s, which is unknown. '+\
|
||||
'Deleting original Create.',
|
||||
raw_material['f_type'])
|
||||
|
||||
return False
|
||||
|
||||
if 'class' not in ACTIVITYPUB_TYPES[raw_material['f_type']]:
|
||||
logger.warn('Attempt to use Create to create '+\
|
||||
'an object of type %s, which is abstract. '+\
|
||||
'Deleting original Create.',
|
||||
raw_material['f_type'])
|
||||
|
||||
return False
|
||||
|
||||
if ACTIVITYPUB_TYPES[raw_material['f_type']]['class']=='Activity':
|
||||
logger.warn('Attempt to use Create to create '+\
|
||||
'an object of type %s. '+\
|
||||
'Create can only create non-activities. '+\
|
||||
|
|
|
@ -217,13 +217,13 @@ class ThingView(KepiView):
|
|||
def activity_get(self, request, *args, **kwargs):
|
||||
|
||||
try:
|
||||
logger.debug('Looking up Thing by id==%s',
|
||||
logger.debug('Looking up Object by id==%s',
|
||||
kwargs['id'])
|
||||
activity_object = Thing.objects.get(
|
||||
activity_object = Object.objects.get(
|
||||
number=kwargs['id'],
|
||||
)
|
||||
|
||||
except Thing.DoesNotExist:
|
||||
except Object.DoesNotExist:
|
||||
logger.info(' -- unknown: %s', kwargs)
|
||||
return None
|
||||
except django.core.exceptions.ValidationError:
|
||||
|
@ -325,7 +325,7 @@ class AllUsersView(KepiView):
|
|||
|
||||
logger.debug('Finding all users.')
|
||||
|
||||
return Thing.objects.filter(f_type='Person')
|
||||
return Object.objects.filter(f_type='Person')
|
||||
|
||||
def _modify_list_item(self, obj):
|
||||
return obj.activity_form
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.test import TestCase
|
||||
from django_kepi.models import Thing
|
||||
from django_kepi.models import Object
|
||||
|
||||
REMOTE_ID_1 = 'https://users.example.com/activity/1'
|
||||
|
||||
|
@ -9,12 +9,12 @@ SAMPLE_NOTE = {
|
|||
"type": "Note",
|
||||
}
|
||||
|
||||
class TestThing(TestCase):
|
||||
class TestObject(TestCase):
|
||||
|
||||
def test_bad_type(self):
|
||||
|
||||
with self.assertRaisesMessage(ValueError, "is not a thing type"):
|
||||
Thing.create(
|
||||
Object.create(
|
||||
f_id = REMOTE_ID_1,
|
||||
f_type = "Wombat",
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ class TestThing(TestCase):
|
|||
def test_remote_no_id(self):
|
||||
|
||||
with self.assertRaisesMessage(ValueError, "Remote things must have an id"):
|
||||
Thing.create(
|
||||
Object.create(
|
||||
f_type = "Create",
|
||||
f_actor = "https://example.com/user/fred",
|
||||
f_object = SAMPLE_NOTE,
|
||||
|
@ -31,27 +31,27 @@ class TestThing(TestCase):
|
|||
def test_create_create_wrong_params(self):
|
||||
|
||||
with self.assertRaisesMessage(ValueError, "Wrong parameters for thing type"):
|
||||
Thing.create(
|
||||
Object.create(
|
||||
f_id = REMOTE_ID_1,
|
||||
f_type = "Create",
|
||||
)
|
||||
|
||||
with self.assertRaisesMessage(ValueError, "Wrong parameters for thing type"):
|
||||
Thing.create(
|
||||
Object.create(
|
||||
f_id = REMOTE_ID_1,
|
||||
f_actor = REMOTE_FRED,
|
||||
f_type = "Create",
|
||||
)
|
||||
|
||||
with self.assertRaisesMessage(ValueError, "Wrong parameters for thing type"):
|
||||
Thing.create(
|
||||
Object.create(
|
||||
f_id = REMOTE_ID_1,
|
||||
f_target = REMOTE_FRED,
|
||||
f_type = "Create",
|
||||
)
|
||||
|
||||
def test_create_create(self):
|
||||
Thing.create(
|
||||
Object.create(
|
||||
f_id = REMOTE_ID_1,
|
||||
f_type = "Create",
|
||||
f_actor = REMOTE_FRED,
|
||||
|
@ -59,6 +59,6 @@ class TestThing(TestCase):
|
|||
)
|
||||
|
||||
self.assertEqual(
|
||||
Thing.objects.filter(remote_url=REMOTE_ID_1).count(),
|
||||
Object.objects.filter(remote_url=REMOTE_ID_1).count(),
|
||||
1,
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import TestCase, Client
|
||||
from django_kepi.delivery import deliver
|
||||
from django_kepi.models import Thing
|
||||
from django_kepi.models import Object
|
||||
import django_kepi.views
|
||||
from unittest.mock import Mock, patch
|
||||
from . import *
|
||||
|
@ -22,9 +22,9 @@ REMOTE_PATH_NAMES = {
|
|||
|
||||
def _message_became_activity(url=ACTIVITY_ID):
|
||||
try:
|
||||
result = Thing.objects.get(remote_url=url)
|
||||
result = Object.objects.get(remote_url=url)
|
||||
return True
|
||||
except Thing.DoesNotExist:
|
||||
except Object.DoesNotExist:
|
||||
return False
|
||||
|
||||
class TestDeliverTasks(TestCase):
|
||||
|
@ -36,7 +36,7 @@ class TestDeliverTasks(TestCase):
|
|||
remote_user_endpoints,
|
||||
):
|
||||
|
||||
a = Thing.create(**activity_fields)
|
||||
a = Object.create(**activity_fields)
|
||||
a.save()
|
||||
|
||||
for who, what in remote_user_details.items():
|
||||
|
@ -211,7 +211,7 @@ class TestDelivery(TestCase):
|
|||
self._set_up_remote_request_mocks()
|
||||
self._set_up_local_user_mocks()
|
||||
|
||||
like = Thing.create(
|
||||
like = Object.create(
|
||||
f_type = 'Like',
|
||||
f_actor = LOCAL_ALICE,
|
||||
f_object = REMOTE_FRED,
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
from django.test import TestCase
|
||||
from unittest import skip
|
||||
from django_kepi.embellish import embellish
|
||||
from . import *
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(name='django_kepi')
|
||||
|
||||
@skip("Decide whether we're keeping this")
|
||||
class TestEmbellish(TestCase):
|
||||
def test_embellish_note(self):
|
||||
|
||||
SOURCE = {
|
||||
'id': 'https://example.com/users/fred/status/1234',
|
||||
'type': 'Note',
|
||||
'content': 'Hello world',
|
||||
}
|
||||
|
||||
EXPECTING = {
|
||||
'id': 'https://example.com/users/fred/status/1234',
|
||||
'url': 'https://example.com/users/fred/status/1234',
|
||||
'atomUri': 'https://example.com/users/fred/status/1234',
|
||||
'type': 'Note',
|
||||
'content': 'Hello world',
|
||||
'summary': None,
|
||||
"attributedTo": "https://example.com/users/fred",
|
||||
"to":["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc":["https://example.com/users/fred/followers"],
|
||||
"sensitive": False,
|
||||
"inReplyTo": None,
|
||||
"inReplyToAtomUri": None,
|
||||
"contentMap":{"en-us": 'Hello world',},
|
||||
"attachment":[],
|
||||
"tag":[],
|
||||
}
|
||||
# (plus "published")
|
||||
# (plus "conversation", wtf?)
|
||||
|
||||
user = create_local_person(
|
||||
name = 'Fred',
|
||||
url = 'https://example.com/users/fred',
|
||||
)
|
||||
|
||||
result = embellish(SOURCE,
|
||||
user=user)
|
||||
|
||||
self.maxDiff = None
|
||||
self.assertDictContainsSubset(
|
||||
EXPECTING,
|
||||
result,
|
||||
)
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
from django.test import TestCase
|
||||
from django_kepi.find import find
|
||||
from django_kepi.models import Thing
|
||||
from django_kepi.create import create
|
||||
from django.conf import settings
|
||||
from . import *
|
||||
|
|
|
@ -5,7 +5,6 @@ from django_kepi.create import create
|
|||
from django_kepi.models.audience import Audience, AUDIENCE_FIELD_NAMES
|
||||
from django_kepi.models.mention import Mention
|
||||
from django_kepi.models.item import Item
|
||||
from django_kepi.models.thing import Thing
|
||||
from django_kepi.models.following import Following
|
||||
from django_kepi.models.activity import Activity
|
||||
from django.test import Client
|
||||
|
|
|
@ -5,7 +5,7 @@ from django_kepi.create import create
|
|||
from django_kepi.models.audience import Audience, AUDIENCE_FIELD_NAMES
|
||||
from django_kepi.models.mention import Mention
|
||||
from django_kepi.models.item import Item
|
||||
from django_kepi.models.thing import Thing
|
||||
from django_kepi.models.thing import Object
|
||||
from django_kepi.models.activity import Activity
|
||||
from django.test import Client
|
||||
from urllib.parse import urlparse
|
||||
|
@ -231,13 +231,13 @@ class TestOutbox(TestCase):
|
|||
@httpretty.activate
|
||||
def test_unwrapped_object(self):
|
||||
|
||||
items_before = list(Thing.objects.all())
|
||||
items_before = list(Object.objects.all())
|
||||
|
||||
self._send(
|
||||
content = OBJECT_FORM,
|
||||
)
|
||||
|
||||
items_after = list(Thing.objects.all())
|
||||
items_after = list(Object.objects.all())
|
||||
|
||||
# This should have created two objects:
|
||||
# the Note we sent, and an implict Create.
|
||||
|
@ -279,7 +279,7 @@ class TestOutbox(TestCase):
|
|||
)
|
||||
|
||||
self.assertEqual(
|
||||
len(Thing.objects.filter(f_actor=json.dumps(ALICE_ID))),
|
||||
len(Object.objects.filter(f_actor=json.dumps(ALICE_ID))),
|
||||
1)
|
||||
|
||||
# TODO When Actors have liked() and Things have likes(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import TestCase, Client
|
||||
from django_kepi.validation import IncomingMessage, validate
|
||||
from django_kepi.models import Thing
|
||||
from django_kepi.models import Object
|
||||
from unittest import skip
|
||||
from unittest.mock import Mock, patch
|
||||
from . import *
|
||||
|
@ -52,9 +52,9 @@ MESSAGE_CONTEXT = ["https://www.w3.org/ns/activitystreams",
|
|||
|
||||
def _message_became_activity(url=ACTIVITY_ID):
|
||||
try:
|
||||
result = Thing.objects.get(remote_url=url)
|
||||
result = Object.objects.get(remote_url=url)
|
||||
return True
|
||||
except Thing.DoesNotExist:
|
||||
except Object.DoesNotExist:
|
||||
return False
|
||||
|
||||
class ResultWrapper(object):
|
||||
|
|
Ładowanie…
Reference in New Issue