James Smith // floppy.org.uk
@Floppy@mastodon.me.uk
Here is how platforms die: first, they are good to their users; then they abuse their users to make things better for their business customers; finally, they abuse those business customers to claw back all the value for themselves. Then, they die. I call this enshittification.- Cory Doctorow, 2023
The fediverse is a collection of community-owned, ad-free, decentralised, and privacy-centric social networks.- fediverse.to
Self-funding - people will pay!
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
application/activity+json
{
...
"id": "https://mastodon.me.uk/users/Floppy",
"type": "Person",
"following": "https://mastodon.me.uk/users/Floppy/following",
"followers": "https://mastodon.me.uk/users/Floppy/followers",
"inbox": "https://mastodon.me.uk/users/Floppy/inbox",
"outbox": "https://mastodon.me.uk/users/Floppy/outbox",
"featured": "https://mastodon.me.uk/users/Floppy/collections/featured",
"featuredTags": "https://mastodon.me.uk/users/Floppy/collections/tags",
"preferredUsername": "Floppy",
"name": "James Smith 💾",
"summary": "Generic humanoid carbon unit",
"url": "https://mastodon.me.uk/@Floppy",
...
}
www.w3.org/TR/activitystreams-core
{
...
"id":"https://mastodon.me.uk/users/Floppy/statuses/113293745221486905/activity",
"type":"Create",
"actor":"https://mastodon.me.uk/users/Floppy",
"published":"2024-10-12T09:29:20Z",
...
"object":{
...
}
}
{
...
"id":"https://mastodon.me.uk/users/Floppy/statuses/113293745221486905",
"type":"Note",
"inReplyTo":null,
"published":"2024-10-12T09:29:20Z",
"url":"https://mastodon.me.uk/@Floppy/113293745221486905",
"attributedTo":"https://mastodon.me.uk/users/Floppy",
"content":"Yay, #OggCamp!
",
"attachment":[
{
"type":"Document",
"mediaType":"image/png",
"url":"https://mastodon.me.uk/system/media_attachments/files/113/293/742/234/978/459/original/f0503c918aab45f5.png",
"name":"A view from the audience in a conference room, with an OggCamp 2024 logo on screen",
...
}
]
}
All public activities for a user.
Defined by to
and cc
fields
GET activities from outboxes
POST activities to relevant inboxes
{
...
"to":[
"https://www.w3.org/ns/activitystreams#Public"
],
"cc":[
"https://mastodon.me.uk/users/Floppy/followers"
],
...
}
From mastodon docs at docs.joinmastodon.org/spec/activitypub/#Mention
{
...
"publicKey": {
"id": "https://mastodon.me.uk/users/Floppy#main-key",
"owner": "https://mastodon.me.uk/users/Floppy",
"publicKeyPem": "-----BEGIN PUBLIC KEY----- MIIBIjANB...
...
...nQIDAQAB -----END PUBLIC KEY----- "
},
...
}
rsa_key = OpenSSL::PKey::RSA.new 2048
cipher = OpenSSL::Cipher.new('AES-128-CBC')
Signature:
keyId="https://my.example.com/actor#main-key",
headers="(request-target) host date digest",
signature="Y2FiYW...IxNGRiZDk4ZA=="
(request-target): post /users/username/inbox
host: mastodon.example
date: 18 Dec 2019 10:08:46 GMT
digest: sha-256=hcK0GZB1BM4R0eenYrj9clYBuyXs/lemt5iWRYmIX0A=
Signature:
keyId="https://my.example.com/actor#main-key",
headers="(request-target) host date digest",
signature="Y2FiYW...IxNGRiZDk4ZA=="
{server}/.well-known/webfinger?resource={uri}
application/jrd+json
acct:floppy@mastodon.me.uk
{
"subject": "acct:Floppy@mastodon.me.uk",
"aliases": [
"https://mastodon.me.uk/@Floppy",
"https://mastodon.me.uk/users/Floppy"
],
"links": [
...
{
"rel": "self",
"type": "application/activity+json",
"href": "https://mastodon.me.uk/users/Floppy"
},
...
]
}
{
"subject": "acct:Floppy@mastodon.me.uk",
...
"links": [
...
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://.../authorize_interaction?uri={uri}"
}
...
]
}
bundle add federails
# config/routes.rb
mount Federails::Engine => '/'
rails generate federails:install
rails generate federails:install:migrations
# app/models/user.rb
class User < ApplicationRecord
# Include the concern here:
include Federails::Entity
# Configure field names
acts_as_federails_actor username_field: :username, name_field: :name,
profile_url_method: :user_url
end
target = Federails::Actor.find_by_account "floppy@mastodon.me.uk"
user.actor.following_follows.create(target_actor: target)
Incoming requests:
class User < ApplicationModel
include Federails::Entity
after_follow :throw_party
end
Federails::Activity.create!(
actor: user.actor,
action: "Create",
entity: comment
)
class Comment < ApplicationRecord
def to_activitypub_object
{
id: url_for(self),
type: "Note",
content: comment
published: created_at.iso8601,
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [commenter.actor.followers_url]
}
end
end
...a bit like having your own Thingiverse
manyfold.app // @manyfold@3dp.chat
mastodon.me.uk // @Floppy@mastodon.me.uk