trwnh.com/unified.test.hugo/content/wiki/tech/spec/activitypub/Activity.md
2024-10-05 01:27:07 -05:00

14 KiB

Activity

an Activity is just an object that has an actor. it represents an action that was performed.

{{}}

activities in activitypub

activities are meant to be POSTed to the outbox in C2S (by the Client), then if the Server is also a Federated Server, they get delivered to recipients' inboxes via POST to inbox (by the Federated Server)

for C2S: if it has actor then do not wrap it in a Create when it gets POSTed to outbox. otherwise, per [AP § 6.2.1 "Object creation without a Create Activity"]:

  • make a new Create to wrap the object in object
  • copy over to/cc/bto/bcc/audience from the object to the activity.
  • [not explicitly stated:] set actor on the activity equal to the current authorized user, then copy that over to object.attributedTo
  • generate an id for both the Create and the object, unless it is transient [[how do we determine this? perhaps a client explicitly specifies id=null?]]
  • return the id of the activity via the Location header

for S2S: check to/cc/bto/bcc/audience on the activity. dereference any collections with a recursion limit (possibly n=1). add all discovered inboxes to a list. remove bto/bcc. POST to the list of discovered inboxes.

some activity types have side-effects defined in the activitypub spec, sections 6 (c2S) and 7 (s2s)

(any Activity)

if it has actor then do not wrap it in a Create when it gets POSTed to outbox

  • C2S: MUST assign id to the activity, ignoring anything that might be set by the Client, unless it is transient how to determine this?
  • C2S: add it to the current actor's outbox if not transient?
  • C2S: Return HTTP 201 Created, Location: <id>
  • S2S: warning, if it's an extension activity type then its side effects may not be understood. there may be fallback strategies to display name/summary/content

Create

Update

Delete

Add

Remove

Follow

Like

Block (C2S only)

Announce (S2S only)

Accept (S2S only)

Reject (S2S only)

Undo

activities in the fediverse

in practice and in actuality, the "fediverse" largely does not conform to any of the 3 activitypub profiles. because c2s is not used, there are basically no Clients or Servers. and even on the s2s side, the side effects described by activitypub are not applied in any meaningful way. the real side effects vary per project. it can be argued that the fediverse is actually not built on activitypub, but rather, it is built on activitystreams 2.0 + linked data notifications. (it is a little-known fact that the inbox property in activitypub is actually ldp:inbox as defined by the linked data platform.)

mastodon

supported activity types https://github.com/mastodon/mastodon/tree/main/app/lib/activitypub/activity

  • Accept (accept a follow request)
  • Add (adds hashtag or status to featured collection)
  • Announce (reblog a status)
  • Block (block an account)
  • Create (create a message or status)
  • Delete (delete account or status)
  • Flag (report accounts and/or statuses)
  • Follow (request to follow a local account)
  • Like (favourite a status)
  • Move (migrate an account's followers)
  • Reject (reject follow request or remove follower)
  • Remove (removes hashtag or status from featured collection)
  • Undo (undoes some activities if possible)
  • Update (update account info or edit a status)

extended logic

  • Accept
    • Accept Follow -- authorize a follow request
      • (when relay is findable by object as follow_activity_id)
      • (when object is uri of existing follow request)
      • (when object is embedded Follow)
        • Accept Follow <Account>
  • Add
    • (must have target)
    • (target must be a toot:featured collection)
    • (object must be inlined?)
    • Add Hashtag to target<featured> -- feature a hashtag
      • (takes object.name and removes prefix #)
      • (creates FeaturedTag entity for the actor's account)
    • Add object<Status> to target<featured> -- pin a status
      • (object must be transformable to status)
      • (status must be authored by actor)
      • (status must not already be pinned)
  • Announce
    • (must be related to local activity)
      • (i.e. actor<Account> followed by local accounts)
      • (or requested through relay)
      • (or object refers to a status whose account is local)
    • (object resolves to a status)
    • Announce object<Status> -- creates a reblog of a status
      • (stop if:)
        • (no status)
        • (status not boostable)
        • (requested through relay)
      • (find existing reblog or create)
  • Block
    • (object resolves to an account)
      • (the resolved account exists and is local)
    • Block object<Account> -- block an account
      • (unfollow the object<Account>)
      • (force object<Account> to unfollow you)
      • (reject any follow requests from object<Account>)
      • (create a block asynchronously)
  • Create
    • (dereference the object)
    • Create EncryptedMessage -- creates an encrypted message
      • (tries to find a device id)
      • (extracts messageType, cipherText, digest, messageFranking)
    • Create object<Status> -- creates a status
      • (rejected if)
        • (unsupported object type)
          • (object is a string)
          • (not in supported types)
            • Note
            • Question
          • (not in converted types)
            • Image
            • Audio
            • Video
            • Article
            • Page
            • Event
        • (or invalid origin)
        • (or tombstone exists for object uri)
        • (or not related to local activity)
  • Delete
    • (if actor matches object)
      • Delete object<Account> -- delete your own account
    • Delete object<Status> -- delete a status
      • (create tombstone unless origin is invalid)
      • (forward deletion if forwardable)
      • (remove status from database and timelines)
  • Flag
    • (object array is resolved as accounts and statuses)
      • (then filtered for local)
    • Flag object<Account,Status> -- report an account and/or statuses
      • (foreach account get reported statuses)
      • (create a report against the account w/ optional status ids and content)
  • Follow
    • (object must be a local account that exists)
    • Follow object<Account> -- request to follow a local account
      • (create or update follow request)
      • (auto-reject if:)
        • (object<Account> is blocking actor<Account>)
        • (object<Account> is domain-blocking actor's domain)
        • (object<Account> has moved/redirected)
        • (object<Account> is the instance actor)
      • (send an Accept Follow if a follow already exists)
      • (otherwise create a follow request)
        • (if you are silenced or they are locked, send frq notification)
        • (otherwise send Accept Follow and follow notification)
  • Like
    • (resolve status from object)
    • Like object<Status> -- favourite a status
      • (stop if:)
        • (no status resolved)
        • (status is not from a local account)
        • (delete arrived first)
        • (you already favourited this status)
      • (create a favourite by actor<Account> for object<Status>)
  • Move
    • (actor must match object and resolve to account)
    • (resolve target as account)
    • Move object<Account> to target<Account> -- migrate your followers
      • (stop if:)
        • (no target<Account>)
        • (target<Account> is suspended)
        • (target.alsoKnownAs doesn't include object)
      • (set a redirect)
      • (async move followers from object<Account> to target<Account>)
  • Reject
    • Reject Follow -- reject a follow request or remove follower
      • (when relay is findable by object as follow_activity_id)
      • (when object is uri of existing follow request)
      • (when object is uri of existing follow)
        • (call UnfollowService for actor<Account>)
      • (when object is embedded Follow)
        • Reject Follow Follow.object<Account>
  • Remove
    • (must have target)
    • (target must be a toot:featured collection)
    • (object must be inlined?)
    • Remove Hashtag from target<featured> -- unfeature a hashtag
      • (takes object.name and removes prefix #)
      • (deletes FeaturedTag entity for the actor's account)
    • Remove object<Status> from target<featured> -- unpin a status
      • (object must be transformable to status)
      • (status must be authored by actor)
      • (destroy pin if existing pin found)
  • Undo
    • (object should be inlined or else it may not be handled)
    • Undo Announce -- unreblog a status
      • (stop if no Announce.id)
      • (resolve Announce.id as status reblog)
      • (call RemoveStatusService on status)
    • Undo Accept -- unfollow an account [yes this is the assumption]
      • (find follow by object.object.id and revoke it)
    • Undo Follow
      • (resolve object.object as account)
        • (stop if not exists or not local)
      • Undo Follow <Account> -- unfollow an account
        • (Undo.actor unfollows Follow.object<Account> if following)
    • Undo Like
      • (resolve object.object as status)
      • (stop if no status or if status is not local)
      • Undo Like <Status> -- unfavourite a status
        • (if actor has favourited the status:)
          • (find a favourite on that status by that account)
          • (destroy it)
    • Undo Block
      • (resolve object.object as account)
      • (stop if not exists or not local)
      • Undo Block <Account> --unblock an account
        • (call UnblockService if actor is blocking Block.object<Account>)
    • Undo object<IRI>
      • (try_undo_announce)
        • (find reblogged status by object uri and actor)
        • (if found, remove reblog and stop, else continue)
      • (try_undo_accept)
        • (do nothing, continue) [because Accept uri is not stored]
      • (try_undo_follow)
        • (find actor<Account> follow request/relation by object uri)
        • (if found, destroy it and stop, else continue)
      • (try_undo_like)
        • (do nothing, continue) ["too costly", no index by Like uri]
      • (try_undo_block)
        • (find actor<Account> block by object uri)
        • (if found, call UnblockService and stop, else continue)
  • Update
    • (dereference object)
    • (if object.type in Application Group Organization Person Service)
      • Update object<Account> -- update an account's info
        • (stop if actor.id does not match object.id)
        • (call ProcessAccountService)
    • (else if object.type in Note Question)
      • Update object<Status> -- edit a status
        • (stop if invalid origin)
        • (resolve object as status)
        • (stop if no status)
        • (call ProcessStatusUpdateService)

pixelfed

https://github.com/pixelfed/pixelfed/blob/dev/app/Util/ActivityPub/Inbox.php

(seems to require inlining in a lot of places? not 100% sure but that's what it looks like to me)

  • Add
    • (must be inlined?)
    • Add Story (not final)
  • Create
    • (requires to for some reason, so cc only will break)
    • Create Question
    • (a single to item will create a DM if no cc)
    • Create Note.inReplyTo
    • Create Note.attachment
  • Follow
    • Follow object<Profile>
  • Announce
    • Announce object<Status>
  • Accept
    • Accept Follow (anything else will return immediately)
  • Delete
    • Delete object<Profile> (if object == actor and is valid string uri)
    • Delete [Person, Tombstone, Story] (???)
      • Delete Person
      • Delete Tombstone (???)
      • Delete Story (not final)
  • Like
    • Like object<Status>
  • Reject
    • (does nothing)
  • Undo
    • (must be inlined)
    • Undo Accept
      • (does nothing)
    • Undo Announce
    • Undo Block
      • (does nothing)
    • Undo Follow
    • Undo Like
  • View
    • View Story (not final)
      • (also seems to get story id by whatever is after the last slash?)
  • Story:Reaction (not final; undocumented extension)
    • (id and actor must be valid urls)
    • (inReplyTo and to must be local)
    • (object must not resolve to Status)
    • (seems to get story id by whatever is after the last slash?)
  • Story:Reply (not final; undocumented extension)
    • (id and actor must be valid urls)
    • (inReplyTo and to must be local)
    • (object must not resolve to Status)
    • (seems to get story id by whatever is after the last slash?)
  • Update (commented out)

misskey

https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/core/activitypub/type.ts

  • Create
  • Delete
  • Update
  • Read
  • Undo
  • Follow
  • Accept
  • Reject
  • Add
  • Remove
  • Like | EmojiReaction | EmojiReact
  • Announce
  • Block
  • Flag

https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/core/activitypub/ApInboxService.ts

pleroma

ObjectValidator https://git.pleroma.social/pleroma/pleroma/-/blob/develop/lib/pleroma/web/activity_pub/object_validator.ex

validate()

  • Block
  • Undo
  • Delete
  • Create ChatMessage
  • Create [Question Answer Audio Video Event Article Note Page]
  • [Event Question Audio Video Article Note Page]
    • Event
    • Question
    • Audio
    • Video
    • Article
    • Note
    • Page
  • Update [Question Answer Audio Video Event Article Note Page]
  • [Accept Reject Follow Update Like EmojiReact Announce]
    • Accept
    • Reject
    • Follow
    • Update
    • Like
    • EmojiReact
    • Announce
    • ChatMessage
    • Answer
  • [Add Remove]

SideEffects https://git.pleroma.social/pleroma/pleroma/-/blob/develop/lib/pleroma/web/activity_pub/side_effects.ex

handle()

  • Accept
    • Accept Follow
  • Reject
    • Reject Follow
  • Follow
  • Block
  • Update
    • Update object<User>
    • Update object<Object>
  • Like
  • Create
    • Create ChatMessage
    • Create Question
    • Create Answer
    • Create [Audio Video Event Article Note Page]
  • Announce
  • Undo
    • Undo Like
    • Undo EmojiReact
    • Undo Announce
    • Undo Block
  • EmojiReact
  • Delete
  • Add
  • Remove

Transmogrifier https://git.pleroma.social/pleroma/pleroma/-/blob/develop/lib/pleroma/web/activity_pub/transmogrifier.ex

handle_incoming()

  • Flag
  • Listen Audio
  • Like._misskey_reaction
  • Create [Question Answer ChatMessage Audio Video Event Article Note Page]
  • [Like EmojiReact Announce Add Remove]
    • (fetch actor and object)
  • [Update Block Follow Accept Reject]
    • (fetch actor)
  • Delete
    • (check if Create exists)
  • Undo Follow
  • Undo
    • (get object by id and expand it)
  • Move

prepare_outgoing()

  • [Create Listen]
  • Update object<updatable>
    • [Note Question Audio Video Event Article Page]
  • Announce
  • Accept -> Accept Follow
  • Reject -> Reject Follow
  • Answer -> Note