kopia lustrzana https://gitlab.com/jaywink/federation
documentation updates and clean up comments
rodzic
2e60c37f36
commit
cbc46334db
|
@ -13,13 +13,13 @@
|
|||
* GET requests are now signed if the django configuration includes FEDERATION_USER which is used to fetch that
|
||||
user's private key.
|
||||
|
||||
* Added Video and Audio objects.
|
||||
* Added Video and Audio objects. Inbound support only.
|
||||
|
||||
* Process Activitypub reply collections.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Signatures are not verified and the corresponding payload is dropped is no public key is found.
|
||||
* Signatures are not verified and the corresponding payload is dropped if no public key is found.
|
||||
|
||||
### Internal changes
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ Help is more than welcome to extend this library. Please see the following resou
|
|||
Environment setup
|
||||
-----------------
|
||||
|
||||
Once you have your (Python 3.6+) virtualenv set up, install the development requirements::
|
||||
Once you have your (Python 3.7+) virtualenv set up, install the development requirements::
|
||||
|
||||
pip install -r dev-requirements.txt
|
||||
|
||||
|
@ -34,7 +34,7 @@ Built documentation is available at ``docs/_build/html/index.html``.
|
|||
Contact for help
|
||||
----------------
|
||||
|
||||
Easiest via Matrix on room ``#socialhome:feneas.org``. There is a bridged
|
||||
Easiest via Matrix on room ``#socialhome:federator.dev``. There is a bridged
|
||||
Freenode channel as well found at ``#socialhome``.
|
||||
|
||||
You can also ask questions or give feedback via issues.
|
||||
|
|
|
@ -14,9 +14,8 @@ Status
|
|||
Currently three protocols are being focused on.
|
||||
|
||||
* Diaspora is considered to be stable with most of the protocol implemented.
|
||||
* ActivityPub support should be considered as alpha - all the basic
|
||||
things work but there are likely to be a lot of compatibility issues with other ActivityPub
|
||||
implementations.
|
||||
* ActivityPub support should be considered as beta - inbound payload are
|
||||
handled by a jsonld processor (calamus)
|
||||
* Matrix support cannot be considered usable as of yet.
|
||||
|
||||
The code base is well tested and in use in several projects. Backward incompatible changes
|
||||
|
@ -48,5 +47,5 @@ License
|
|||
Author
|
||||
......
|
||||
|
||||
Jason Robinson / `jasonrobinson.me <https://jasonrobinson.me>`_ / `@jaywink:federator.dev <https://matrix.to/#/@jaywink:federator.dev>`_ / `GitLab <https://git.feneas.org/jaywink>`_ / `GitHub <https://github.com/jaywink>`_
|
||||
Jason Robinson / `jasonrobinson.me <https://jasonrobinson.me>`_ / `@jaywink:federator.dev <https://matrix.to/#/@jaywink:federator.dev>`_ / `GitLab <https://gitlab.com/jaywink>`_ / `GitHub <https://github.com/jaywink>`_
|
||||
|
||||
|
|
|
@ -48,9 +48,15 @@ Features currently supported:
|
|||
* Actor (Person outbound, Person, Organization, Service inbound)
|
||||
* Note, Article and Page (Create, Delete, Update)
|
||||
* These become a ``Post`` or ``Comment`` depending on ``inReplyTo``.
|
||||
* Attachment images from the above objects
|
||||
* Attachment images, (inbound only for audios and videos) from the above objects
|
||||
* Follow, Accept Follow, Undo Follow
|
||||
* Announce
|
||||
* Inbound Peertube Video objects translated as ``Post``.
|
||||
|
||||
* Inbound processing of reply collections, for platforms that implement it.
|
||||
* Link, Like, View, Signature, PropertyValue, IdentityProof and Emojis objects are only processed for inbound
|
||||
payloads currently. Outbound processing requires support by the client
|
||||
application.
|
||||
|
||||
Namespace
|
||||
.........
|
||||
|
@ -71,23 +77,26 @@ The following keys will be set on the entity based on the ``source`` property ex
|
|||
* ``_rendered_content`` will be the object ``content``
|
||||
* ``raw_content`` will object ``content`` run through a HTML2Markdown renderer
|
||||
|
||||
The ``contentMap`` property is processed but content language selection is not implemented yet.
|
||||
|
||||
For outbound entities, ``raw_content`` is expected to be in ``text/markdown``,
|
||||
specifically CommonMark. When sending payloads, ``raw_content`` will be rendered via
|
||||
the ``commonmark`` library into ``object.content``. The original ``raw_content``
|
||||
will be added to the ``object.source`` property.
|
||||
|
||||
Images
|
||||
Medias
|
||||
......
|
||||
|
||||
Any images referenced in the ``raw_content`` of outbound entities will be extracted
|
||||
into ``object.attachment`` objects, for receivers that don't support inline images.
|
||||
These attachments will have a ``pyfed:inlineImage`` property set to ``true`` to
|
||||
indicate the image has been extrated from the content. Receivers should ignore the
|
||||
into ``object.attachment`` object. For receivers that don't support inline images,
|
||||
image attachments will have a ``pyfed:inlineImage`` property set to ``true`` to
|
||||
indicate the image has been extracted from the content. Receivers should ignore the
|
||||
inline image attachments if they support showing ``<img>`` HTML tags or the markdown
|
||||
content in ``object.source``.
|
||||
content in ``object.source``. Outbound audio and video attachments currently lack
|
||||
support from client applications.
|
||||
|
||||
For inbound entities we do this automatically by not including received attachments in
|
||||
the entity ``_children`` attribute.
|
||||
For inbound entities we do this automatically by not including received image attachments in
|
||||
the entity ``_children`` attribute. Audio and video are passed through the client application.
|
||||
|
||||
.. _matrix:
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ passed back to the caller.
|
|||
For sending messages out, either base or protocol specific entities can be passed
|
||||
to the outbound senders.
|
||||
|
||||
If you need the correct protocol speficic entity class from the base entity,
|
||||
If you need the correct protocol specific entity class from the base entity,
|
||||
each protocol will define a ``get_outbound_entity`` function.
|
||||
|
||||
.. autofunction:: federation.entities.activitypub.mappers.get_outbound_entity
|
||||
|
@ -212,6 +212,7 @@ Some settings need to be set in Django settings. An example is below:
|
|||
|
||||
FEDERATION = {
|
||||
"base_url": "https://myserver.domain.tld,
|
||||
"federation_id": "https://example.com/u/john/",
|
||||
"get_object_function": "myproject.utils.get_object",
|
||||
"get_private_key_function": "myproject.utils.get_private_key",
|
||||
"get_profile_function": "myproject.utils.get_profile",
|
||||
|
@ -223,6 +224,7 @@ Some settings need to be set in Django settings. An example is below:
|
|||
}
|
||||
|
||||
* ``base_url`` is the base URL of the server, ie protocol://domain.tld.
|
||||
* ``federation_id`` is a valid ActivityPub local profile id whose private key will be used to create the HTTP signature for GET requests to ActivityPub platforms.
|
||||
* ``get_object_function`` should be the full path to a function that will return the object matching the ActivityPub ID for the request object passed to this function.
|
||||
* ``get_private_key_function`` should be the full path to a function that will accept a federation ID (url, handle or guid) and return the private key of the user (as an RSA object). Required for example to sign outbound messages in some cases.
|
||||
* ``get_profile_function`` should be the full path to a function that should return a ``Profile`` entity. The function should take one or more keyword arguments: ``fid``, ``handle``, ``guid`` or ``request``. It should look up a profile with one or more of the provided parameters.
|
||||
|
|
|
@ -130,14 +130,6 @@ class ActivitypubNoteMixin(AttachImagesMixin, CleanContentMixin, PublicMixin, Cr
|
|||
if isinstance(tag, Mention):
|
||||
self._mentions.add(tag.href)
|
||||
|
||||
#if not isinstance(self._source_object, dict):
|
||||
# return
|
||||
#source = self._source_object.get('object') if isinstance(self._source_object.get('object'), dict) else \
|
||||
# self._source_object
|
||||
#for tag in source.get('tag', []):
|
||||
# if tag.get('type') == "Mention" and tag.get('href'):
|
||||
# self._mentions.add(tag.get('href'))
|
||||
|
||||
def pre_send(self):
|
||||
super().pre_send()
|
||||
self.extract_mentions()
|
||||
|
|
|
@ -40,7 +40,7 @@ def get_loader(*args, **kwargs):
|
|||
backend = rc.SQLiteCache(db_path='fed_cache')
|
||||
except ImportError:
|
||||
backend = rc.SQLiteCache(db_path='fed_cache')
|
||||
logger.info('Using %s for requests_cache', type(backend))
|
||||
logger.debug('Using %s for requests_cache', type(backend))
|
||||
|
||||
requests_loader = jsonld.requests_document_loader(*args, **kwargs)
|
||||
|
||||
|
@ -239,31 +239,31 @@ class Object(metaclass=JsonLDAnnotation):
|
|||
image = MixedField(as2.image, nested='ImageSchema')
|
||||
tag_list = MixedField(as2.tag, nested=['HashtagSchema','MentionSchema','PropertyValueSchema','EmojiSchema'])
|
||||
_children = fields.Nested(as2.attachment, nested=['ImageSchema', 'AudioSchema', 'DocumentSchema','PropertyValueSchema','IdentityProofSchema'], many=True)
|
||||
#_children = MixedField(as2.attachment, nested=['ImageSchema', 'AudioSchema', 'DocumentSchema','PropertyValueSchema','IdentityProofSchema'])
|
||||
#audience
|
||||
content_map = LanguageMap(as2.content) # language maps are not implemented in calamus
|
||||
context = IRI(as2.context)
|
||||
guid = fields.String(diaspora.guid)
|
||||
name = fields.String(as2.name)
|
||||
#endtime
|
||||
generator = MixedField(as2.generator, nested='ServiceSchema')
|
||||
#generator = Dict(as2.generator)
|
||||
#location
|
||||
#preview
|
||||
created_at = fields.DateTime(as2.published, add_value_types=True)
|
||||
replies = MixedField(as2.replies, nested=['CollectionSchema','OrderedCollectionSchema'])
|
||||
signature = MixedField(sec.signature, nested = 'SignatureSchema')
|
||||
start_time = fields.DateTime(as2.startTime, add_value_types=True)
|
||||
updated = fields.DateTime(as2.updated, add_value_types=True)
|
||||
to = IRI(as2.to)
|
||||
#bto
|
||||
cc = IRI(as2.cc)
|
||||
#bcc
|
||||
media_type = fields.String(as2.mediaType)
|
||||
#duration
|
||||
sensitive = fields.Boolean(as2.sensitive)
|
||||
source = Dict(as2.source)
|
||||
|
||||
# The following properties are defined by some platforms, but are not implemented yet
|
||||
#audience
|
||||
#endtime
|
||||
#location
|
||||
#preview
|
||||
#bto
|
||||
#bcc
|
||||
#duration
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
for k, v in kwargs.items():
|
||||
if hasattr(self, k):
|
||||
|
@ -461,8 +461,9 @@ class Link(metaclass=JsonLDAnnotation):
|
|||
width = Integer(as2.width, flavor=xsd.nonNegativeInteger, add_value_types=True)
|
||||
fps = Integer(pt.fps, flavor=schema.Number, add_value_types=True)
|
||||
size = Integer(pt.size, flavor=schema.Number, add_value_types=True)
|
||||
#preview : variable type?
|
||||
tag = MixedField(as2.tag, nested=['InfohashSchema', 'LinkSchema'])
|
||||
# Not implemented yet
|
||||
#preview : variable type?
|
||||
|
||||
class Meta:
|
||||
rdf_type = as2.Link
|
||||
|
@ -513,16 +514,9 @@ class Person(Object):
|
|||
outbox = IRI(as2.outbox, dump_derived={'fmt': '{id}outbox/', 'fields': ['id']})
|
||||
following = IRI(as2.following, dump_derived={'fmt': '{id}following/', 'fields': ['id']})
|
||||
followers = IRI(as2.followers, dump_derived={'fmt': '{id}followers/', 'fields': ['id']})
|
||||
#liked is a collection
|
||||
#streams
|
||||
username = fields.String(as2.preferredUsername)
|
||||
endpoints = Dict(as2.endpoints)
|
||||
shared_inbox = IRI(as2.sharedInbox) # misskey adds this
|
||||
#proxyUrl
|
||||
#oauthAuthorizationEndpoint
|
||||
#oauthTokenEndpoint
|
||||
#provideClientKey
|
||||
#signClientKey
|
||||
url = IRI(as2.url)
|
||||
playlists = IRI(pt.playlists)
|
||||
featured = IRI(toot.featured)
|
||||
|
@ -542,6 +536,14 @@ class Person(Object):
|
|||
copied_to = IRI(toot.copiedTo)
|
||||
capabilities = Dict(litepub.capabilities)
|
||||
suspended = fields.Boolean(toot.suspended)
|
||||
# Not implemented yet
|
||||
#liked is a collection
|
||||
#streams
|
||||
#proxyUrl
|
||||
#oauthAuthorizationEndpoint
|
||||
#oauthTokenEndpoint
|
||||
#provideClientKey
|
||||
#signClientKey
|
||||
|
||||
@classmethod
|
||||
def from_base(cls, entity):
|
||||
|
@ -717,7 +719,7 @@ class Video(Object):
|
|||
for a in act:
|
||||
if type(a) == Person:
|
||||
new_act.append(a.id)
|
||||
# TODO: fix extract_receivers which can't handle multiple actors!
|
||||
# TODO: fix extract_receivers which doesn't handle multiple actors!
|
||||
self.actor_id = new_act[0]
|
||||
|
||||
entity = ActivitypubPost(**self.__dict__)
|
||||
|
@ -740,10 +742,10 @@ class Signature(Object):
|
|||
|
||||
class Activity(Object):
|
||||
actor_id = IRI(as2.actor)
|
||||
#target_id = IRI(as2.target)
|
||||
instrument = MixedField(as2.instrument, nested='ServiceSchema')
|
||||
# Not implemented yet
|
||||
#result
|
||||
#origin
|
||||
instrument = MixedField(as2.instrument, nested='ServiceSchema')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.activity = self
|
||||
|
@ -868,10 +870,10 @@ def extract_receiver(entity, receiver):
|
|||
return []
|
||||
|
||||
|
||||
# Work in progress
|
||||
#obj = retrieve_and_parse_document(receiver)
|
||||
#if isinstance(obj, ActivitypubProfile):
|
||||
# return [UserType(id=receiver, receiver_variant=ReceiverVariant.ACTOR)]
|
||||
|
||||
#if isinstance(obj, Collection) and base_url:
|
||||
# return process_followers(obj, base_url)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue