kopia lustrzana https://gitlab.com/marnanel/chapeau
Copied in kepi files from un_chapeau. Added requirements.txt.
rodzic
e8283890bf
commit
8011d9a833
|
@ -1,5 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class KepiConfig(AppConfig):
|
||||
name = 'kepi'
|
||||
class KepiActivityConfig(AppConfig):
|
||||
name = 'kepi_activity'
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
from rest_framework import serializers
|
||||
from un_chapeau.config import config
|
||||
|
||||
class CollectionView(object):
|
||||
|
||||
def __init__(self, user):
|
||||
self._user = user
|
||||
self._collection = self._resultsset()
|
||||
|
||||
def _resultsset(self):
|
||||
raise NotImplemented("abstract")
|
||||
|
||||
def url(self):
|
||||
raise NotImplemented("abstract")
|
||||
|
||||
def _page_url(self, page_number):
|
||||
return '{}?page={}'.format(
|
||||
self.url(),
|
||||
page_number,
|
||||
)
|
||||
|
||||
def collection_dict(self):
|
||||
result= {
|
||||
"id": self.url(),
|
||||
"type":"OrderedCollection",
|
||||
"totalItems": len(self._collection),
|
||||
}
|
||||
|
||||
if len(collection)!=0:
|
||||
result['first'] = self._page_url(1)
|
||||
|
||||
return result
|
||||
|
||||
def collection_page_dict(self, page_number):
|
||||
items_per_page = config['ITEMS_PER_PAGE']
|
||||
|
||||
start = (page_number-1)*items_per_page
|
||||
|
||||
items = self._collection[start:start+items_per_page]
|
||||
|
||||
result = {
|
||||
"id": self._page_url(page_number),
|
||||
"type":"OrderedCollectionPage",
|
||||
"totalItems": len(self._collection),
|
||||
"partOf": self.url(),
|
||||
"orderedItems": items,
|
||||
}
|
||||
|
||||
if start>0:
|
||||
result['prev'] = self._page_url(page_number-1)
|
||||
|
||||
if (start+items_per_page)<len(self._collection):
|
||||
result['next'] = self._page_url(page_number+1)
|
||||
|
||||
return result
|
||||
|
||||
#############################################
|
||||
|
||||
class Following(CollectionView):
|
||||
def _resultsset(self):
|
||||
return self._user.following()
|
||||
|
||||
class Followers(CollectionView):
|
||||
def _resultsset(self):
|
||||
return self._user.followers()
|
||||
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
from un_chapeau.config import config
|
||||
from un_chapeau.constants import ATSIGN_CONTEXT
|
||||
import trilby_api.models as trilby_models
|
||||
from rest_framework_constant.fields import ConstantField
|
||||
from rest_framework import serializers, mixins, pagination
|
||||
from rest_framework.response import Response
|
||||
|
||||
class ActivityPagination(pagination.PageNumberPagination):
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
return Response({
|
||||
# what if there's no next or prev?
|
||||
'next': self.get_next_link(),
|
||||
'prev': self.get_previous_link(),
|
||||
'totalitems': self.page.paginator.count,
|
||||
'orderedItems': data,
|
||||
# partOf ...
|
||||
# @context...
|
||||
})
|
||||
|
||||
# also, add Link header
|
||||
|
||||
class ActivitySerializer(serializers.ModelSerializer):
|
||||
|
||||
def _to_representation(self, instance):
|
||||
|
||||
result = super()._to_representation(instance)
|
||||
|
||||
result.update({
|
||||
'context': ATSIGN_CONTEXT,
|
||||
'type': self.Meta.activity_type,
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
class User(ActivitySerializer):
|
||||
|
||||
class Meta:
|
||||
model = trilby_models.User
|
||||
|
||||
activity_type = 'Person'
|
||||
|
||||
fields = (
|
||||
'id', # profileserializers.URL()
|
||||
'name', # display_name
|
||||
'preferredUsername', # username
|
||||
'url', # profileserializers.URL()
|
||||
'summary', # note
|
||||
"manuallyApprovesFollowers", # ???
|
||||
|
||||
'followers', # followersserializers.URL
|
||||
'following', # followingserializers.URL
|
||||
'inbox', # inboxserializers.URL
|
||||
'outbox', # outboxserializers.URL
|
||||
'endpoints',
|
||||
|
||||
'icon',
|
||||
'image',
|
||||
'publicKey',
|
||||
|
||||
'tag',
|
||||
'attachment',
|
||||
)
|
||||
|
||||
# XXX MERGE FROM THIS
|
||||
# "icon": {
|
||||
# "url": user.avatar.url,
|
||||
# "type": "Image",
|
||||
# "mediaType": "image/jpeg",
|
||||
# },
|
||||
# "image": {
|
||||
# "url": user.header.url,
|
||||
# "type": "Image",
|
||||
# "mediaType": "image/jpeg",
|
||||
# },
|
||||
# "publicKey": {
|
||||
# "owner": user.profileserializers.URL(),
|
||||
# "id": '{}#main-key'.format(user.profileserializers.URL()),
|
||||
# "publicKeyPem": user.public_key,
|
||||
# },
|
||||
|
||||
# XXX Mastodon has the "featured" collection here; what is it?
|
||||
|
||||
followers = serializers.URLField()
|
||||
following = serializers.URLField()
|
||||
inbox = serializers.URLField()
|
||||
outbox = serializers.URLField()
|
||||
|
||||
icon = ConstantField(value='nyi')
|
||||
image = ConstantField(value='nyi')
|
||||
publicKey = ConstantField(value='nyi')
|
||||
|
||||
tag = ConstantField(value=[])
|
||||
attachment = ConstantField(value=[])
|
||||
|
||||
endpoints = ConstantField(value = {
|
||||
"sharedInbox": config['SHARED_INBOX_URL'],
|
||||
})
|
||||
|
||||
class ListFromUser(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = trilby_models.User
|
||||
|
||||
activity_type = 'OrderedCollection'
|
||||
|
||||
fields = (
|
||||
'id',
|
||||
)
|
||||
|
||||
id = serializers.CharField(
|
||||
source="profileURL",
|
||||
)
|
||||
|
||||
|
|
@ -1,3 +1,11 @@
|
|||
from django.test import TestCase
|
||||
from django.test import TestCase, Client
|
||||
from .views import User
|
||||
|
||||
# Create your tests here.
|
||||
class UserTests(TestCase):
|
||||
|
||||
def test_user_activity(self):
|
||||
|
||||
c = Client()
|
||||
activity = c.get('/users/alice/activity').json()
|
||||
|
||||
raise ValueError(str(activity))
|
||||
|
|
|
@ -1,3 +1,65 @@
|
|||
from django.shortcuts import render
|
||||
# XXX several of these are probably superfluous
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.views import View
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from oauth2_provider.models import Application
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.utils.datastructures import MultiValueDictKeyError
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
from un_chapeau.config import config
|
||||
import trilby_api.models as trilby
|
||||
import kepi_activity.serializers as serializers
|
||||
from rest_framework import generics, response
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
import json
|
||||
import re
|
||||
|
||||
def render(data):
|
||||
# XXX merge in
|
||||
result = JsonResponse(
|
||||
data=data,
|
||||
json_dumps_params={
|
||||
'sort_keys': True,
|
||||
'indent': 2,
|
||||
}
|
||||
)
|
||||
|
||||
result['Content-Type'] = 'application/activity+json'
|
||||
|
||||
return result
|
||||
|
||||
class UserView(generics.GenericAPIView):
|
||||
|
||||
serializer_class = serializers.User
|
||||
permission_classes = ()
|
||||
|
||||
class FollowersView(generics.ListAPIView):
|
||||
|
||||
serializer_class = serializers.ListFromUser
|
||||
permission_classes = ()
|
||||
|
||||
def get_queryset(self):
|
||||
|
||||
username=self.kwargs['username']
|
||||
|
||||
return trilby.User.objects.filter(
|
||||
followers__username=username,
|
||||
).order_by('date_joined')
|
||||
|
||||
class FollowingView(generics.ListAPIView):
|
||||
|
||||
serializer_class = serializers.ListFromUser
|
||||
permission_classes = ()
|
||||
|
||||
def get_queryset(self):
|
||||
|
||||
username=self.kwargs['username']
|
||||
|
||||
return trilby.User.objects.filter(
|
||||
following__username=username,
|
||||
).order_by('date_joined')
|
||||
|
||||
# Create your views here.
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
setuptools
|
||||
wheel
|
||||
django
|
||||
django-rest-framework
|
||||
djangorestframework-xml
|
||||
djangorestframework-constant-field
|
Ładowanie…
Reference in New Issue