For Fun: Let's collect ActivityPub Activities that amuse us

Primary Goal: Have Fun.
Secondary Goal: Collect possible input for tests.

The following plays havoc on my display logic, as I expected content to be at most an emoji.

{
  "@context": "about:bovine",
  "id": "https://fed.brid.gy/r/https://snarfed.org/2023-09-24_51013",
  "type": "Like",
  "actor": "https://fed.brid.gy/snarfed.org",
  "cc": [
    "as:Public",
    "https://mymath.rocks/endpoints/30zoCe7haKBEFolH4rbAmKj-t9_bG0c2X2kMQkJk5qY",
    "https://mymath.rocks/endpoints/SYn3cl_N4HAPfPHgo2x37XunLEmhV9LnxCggcYwyec0"
  ],
  "content": "Likes <a class=\"u-like-of\" href=\"https://mastodon.social/@helge@mymath.rocks/111095945789341275\">https://mastodon.social/@helge@mymath.rocks/111095945789341275</a>.",
  "object": "https://mymath.rocks/objects/f45a04bb-89cf-488c-805a-c8821d6c6efe",
  "published": "2023-09-24T13:06:29-07:00",
  "to": [
    "as:Public"
  ],
  "url": "https://fed.brid.gy/r/https://snarfed.org/2023-09-24_51013"
}
2 Likes

I like the web view of it though (simply open the URL in your browser).

1 Like

I’m writing something and I’m quite amused by

{
   "@context": "https://www.w3.org/ns/activitystreams",
   "id": "https://my.example/like",
   "actor": "https://my.example/helge",
   "type": "Like",
   "object": "https://remote.example/object",
   "published": "2024-01-08T18:56:38Z",
   "summaryMap": {
       "en": "Helge likes this",
       "de": "Helge mag dies",
       "fr": "Helge aime ceci",
       "es": "A Helge le gusta"
    }
}

Not sure how to actually do something like this, but internationalization for automated generated text, seems like a bad idea in this form.

"es": "A Helge le gusta"
1 Like

Akkoma sends the following Follow request, when manuallyApprovesFollowers is set to True.

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "http://akkoma/schemas/litepub-0.1.jsonld",
    {
      "@language": "und"
    }
  ],
  "actor": "http://akkoma/users/witch",
  "bcc": [],
  "bto": [],
  "cc": [],
  "id": "http://akkoma/activities/5971ab5d-92a1-4a66-ac12-077a868d2b21",
  "object": "http://bovine/milkdrinker",
  "state": "pending",
  "to": [
    "http://bovine/milkdrinker"
  ],
  "type": "Follow"
}

this isn’t an activity nor does it federate in the real world by any implementation but i was always amused (and, frankly, concerned) that this is completely valid by the specs. introducing, the post that owns itself:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://example.com/",
  "type": ["Person", "Note"],
  "preferredUsername": "test",
  "inbox": "https://example.com/inbox",
  "content": "<p>I am so sorry.</p>",
  "attributedTo": "https://example.com/"
}

Not only is self-ownership completely valid, it’s actually potentially useful! Consider a Collection that owns itself and is therefore allowed to Add items into itself:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Collection",
  "items": [
    "https://example.com/some-object",
    "https://example.com/some-other-object"
  ],
  "outbox": "https://example.com/some-outbox",
  "inbox": "https://example.com/some-inbox",
  "attributedTo": "https://example.com/some-collection",
  "id": "https://example.com/some-collection"
}
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://example.com/some-add",
  "actor": "https://example.com/some-collection"
  "type": "Add",
  "object": "https://example.com/some-third-object",
  "target": "https://example.com/some-collection"
}

From an ActivityPub S2S perspective, the authorization check passes, since actor and target.attributedTo match, so the actor is allowed to Add to target. This allows you to abstract away any authorization or access control to an external system.

I’ve build my new toy bovine with fediverse-pasture and it allows me to mess around with this kind of stuff.

To follow the instructions, get the fediverse-pasture and start mitra via

docker compose --file fediverse-pasture/mitra.yml up

Then from the compose file on the tutorial for bovine start the repl

docker compose run repl

If one runs the following commands:

>>> note = {
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "http://bovine/example.com",
    "type": "Person",
    "preferredUsername": "test",
    "inbox": "https://example.com/inbox",
    "content": "<p>I am so sorry.</p>",
    "attributedTo": "http://bovine/milkdrinker",
    "to": "http://mitra/users/admin",
}
>>> await actor.post("http://mitra/users/admin/inbox", activity_factory.create(note).build())
<ClientResponse(http://mitra/users/admin/inbox) [202 Accepted]>
<CIMultiDictProxy('Content-Length': '0', 'x-content-type-options': 'nosniff', 'content-security-policy': "base-uri 'self'; connect-src 'self'; default-src 'none'; frame-ancestors 'none'; img-src 'self' data:; manifest-src 'self'; media-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self'", 'Vary': 'Origin, Access-Control-Request-Method, Access-Control-Request-Headers', 'Date': 'Sun, 20 Oct 2024 07:39:29 GMT')>

One creates a valid Activity in mitra by @silverpill see:

This is a consequence of Mitra using duck typing to parse arriving objects (AFAIK). It couldn’t hand the "type": ["Note", "Person"].

I’m done playing with my toys now.

1 Like

What version you’re running?
Mitra uses duck typing, but object with inbox property shouldn’t be processed as “post” anymore (that was fixed in v2.17.0).

Not sure what version that was. Can confirm that for Mitra v3.7.1, I need to remove the inbox property for the post to be displayed.

Processing still fails if type is a one item list.

1 Like

This is making me laugh a lot, we have

{
  "@context": [
    "http://joinmastodon.org/ns",
    "https://w3id.org/security/v1",
    "https://www.w3.org/ns/activitystreams",
    "http://schema.org"
  ],
  "attachment": [
    {
      "name": "NLnet website",
      "type": "PropertyValue",
      "value": "<a href=\"https://nlnet.nl/\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">https://nlnet.nl/</a>"
    }
  ],
  "discoverable": true,
  "featured": "https://social.nlnet.nl/users/nlnet/collections/featured",
  "followers": "https://social.nlnet.nl/users/nlnet/followers",
  "following": "https://social.nlnet.nl/users/nlnet/following",
  "icon": {
    "mediaType": "image/jpeg",
    "type": "Image",
    "url": "https://social.nlnet.nl/fileserver/01PQYTCQGNVX1BV35GWGD863GC/attachment/original/01HSSJEDF6SSJ9DBXGA1YDHTWY.jpg"
  },
  "id": "https://social.nlnet.nl/users/nlnet",
  "image": {
    "mediaType": "image/jpeg",
    "type": "Image",
    "url": "https://social.nlnet.nl/fileserver/01PQYTCQGNVX1BV35GWGD863GC/attachment/original/01MDHADSHN81TYXV5PS8D0XYRZ.jpg"
  },
  "inbox": "https://social.nlnet.nl/users/nlnet/inbox",
  "manuallyApprovesFollowers": false,
  "name": "NLnet",
  "outbox": "https://social.nlnet.nl/users/nlnet/outbox",
  "preferredUsername": "nlnet",
  "publicKey": {
    "id": "https://social.nlnet.nl/users/nlnet/main-key",
    "owner": "https://social.nlnet.nl/users/nlnet",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlFNqNT+ZzHJOFTFkDXfh\nSJbbFhwMMpAXQiggylw5llfZ5bEM4Nf+Zi0oDQHUHuSw8GNy92eGs/FR23NIcRf/\nQizlo4cTw8hnagk6CHzSJrAw2iPitUlJKssRJTUMjUTWJzRNRnLkv2HeqR5LL+ED\nOKaR1/rQt8c2cCA2TeJXUKZDXlKvWfaAY91De2tkkoB+wjqf94ufXMU5xEC5Hgee\nmYg0qCVOeTJzHYpTsl7jvw2VUZA4Tx45e861CrYkgd5YyhTudIOOlJaWgQEG/faO\nSpJcNoQyoB+tYUcVP+kAgJ6nJC7h2HtFGvRtB8vf1ejPIxR1ZNpl8FW0OF4karni\n6wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  "summary": "<p>We are NLnet foundation. We support organisations and people who contribute to an open internet for all. If you are working on a project that helps fix the internet through open hardware, open software, open standards, open science and open data, we invite you to apply for a grant.<br>We're lead of the <span class=\"h-card\"><a href=\"https://mastodon.xyz/@NGIZero\" class=\"u-url mention\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">@<span>NGIZero</span></a></span> coalition which runs several programmes to fund those who are building free and open source technologies for the Next Generation Internet.<br>After an historical contribution to the early internet in Europe in the 1980's, we've been financially supporting the open internet since 1997.<br>We like hex stickers.</p>",
  "tag": [],
  "type": "Person",
  "url": "https://social.nlnet.nl/@nlnet"
}

as currently served. This looks good, right? Well it’s not:

  • First "http://joinmastodon.org/ns" cannot be resolved.
  • Second, due to the ordering, when compacting against the activitystreams context, we get
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://social.nlnet.nl/users/nlnet",
  "type": "http://schema.org/Person", ...

I believe to remember that both issues are caused by the ActivityPub library they use, but too lazy to look into it.

2 Likes

Another thing, I find amusing

{
  "type": "PropertyValue",
  "name": "bsky",
  "value": "<a href=\"https://bsky.app/profile/example\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">bsky.app/profile/example</span><span class=\"invisible\"></span></a>"
}

instead of the value of the attachment to the actor being a simple uri, one gets a VERY awkwardly formatted link. A clean version would be

{
  "type": "PropertyValue",
  "name": "bsky",
  "value": "https://bsky.app/profile/example"
}

Maybe someone can point out the Mastodon issue that has been open for a decade that this should be fixed.

fep/fep/fb2a/fep-fb2a.md at main - fediverse/fep - Codeberg.org proposes using a Link or Note to clear up exactly this unnecessarily messy formatting. I’m not sure it’s a high priority for Mastodon to adopt, but it could be done if they cared.

Just to share it with the class. If you wonder why you cannot message Mastodon from Mobilizon: No mention tag, here’s a sample Activity. Also enjoy @context.

bovine-1  | {
bovine-1  |   "@context": [
bovine-1  |     "https://www.w3.org/ns/activitystreams",
bovine-1  |     "https://w3id.org/security/v1",
bovine-1  |     {
bovine-1  |       "addressRegion": "sc:addressRegion",
bovine-1  |       "timezone": {
bovine-1  |         "@id": "mz:timezone",
bovine-1  |         "@type": "sc:Text"
bovine-1  |       },
bovine-1  |       "isOnline": {
bovine-1  |         "@id": "mz:isOnline",
bovine-1  |         "@type": "sc:Boolean"
bovine-1  |       },
bovine-1  |       "pt": "https://joinpeertube.org/ns#",
bovine-1  |       "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
bovine-1  |       "inLanguage": "sc:inLanguage",
bovine-1  |       "address": {
bovine-1  |         "@id": "sc:address",
bovine-1  |         "@type": "sc:PostalAddress"
bovine-1  |       },
bovine-1  |       "status": {
bovine-1  |         "@id": "ical:status",
bovine-1  |         "@type": "ical:status"
bovine-1  |       },
bovine-1  |       "discoverable": "toot:discoverable",
bovine-1  |       "repliesModerationOption": {
bovine-1  |         "@id": "mz:repliesModerationOption",
bovine-1  |         "@type": "mz:repliesModerationOptionType"
bovine-1  |       },
bovine-1  |       "sc": "http://schema.org#",
bovine-1  |       "mz": "https://joinmobilizon.org/ns#",
bovine-1  |       "category": "sc:category",
bovine-1  |       "joinModeType": {
bovine-1  |         "@id": "mz:joinModeType",
bovine-1  |         "@type": "rdfs:Class"
bovine-1  |       },
bovine-1  |       "Hashtag": "as:Hashtag",
bovine-1  |       "propertyID": "sc:propertyID",
bovine-1  |       "PostalAddress": "sc:PostalAddress",
bovine-1  |       "discussions": {
bovine-1  |         "@id": "mz:discussions",
bovine-1  |         "@type": "@id"
bovine-1  |       },
bovine-1  |       "remainingAttendeeCapacity": "sc:remainingAttendeeCapacity",
bovine-1  |       "streetAddress": "sc:streetAddress",
bovine-1  |       "anonymousParticipationEnabled": {
bovine-1  |         "@id": "mz:anonymousParticipationEnabled",
bovine-1  |         "@type": "sc:Boolean"
bovine-1  |       },
bovine-1  |       "externalParticipationUrl": {
bovine-1  |         "@id": "mz:externalParticipationUrl",
bovine-1  |         "@type": "sc:URL"
bovine-1  |       },
bovine-1  |       "addressLocality": "sc:addressLocality",
bovine-1  |       "joinMode": {
bovine-1  |         "@id": "mz:joinMode",
bovine-1  |         "@type": "mz:joinModeType"
bovine-1  |       },
bovine-1  |       "location": {
bovine-1  |         "@id": "sc:location",
bovine-1  |         "@type": "sc:Place"
bovine-1  |       },
bovine-1  |       "toot": "http://joinmastodon.org/ns#",
bovine-1  |       "participantCount": {
bovine-1  |         "@id": "mz:participantCount",
bovine-1  |         "@type": "sc:Integer"
bovine-1  |       },
bovine-1  |       "uuid": "sc:identifier",
bovine-1  |       "maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
bovine-1  |       "participationMessage": {
bovine-1  |         "@id": "mz:participationMessage",
bovine-1  |         "@type": "sc:Text"
bovine-1  |       },
bovine-1  |       "openness": {
bovine-1  |         "@id": "mz:openness",
bovine-1  |         "@type": "@id"
bovine-1  |       },
bovine-1  |       "members": {
bovine-1  |         "@id": "mz:members",
bovine-1  |         "@type": "@id"
bovine-1  |       },
bovine-1  |       "events": {
bovine-1  |         "@id": "mz:events",
bovine-1  |         "@type": "@id"
bovine-1  |       },
bovine-1  |       "resources": {
bovine-1  |         "@id": "mz:resources",
bovine-1  |         "@type": "@id"
bovine-1  |       },
bovine-1  |       "addressCountry": "sc:addressCountry",
bovine-1  |       "posts": {
bovine-1  |         "@id": "mz:posts",
bovine-1  |         "@type": "@id"
bovine-1  |       },
bovine-1  |       "commentsEnabled": {
bovine-1  |         "@id": "pt:commentsEnabled",
bovine-1  |         "@type": "sc:Boolean"
bovine-1  |       },
bovine-1  |       "value": "sc:value",
bovine-1  |       "PropertyValue": "sc:PropertyValue",
bovine-1  |       "repliesModerationOptionType": {
bovine-1  |         "@id": "mz:repliesModerationOptionType",
bovine-1  |         "@type": "rdfs:Class"
bovine-1  |       },
bovine-1  |       "todos": {
bovine-1  |         "@id": "mz:todos",
bovine-1  |         "@type": "@id"
bovine-1  |       },
bovine-1  |       "ical": "http://www.w3.org/2002/12/cal/ical#",
bovine-1  |       "postalCode": "sc:postalCode",
bovine-1  |       "memberCount": {
bovine-1  |         "@id": "mz:memberCount",
bovine-1  |         "@type": "sc:Integer"
bovine-1  |       },
bovine-1  |       "@language": "und"
bovine-1  |     }
bovine-1  |   ],
bovine-1  |   "actor": "http://mobilizon/@rose",
bovine-1  |   "attributedTo": "http://mobilizon/@rose",
bovine-1  |   "cc": [],
bovine-1  |   "id": "http://mobilizon/comments/b3b7ffbd-f47f-436f-8901-4b26cac75a95/activity",
bovine-1  |   "object": {
bovine-1  |     "actor": "http://mobilizon/@rose",
bovine-1  |     "cc": [],
bovine-1  |     "content": "<p>prick</p>",
bovine-1  |     "id": "http://mobilizon/comments/b3b7ffbd-f47f-436f-8901-4b26cac75a95",
bovine-1  |     "mediaType": "text/html",
bovine-1  |     "published": "2025-01-08T07:57:11Z",
bovine-1  |     "publishedAt": "2025-01-08T07:57:11Z",
bovine-1  |     "to": [
bovine-1  |       "http://bovine/milkdrinker",
bovine-1  |       "http://mobilizon/@rose"
bovine-1  |     ],
bovine-1  |     "type": "Note"
bovine-1  |   },
bovine-1  |   "published": "2025-01-08T07:57:11Z",
bovine-1  |   "to": [
bovine-1  |     "http://bovine/milkdrinker",
bovine-1  |     "http://mobilizon/@rose"
bovine-1  |   ],
bovine-1  |   "type": "Create"
bovine-1  | }
1 Like

Is the mention tag needed for delivery in general, or just for Mastodon notifications?

They appear as followers only posts in the profile, but not as a “private mention” (or in the home feed).

This means people will probably overlook them.

Also direct messaging Mastodon → Mobilizon doesn’t give me a message.

1 Like

With regards to this most notable are the horrible app-specific extensions, where we really want interopable business domains. For the next Events app they need to sprinkle in some Mobilizon and some FooBar extension whiff, then bolt on their own stuff that the next Events app may consider also including in a prep for a spectular whack-a-mole development cycle.

the “app-specific extensions” aren’t even that big of a deal compared to the misuse of their term definitions as if they were a schema (which they are not).

i mean, there’s the perennial “incorrect http://schema.org# prefix” issue that persists solely because of mastodon making a mistake once that got uncritically copied by others. but on so many levels, the canonical statements being produced are nonsensical. i wonder to what extent mobilizon actually uses their own context declaration…

in any case, context declarations like this make me wish there was a more widespread culture of just using full uris or expanded form. but that’s talk for some other threads:

(yes, i need to make some changes / revisions there, at some point)

1 Like

this sounds like a bug in mastodon. i think recipients in to/cc but without a Mention in tag are supposed to be processed as “silent mentions”, and it sounds like this is being skipped?

EDIT: Generate a notification if someone is addressed directly, even if not tagged with a Mention · Issue #32242 · mastodon/mastodon · GitHub

If you wish to investigate:

https://pasture.funfedi.dev/

and then download the archive, then run

docker compose --file fediverse-pasture/mastodon.yml\
       --file fediverse-pasture/mobilizon.yml up --wait

real	1m41.349s

and well wait a bit for everything to be ready.

  • Then open http://localhost:2984
  • and use the credentials rose@frama and password to login.
  • Messages (top left)
  • New private message, recipient http://mastodon/users/hippo press enter should display a dropdown, select hippo@mastodon
  • type in “prick” in the message box and hit send
  • http://localhost:2970/auth/sign_in and sign in hippo@mastodon.localhost and password
  • “Your home timeline is empty! Follow more people to fill it up.”
  • search for rose@mobilizon and see the message

These things are easy once you have the infrastructure.

Finally, you should stop the containers:

docker compose --file fediverse-pasture/mastodon.yml --file fediverse-pasture/mobilizon.yml down

nobody got the RAM to have every Fediverse applications in existence running.

2 Likes