Add support for context

This commit is contained in:
Thomas Sileo 2019-09-08 10:34:45 +02:00
parent 623261b832
commit 51ed481bb5
2 changed files with 43 additions and 8 deletions

View file

@ -33,6 +33,7 @@ from config import _drop_db
from core import feed from core import feed
from core.activitypub import activity_url from core.activitypub import activity_url
from core.activitypub import post_to_outbox from core.activitypub import post_to_outbox
from core.activitypub import new_context
from core.meta import Box from core.meta import Box
from core.meta import MetaKey from core.meta import MetaKey
from core.meta import _meta from core.meta import _meta
@ -142,6 +143,7 @@ def api_delete() -> _Response:
# Create the delete, same audience as the Create object # Create the delete, same audience as the Create object
delete = ap.Delete( delete = ap.Delete(
context=new_context(note),
actor=ID, actor=ID,
object=ap.Tombstone(id=note.id).to_dict(embed=True), object=ap.Tombstone(id=note.id).to_dict(embed=True),
to=note.to, to=note.to,
@ -169,6 +171,7 @@ def api_boost() -> _Response:
to=[MY_PERSON.followers, note.attributedTo], to=[MY_PERSON.followers, note.attributedTo],
cc=[ap.AS_PUBLIC], cc=[ap.AS_PUBLIC],
published=now(), published=now(),
context=new_context(note),
) )
announce_id = post_to_outbox(announce) announce_id = post_to_outbox(announce)
@ -202,6 +205,7 @@ def api_vote() -> _Response:
to=note.get_actor().id, to=note.get_actor().id,
name=choice, name=choice,
tag=[], tag=[],
context=new_context(note),
inReplyTo=note.id, inReplyTo=note.id,
) )
raw_note["@context"] = config.DEFAULT_CTX raw_note["@context"] = config.DEFAULT_CTX
@ -232,7 +236,14 @@ def api_like() -> _Response:
else: else:
to = [note.get_actor().id] to = [note.get_actor().id]
like = ap.Like(object=note.id, actor=MY_PERSON.id, to=to, cc=cc, published=now()) like = ap.Like(
object=note.id,
actor=MY_PERSON.id,
to=to,
cc=cc,
published=now(),
context=new_context(note),
)
like_id = post_to_outbox(like) like_id = post_to_outbox(like)
@ -301,6 +312,7 @@ def api_undo() -> _Response:
undo = ap.Undo( undo = ap.Undo(
actor=MY_PERSON.id, actor=MY_PERSON.id,
context=new_context(obj),
object=obj.to_dict(embed=True, embed_object_id_only=True), object=obj.to_dict(embed=True, embed_object_id_only=True),
published=now(), published=now(),
to=obj.to, to=obj.to,
@ -421,12 +433,11 @@ def api_new_note() -> _Response:
else: else:
cc.append(reply.attributedTo) cc.append(reply.attributedTo)
context = new_context(reply)
for tag in tags: for tag in tags:
if tag["type"] == "Mention": if tag["type"] == "Mention":
if visibility == ap.Visibility.DIRECT:
to.append(tag["href"]) to.append(tag["href"])
else:
cc.append(tag["href"])
raw_note = dict( raw_note = dict(
attributedTo=MY_PERSON.id, attributedTo=MY_PERSON.id,
@ -437,6 +448,7 @@ def api_new_note() -> _Response:
tag=tags, tag=tags,
source={"mediaType": "text/markdown", "content": source}, source={"mediaType": "text/markdown", "content": source},
inReplyTo=reply.id if reply else None, inReplyTo=reply.id if reply else None,
context=context,
) )
if "file" in request.files and request.files["file"].filename: if "file" in request.files and request.files["file"].filename:
@ -450,7 +462,7 @@ def api_new_note() -> _Response:
raw_note["attachment"] = [ raw_note["attachment"] = [
{ {
"mediaType": mtype, "mediaType": mtype,
"name": rfilename, "name": _user_api_arg("file_description", default=rfilename),
"type": "Document", "type": "Document",
"url": f"{BASE_URL}/uploads/{oid}/{rfilename}", "url": f"{BASE_URL}/uploads/{oid}/{rfilename}",
} }
@ -508,6 +520,7 @@ def api_new_question() -> _Response:
attributedTo=MY_PERSON.id, attributedTo=MY_PERSON.id,
cc=list(set(cc)), cc=list(set(cc)),
to=[ap.AS_PUBLIC], to=[ap.AS_PUBLIC],
context=new_context(),
content=content, content=content,
tag=tags, tag=tags,
source={"mediaType": "text/markdown", "content": source}, source={"mediaType": "text/markdown", "content": source},
@ -563,7 +576,12 @@ def api_follow() -> _Response:
return _user_api_response(activity=existing["activity"]["id"]) return _user_api_response(activity=existing["activity"]["id"])
follow = ap.Follow( follow = ap.Follow(
actor=MY_PERSON.id, object=actor, to=[actor], cc=[ap.AS_PUBLIC], published=now() actor=MY_PERSON.id,
object=actor,
to=[actor],
cc=[ap.AS_PUBLIC],
published=now(),
context=new_context(),
) )
follow_id = post_to_outbox(follow) follow_id = post_to_outbox(follow)

View file

@ -272,12 +272,29 @@ def save_reply(activity: ap.BaseActivity, meta: Dict[str, Any] = {}) -> None:
) )
def new_context(parent: Optional[ap.BaseActivity] = None) -> str:
"""`context` is here to group related activities, it's not meant to be resolved.
We're just following the convention."""
# Copy the context from the parent if any
if parent and (parent.context or parent.conversation):
if parent.context:
if isinstance(parent.context, str):
return parent.context
elif isinstance(parent.context, dict) and parent.context.get("id"):
return parent.context["id"]
return parent.conversation
# Generate a new context
ctx_id = binascii.hexlify(os.urandom(12)).decode("utf-8")
return urljoin(BASE_URL, f"/contexts/{ctx_id}")
def post_to_outbox(activity: ap.BaseActivity) -> str: def post_to_outbox(activity: ap.BaseActivity) -> str:
if activity.has_type(ap.CREATE_TYPES): if activity.has_type(ap.CREATE_TYPES):
activity = activity.build_create() activity = activity.build_create()
# Assign create a random ID # Assign create a random ID
obj_id = binascii.hexlify(os.urandom(8)).decode("utf-8") obj_id = binascii.hexlify(os.urandom(12)).decode("utf-8")
uri = activity_url(obj_id) uri = activity_url(obj_id)
activity._data["id"] = uri activity._data["id"] = uri
if activity.has_type(ap.ActivityType.CREATE): if activity.has_type(ap.ActivityType.CREATE):