forked from mirrors/bookwyrm
Merge branch 'stop-storing-ap-json'
This commit is contained in:
commit
6c69c010a6
10 changed files with 138 additions and 102 deletions
|
@ -3,5 +3,5 @@ from .actor import get_actor
|
||||||
from .collection import get_outbox, get_outbox_page, get_add, get_remove, \
|
from .collection import get_outbox, get_outbox_page, get_add, get_remove, \
|
||||||
get_following, get_followers
|
get_following, get_followers
|
||||||
from .create import get_create
|
from .create import get_create
|
||||||
from .follow import get_follow_request, get_accept
|
from .follow import get_follow_request, get_unfollow, get_accept
|
||||||
from .status import get_review, get_review_article, get_status, get_replies
|
from .status import get_review, get_review_article, get_status, get_replies
|
||||||
|
|
|
@ -16,6 +16,21 @@ def get_follow_request(user, to_follow):
|
||||||
'object': to_follow.actor,
|
'object': to_follow.actor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_unfollow(relationship):
|
||||||
|
''' undo that precious bond of friendship '''
|
||||||
|
return {
|
||||||
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
|
'id': '%s/undo' % relationship.absolute_id,
|
||||||
|
'type': 'Undo',
|
||||||
|
'actor': relationship.user_subject.actor,
|
||||||
|
'object': {
|
||||||
|
'id': relationship.relationship_id,
|
||||||
|
'type': 'Follow',
|
||||||
|
'actor': relationship.user_subject.actor,
|
||||||
|
'object': relationship.user_object.actor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_accept(user, request_activity):
|
def get_accept(user, request_activity):
|
||||||
''' accept a follow request '''
|
''' accept a follow request '''
|
||||||
|
|
|
@ -37,6 +37,9 @@ def shared_inbox(request):
|
||||||
if activity['type'] == 'Follow':
|
if activity['type'] == 'Follow':
|
||||||
response = handle_incoming_follow(activity)
|
response = handle_incoming_follow(activity)
|
||||||
|
|
||||||
|
elif activity['type'] == 'Undo':
|
||||||
|
response = handle_incoming_undo(activity)
|
||||||
|
|
||||||
elif activity['type'] == 'Create':
|
elif activity['type'] == 'Create':
|
||||||
response = handle_incoming_create(activity)
|
response = handle_incoming_create(activity)
|
||||||
|
|
||||||
|
@ -183,10 +186,32 @@ def handle_incoming_follow(activity):
|
||||||
# figure out who they are
|
# figure out who they are
|
||||||
user = get_or_create_remote_user(activity['actor'])
|
user = get_or_create_remote_user(activity['actor'])
|
||||||
# TODO: allow users to manually approve requests
|
# TODO: allow users to manually approve requests
|
||||||
|
models.UserRelationship.objects.create(
|
||||||
|
user_subject=to_follow,
|
||||||
|
user_object=user,
|
||||||
|
status='follow_request',
|
||||||
|
relationship_id=activity['id']
|
||||||
|
)
|
||||||
outgoing.handle_outgoing_accept(user, to_follow, activity)
|
outgoing.handle_outgoing_accept(user, to_follow, activity)
|
||||||
return HttpResponse()
|
return HttpResponse()
|
||||||
|
|
||||||
|
|
||||||
|
def handle_incoming_undo(activity):
|
||||||
|
''' unfollow a local user '''
|
||||||
|
obj = activity['object']
|
||||||
|
if not obj['type'] == 'Follow':
|
||||||
|
#idk how to undo other things
|
||||||
|
return HttpResponseNotFound()
|
||||||
|
try:
|
||||||
|
requester = get_or_create_remote_user(obj['actor'])
|
||||||
|
to_unfollow = models.User.objects.get(actor=obj['object'])
|
||||||
|
except models.User.DoesNotExist:
|
||||||
|
return HttpResponseNotFound()
|
||||||
|
|
||||||
|
to_unfollow.followers.remove(requester)
|
||||||
|
return HttpResponse()
|
||||||
|
|
||||||
|
|
||||||
def handle_incoming_follow_accept(activity):
|
def handle_incoming_follow_accept(activity):
|
||||||
''' hurray, someone remote accepted a follow request '''
|
''' hurray, someone remote accepted a follow request '''
|
||||||
# figure out who they want to follow
|
# figure out who they want to follow
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 3.0.3 on 2020-02-17 02:39
|
# Generated by Django 3.0.3 on 2020-02-19 06:43
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
|
@ -41,11 +41,10 @@ class Migration(migrations.Migration):
|
||||||
('outbox', models.CharField(max_length=255, unique=True)),
|
('outbox', models.CharField(max_length=255, unique=True)),
|
||||||
('summary', models.TextField(blank=True, null=True)),
|
('summary', models.TextField(blank=True, null=True)),
|
||||||
('local', models.BooleanField(default=True)),
|
('local', models.BooleanField(default=True)),
|
||||||
|
('fedireads_user', models.BooleanField(default=True)),
|
||||||
('localname', models.CharField(max_length=255, null=True, unique=True)),
|
('localname', models.CharField(max_length=255, null=True, unique=True)),
|
||||||
('name', models.CharField(blank=True, max_length=100, null=True)),
|
('name', models.CharField(blank=True, max_length=100, null=True)),
|
||||||
('avatar', models.ImageField(blank=True, null=True, upload_to='avatars/')),
|
('avatar', models.ImageField(blank=True, null=True, upload_to='avatars/')),
|
||||||
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_date', models.DateTimeField(auto_now=True)),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'user',
|
'verbose_name': 'user',
|
||||||
|
@ -60,66 +59,96 @@ class Migration(migrations.Migration):
|
||||||
name='Author',
|
name='Author',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField(blank=True, null=True)),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('openlibrary_key', models.CharField(max_length=255)),
|
('openlibrary_key', models.CharField(max_length=255)),
|
||||||
('data', fedireads.utils.fields.JSONField()),
|
('data', fedireads.utils.fields.JSONField()),
|
||||||
('added_date', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_date', models.DateTimeField(auto_now=True)),
|
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Book',
|
name='Book',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField(blank=True, null=True)),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('openlibrary_key', models.CharField(max_length=255, unique=True)),
|
('openlibrary_key', models.CharField(max_length=255, unique=True)),
|
||||||
('data', fedireads.utils.fields.JSONField()),
|
('data', fedireads.utils.fields.JSONField()),
|
||||||
('cover', models.ImageField(blank=True, null=True, upload_to='covers/')),
|
('cover', models.ImageField(blank=True, null=True, upload_to='covers/')),
|
||||||
('added_date', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_date', models.DateTimeField(auto_now=True)),
|
|
||||||
('added_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
('added_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||||
('authors', models.ManyToManyField(to='fedireads.Author')),
|
('authors', models.ManyToManyField(to='fedireads.Author')),
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='FederatedServer',
|
name='FederatedServer',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField(blank=True, null=True)),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('server_name', models.CharField(max_length=255, unique=True)),
|
('server_name', models.CharField(max_length=255, unique=True)),
|
||||||
('status', models.CharField(default='federated', max_length=255)),
|
('status', models.CharField(default='federated', max_length=255)),
|
||||||
('application_type', models.CharField(max_length=255, null=True)),
|
('application_type', models.CharField(max_length=255, null=True)),
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Shelf',
|
name='Shelf',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField(blank=True, null=True)),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('name', models.CharField(max_length=100)),
|
('name', models.CharField(max_length=100)),
|
||||||
('identifier', models.CharField(max_length=100)),
|
('identifier', models.CharField(max_length=100)),
|
||||||
('editable', models.BooleanField(default=True)),
|
('editable', models.BooleanField(default=True)),
|
||||||
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_date', models.DateTimeField(auto_now=True)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Status',
|
name='Status',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField(blank=True, null=True)),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('status_type', models.CharField(default='Note', max_length=255)),
|
('status_type', models.CharField(default='Note', max_length=255)),
|
||||||
('activity_type', models.CharField(default='Note', max_length=255)),
|
('activity_type', models.CharField(default='Note', max_length=255)),
|
||||||
('local', models.BooleanField(default=True)),
|
('local', models.BooleanField(default=True)),
|
||||||
('privacy', models.CharField(default='public', max_length=255)),
|
('privacy', models.CharField(default='public', max_length=255)),
|
||||||
('sensitive', models.BooleanField(default=False)),
|
('sensitive', models.BooleanField(default=False)),
|
||||||
('content', models.TextField(blank=True, null=True)),
|
|
||||||
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('mention_books', models.ManyToManyField(related_name='mention_book', to='fedireads.Book')),
|
('mention_books', models.ManyToManyField(related_name='mention_book', to='fedireads.Book')),
|
||||||
('mention_users', models.ManyToManyField(related_name='mention_user', to=settings.AUTH_USER_MODEL)),
|
('mention_users', models.ManyToManyField(related_name='mention_user', to=settings.AUTH_USER_MODEL)),
|
||||||
('reply_parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='fedireads.Status')),
|
('reply_parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='fedireads.Status')),
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserRelationship',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField(blank=True, null=True)),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('status', models.CharField(default='follows', max_length=100, null=True)),
|
||||||
|
('relationship_id', models.CharField(max_length=100)),
|
||||||
|
('user_object', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='user_object', to=settings.AUTH_USER_MODEL)),
|
||||||
|
('user_subject', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='user_subject', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='ShelfBook',
|
name='ShelfBook',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField(blank=True, null=True)),
|
||||||
('created_date', models.DateTimeField(auto_now_add=True)),
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('added_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
('added_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||||
('book', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='fedireads.Book')),
|
('book', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='fedireads.Book')),
|
||||||
|
@ -152,7 +181,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='user',
|
model_name='user',
|
||||||
name='followers',
|
name='followers',
|
||||||
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
|
field=models.ManyToManyField(through='fedireads.UserRelationship', to=settings.AUTH_USER_MODEL),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='user',
|
model_name='user',
|
||||||
|
@ -176,6 +205,9 @@ class Migration(migrations.Migration):
|
||||||
('rating', models.IntegerField(default=0, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(5)])),
|
('rating', models.IntegerField(default=0, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(5)])),
|
||||||
('book', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='fedireads.Book')),
|
('book', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='fedireads.Book')),
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
bases=('fedireads.status',),
|
bases=('fedireads.status',),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
# Generated by Django 3.0.3 on 2020-02-19 01:18
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.utils.timezone
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('fedireads', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name='author',
|
|
||||||
old_name='added_date',
|
|
||||||
new_name='created_date',
|
|
||||||
),
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name='book',
|
|
||||||
old_name='added_date',
|
|
||||||
new_name='created_date',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='author',
|
|
||||||
name='updated_date',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='book',
|
|
||||||
name='updated_date',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='shelf',
|
|
||||||
name='updated_date',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='user',
|
|
||||||
name='created_date',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='user',
|
|
||||||
name='updated_date',
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='author',
|
|
||||||
name='content',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='book',
|
|
||||||
name='content',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='federatedserver',
|
|
||||||
name='content',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='federatedserver',
|
|
||||||
name='created_date',
|
|
||||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='shelf',
|
|
||||||
name='content',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='shelfbook',
|
|
||||||
name='content',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='user',
|
|
||||||
name='fedireads_user',
|
|
||||||
field=models.BooleanField(default=True),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,5 +1,5 @@
|
||||||
''' bring all the models into the app namespace '''
|
''' bring all the models into the app namespace '''
|
||||||
from .book import Shelf, ShelfBook, Book, Author
|
from .book import Shelf, ShelfBook, Book, Author
|
||||||
from .user import User, FederatedServer
|
from .user import User, UserRelationship, FederatedServer
|
||||||
from .activity import Status, Review
|
from .activity import Status, Review
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,12 @@ class User(AbstractUser):
|
||||||
# name is your display name, which you can change at will
|
# name is your display name, which you can change at will
|
||||||
name = models.CharField(max_length=100, blank=True, null=True)
|
name = models.CharField(max_length=100, blank=True, null=True)
|
||||||
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
|
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
|
||||||
followers = models.ManyToManyField('self', symmetrical=False)
|
followers = models.ManyToManyField(
|
||||||
|
'self',
|
||||||
|
symmetrical=False,
|
||||||
|
through='UserRelationship',
|
||||||
|
through_fields=('user_subject', 'user_object')
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def absolute_id(self):
|
def absolute_id(self):
|
||||||
|
@ -43,6 +48,29 @@ class User(AbstractUser):
|
||||||
return 'https://%s/%s/%s' % (DOMAIN, model_name, self.localname)
|
return 'https://%s/%s/%s' % (DOMAIN, model_name, self.localname)
|
||||||
|
|
||||||
|
|
||||||
|
class UserRelationship(FedireadsModel):
|
||||||
|
''' many-to-many through table for followers '''
|
||||||
|
user_subject = models.ForeignKey(
|
||||||
|
'User',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
related_name='user_subject'
|
||||||
|
)
|
||||||
|
user_object = models.ForeignKey(
|
||||||
|
'User',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
related_name='user_object'
|
||||||
|
)
|
||||||
|
# follow or follow_request for pending TODO: blocking?
|
||||||
|
status = models.CharField(max_length=100, default='follows', null=True)
|
||||||
|
relationship_id = models.CharField(max_length=100)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def absolute_id(self):
|
||||||
|
''' use shelf identifier as absolute id '''
|
||||||
|
base_path = self.user_subject.absolute_id
|
||||||
|
return '%s#%s/%d' % (base_path, self.status, self.id)
|
||||||
|
|
||||||
|
|
||||||
class FederatedServer(FedireadsModel):
|
class FederatedServer(FedireadsModel):
|
||||||
''' store which server's we federate with '''
|
''' store which server's we federate with '''
|
||||||
server_name = models.CharField(max_length=255, unique=True)
|
server_name = models.CharField(max_length=255, unique=True)
|
||||||
|
|
|
@ -77,9 +77,26 @@ def handle_outgoing_follow(user, to_follow):
|
||||||
raise(error['error'])
|
raise(error['error'])
|
||||||
|
|
||||||
|
|
||||||
|
def handle_outgoing_unfollow(user, to_unfollow):
|
||||||
|
''' someone local wants to follow someone '''
|
||||||
|
relationship = models.UserRelationship.objects.get(
|
||||||
|
user_object=user,
|
||||||
|
user_subject=to_unfollow
|
||||||
|
)
|
||||||
|
activity = activitypub.get_unfollow(relationship)
|
||||||
|
errors = broadcast(user, activity, [to_unfollow.inbox])
|
||||||
|
to_unfollow.followers.remove(user)
|
||||||
|
for error in errors:
|
||||||
|
raise(error['error'])
|
||||||
|
|
||||||
|
|
||||||
def handle_outgoing_accept(user, to_follow, request_activity):
|
def handle_outgoing_accept(user, to_follow, request_activity):
|
||||||
''' send an acceptance message to a follow request '''
|
''' send an acceptance message to a follow request '''
|
||||||
to_follow.followers.add(user)
|
relationship = models.UserRelationship.objects.get(
|
||||||
|
relationship_id=request_activity['id']
|
||||||
|
)
|
||||||
|
relationship.status = 'follow'
|
||||||
|
relationship.save()
|
||||||
activity = activitypub.get_accept(to_follow, request_activity)
|
activity = activitypub.get_accept(to_follow, request_activity)
|
||||||
recipient = get_recipients(to_follow, 'direct', direct_recipients=[user])
|
recipient = get_recipients(to_follow, 'direct', direct_recipients=[user])
|
||||||
broadcast(to_follow, activity, recipient)
|
broadcast(to_follow, activity, recipient)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<form name="logout" action="/logout/" method="post">
|
<form name="logout" action="/logout/" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
Welcome, {% include 'snippets/username.html' %}
|
Welcome, {% include 'snippets/username.html' with user=request.user %}
|
||||||
<input type="submit" value="Log out"></input>
|
<input type="submit" value="Log out"></input>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -278,11 +278,10 @@ def follow(request):
|
||||||
@login_required
|
@login_required
|
||||||
def unfollow(request):
|
def unfollow(request):
|
||||||
''' unfollow a user '''
|
''' unfollow a user '''
|
||||||
# TODO: this is not an implementation!!
|
user = request.user
|
||||||
followed = request.POST.get('user')
|
to_unfollow = models.User.objects.get(id=request.POST.get('user'))
|
||||||
followed = models.User.objects.get(id=followed)
|
outgoing.handle_outgoing_unfollow(user, to_unfollow)
|
||||||
followed.followers.remove(request.user)
|
return redirect('/user/%s' % to_unfollow.username)
|
||||||
return redirect('/user/%s' % followed.username)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
Loading…
Reference in a new issue