From 69a06c83d78a74d66e218c4310f0d0eb6c549cd4 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 25 Nov 2023 17:28:22 -1000 Subject: [PATCH] Add more actions and server metadata --- docs/objects/actions.md | 38 ++++++++++ docs/objects/announce.md | 17 +++++ docs/objects/dislike.md | 17 +++++ docs/objects/follow-accept.md | 17 +++++ docs/objects/follow-reject.md | 17 +++++ docs/objects/follow.md | 17 +++++ docs/objects/like.md | 17 +++++ docs/objects/server-metadata.md | 122 ++++++++++++++++++++++++++++++++ docs/objects/undo.md | 25 +++++++ 9 files changed, 287 insertions(+) create mode 100644 docs/objects/announce.md create mode 100644 docs/objects/dislike.md create mode 100644 docs/objects/follow-accept.md create mode 100644 docs/objects/follow-reject.md create mode 100644 docs/objects/follow.md create mode 100644 docs/objects/like.md create mode 100644 docs/objects/server-metadata.md create mode 100644 docs/objects/undo.md diff --git a/docs/objects/actions.md b/docs/objects/actions.md index e69de29..8eae14d 100644 --- a/docs/objects/actions.md +++ b/docs/objects/actions.md @@ -0,0 +1,38 @@ +# Actions + +Actions are the main way that clients interact with the Lysand protocol. They are JSON objects that represent an action that a user wants to perform, such as posting a new object or following a user. + +Here is an example action: +```json5 +{ + "type": "Like", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "created_at": "2021-01-01T00:00:00.000Z", + "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19" +} +``` + +## Type + +Currently available types are: +- [`Like`](/objects/like) +- [`Dislike`](/objects/dislike) +- [`Follow`](/objects/follow) +- [`FollowAccept`](/objects/follow-accept) +- [`FollowReject`](/objects/follow-reject) +- [`Announce`](/objects/announce) +- [`Undo`](/objects/undo) + +Notably, a `Block` action is not included in the Lysand protocol. This is because Lysand does not have a concept of blocking users. Instead, it is up to the client or server to decide if it wants to display content from a user or not. + +This serves to prevent abuse of the protocol to find out if a user has blocked another user, which is a privacy concern. + +## Fields + +### Author + +The `author` field on an Action is a string that represents the URI of the user that created the action. It is used to identify the author of the action. + +The `author` field is required on all actions. diff --git a/docs/objects/announce.md b/docs/objects/announce.md new file mode 100644 index 0000000..9001bbc --- /dev/null +++ b/docs/objects/announce.md @@ -0,0 +1,17 @@ +# Announce + +An `Announce` action is an action that represents a user announcing an object. It is used to share an object with the user's followers. This is similar to "retweeting" on Twitter. + +An `Announce` object **MUST** have an `object` field that contains the URI of the object that the user is announcing. The object **MUST** be a `Publication` object. + +Example: +```json5 +{ + "type": "Announce", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19" +} +``` diff --git a/docs/objects/dislike.md b/docs/objects/dislike.md new file mode 100644 index 0000000..7a896d4 --- /dev/null +++ b/docs/objects/dislike.md @@ -0,0 +1,17 @@ +# Dislike + +A `Dislike` action is an action that represents a user disliking an object. It is one of the most common type of action. + +A `Dislike` object **MUST** have an `object` field that contains the URI of the object that the user is disliking. The object **MUST** be a `Publication` object. + +Example: +```json5 +{ + "type": "Dislike", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19" +} +``` diff --git a/docs/objects/follow-accept.md b/docs/objects/follow-accept.md new file mode 100644 index 0000000..9ccad98 --- /dev/null +++ b/docs/objects/follow-accept.md @@ -0,0 +1,17 @@ +# Follow Accept + +A `FollowAccept` action is an action that represents a user accepting a follow request from another user. By accepting a follow request, the user will be able to see the other user's posts in their feed. + +A `FollowAccept` object **MUST** have an `follower` field that contains the URI of the user that the user is accepting a follow request from. + +Example: +```json5 +{ + "type": "FollowAccept", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "follower": "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7" +} +``` \ No newline at end of file diff --git a/docs/objects/follow-reject.md b/docs/objects/follow-reject.md new file mode 100644 index 0000000..a35bd78 --- /dev/null +++ b/docs/objects/follow-reject.md @@ -0,0 +1,17 @@ +# Follow Reject + +A `FollowReject` action is an action that represents a user rejecting a follow request from another user. By rejecting a follow request, the user will not be able to see the other user's posts in their feed. + +A `FollowReject` object **MUST** have an `follower` field that contains the URI of the user that the user is rejecting a follow request from. + +Example: +```json5 +{ + "type": "FollowReject", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "follower": "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7" +} +``` diff --git a/docs/objects/follow.md b/docs/objects/follow.md new file mode 100644 index 0000000..a89eef9 --- /dev/null +++ b/docs/objects/follow.md @@ -0,0 +1,17 @@ +# Follow + +A `Follow` action is an action that represents a user following another user. By following another user, the user will be able to see the other user's posts in their feed. + +A `Follow` object **MUST** have an `followee` field that contains the URI of the user that the user is following. + +Example: +```json5 +{ + "type": "Follow", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "followee": "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7" +} +``` diff --git a/docs/objects/like.md b/docs/objects/like.md new file mode 100644 index 0000000..6d886df --- /dev/null +++ b/docs/objects/like.md @@ -0,0 +1,17 @@ +# Like + +A `Like` action is an action that represents a user liking/favouriting an object. It is one of the most common type of action. + +A `Like` object **MUST** have an `object` field that contains the URI of the object that the user is liking. The object **MUST** be a `Publication` object. + +Example: +```json5 +{ + "type": "Like", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19" +} +``` \ No newline at end of file diff --git a/docs/objects/server-metadata.md b/docs/objects/server-metadata.md new file mode 100644 index 0000000..9790781 --- /dev/null +++ b/docs/objects/server-metadata.md @@ -0,0 +1,122 @@ +# Server Metadata + +Server metadata is metadata that servers can provide to clients to help them determine how to interact with the server. It is meant to be a simple way for servers to provide information to other servers and clients. + +Unlike other objects, server metadata is not meant to be federated. The `id`, `uri` and `created_at` fields are not required on server metadata objects. + +Here is an example server metadata object: +```json5 +{ + "type": "ServerMetadata", + "name": "Example Server", + "version": "1.0.0", + "description": "This is an example server.", + "website": "https://example.com", + "moderators": [ + "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7", + // ... + ], + "admins": [ + // ... + ], + "logo": [ + { + "content": "https://cdn.example.com/logo.png", + "content_type": "image/png" + }, + { + "content": "https://cdn.example.com/logo.webp", + "content_type": "image/webp" + } + ], + "banner": [ + { + "content": "https://cdn.example.com/banner.png", + "content_type": "image/png" + }, + { + "content": "https://cdn.example.com/banner.webp", + "content_type": "image/webp" + } + ], + "supported_extensions": [ "org.lysand:reactions" ], + "extensions": { + // Example extension + "org.joinmastodon:monthly_active_users": 1000 + } +} +``` + +## Fields + +### Type + +The `type` field on a Server Metadata object is a string that represents the type of the object. It is used to determine how the object should be displayed to the user. It should be `ServerMetadata`. + +### Name + +The `name` field on a Server Metadata object is a string that represents the name of the server. The `name` field is required on all Server Metadata objects. + +It is recommended that servers limit the length of the name from 1 to 50 characters, but it is up to the server to decide how long the name can be. The protocol does not have an upper limit for the length of the name. + +### Version + +The `version` field on a Server Metadata object is a string that represents the version of the server. It is recommended that servers use [SemVer](https://semver.org) to version their servers, but it is not required. The protocol does not have any requirements for the format of the version. + +The `version` field is not required on all Server Metadata objects. If it is not provided, it is assumed that the server does not have a version. + +### Description + +The `description` field on a Server Metadata object is a string that represents the description of the server. It should include information about the server, such as what it is about and what it is used for. + +For example, a server focused on a specific topic may include information about that topic in the description. + +The `description` field is not required on all Server Metadata objects. If it is not provided, it is assumed that the server does not have a description. + +It is recommended that servers limit the length of the description from 1 to 500 characters, but it is up to the server to decide how long the description can be. The protocol does not have an upper limit for the length of the description. + +### Website + +The `website` field on a Server Metadata object is a string that represents the website of the server. his may be used to link to the server's website, such as a status page or a public modlog. + +The `website` field is not required on Server Metadata objects. If it is not provided, it is assumed that the server does not have a website. + +### Moderators + +The `moderators` field on a Server Metadata object is an array of URIs that represent the moderators of the server. + +The `moderators` field is not required on all Server Metadata objects. If it is not provided, it is assumed that the server does not have any moderators, or is not willing to provide a list. + +### Admins + +The `admins` field on a Server Metadata object is an array of URIs that represent the admins of the server. + +The `admins` field is not required on all Server Metadata objects. If it is not provided, it is assumed that the server does not have any admins, or is not willing to provide a list. + +### Logo + +The `logo` field on a Server Metadata object is an array of `ContentFormat` objects. It is meant to serve as a logo for the server. + +The `logo` field is not required on all Server Metadata objects. If it is not provided, it is assumed that the server does not have a logo. + +The logo content_type **MUST** be an image format, such as `image/png` or `image/jpeg`. The logo content_type **MUST NOT** be a video format, such as `video/mp4` or `video/webm`. + +Lysand heavily recommends that servers provide both the original format and a modern format for each logo, such as WebP, AVIF, JXL, or HEIF. This is to reduce bandwidth usage and improve performance for clients. + +Clients should display the most modern format that they support, such as WebP, AVIF, JXL, or HEIF. If the client does not support any modern formats, it should display the original format. + +> **Note:** Servers may find it useful to use a CDN that can automatically convert images to modern formats, such as Cloudflare. This will offload image processing from the server, and improve performance for clients. + +### Banner + +The `banner` field on a Server Metadata object is an array of `ContentFormat` objects. It is meant to serve as a banner for the server. + +The `banner` field is not required on all Server Metadata objects. If it is not provided, it is assumed that the server does not have a banner. + +The banner content_type **MUST** be an image format, such as `image/png` or `image/jpeg`. The banner content_type **MUST NOT** be a video format, such as `video/mp4` or `video/webm`. + +Lysand heavily recommends that servers provide both the original format and a modern format for each banner, such as WebP, AVIF, JXL, or HEIF. This is to reduce bandwidth usage and improve performance for clients. + +Clients should display the most modern format that they support, such as WebP, AVIF, JXL, or HEIF. If the client does not support any modern formats, it should display the original format. + +> **Note:** Servers may find it useful to use a CDN that can automatically convert images to modern formats, such as Cloudflare. This will offload image processing from the server, and improve performance for clients. \ No newline at end of file diff --git a/docs/objects/undo.md b/docs/objects/undo.md new file mode 100644 index 0000000..cc7f4bb --- /dev/null +++ b/docs/objects/undo.md @@ -0,0 +1,25 @@ +##### 1.6.3.1.7. Undo + +An `Undo` action is an action that represents a user undoing an action. It is used to cancel an action or delete an already existing object. + +An `Undo` object **MUST** have an `object` field that contains the URI of the object that the user is undoing. The object **MUST** be a `Publication` object. + +Servers **MUST** not allow users to undo actions that they did not create. + +Servers that receive `Undo` actions **MUST** undo the action that is being undone. For example, if a user likes a post, and then undoes the like, the server **MUST** remove the like from the post. Similarly, if an `Undo` action is received for a `Follow` action, the server **MUST** unfollow the user. + +If the `Undo` action has a Publication or other object as the `object` field, the server **MUST** stop showing the object to users. Deleting the original object is recommended, but not required. + +An `Undo` action on a `Patch` object **MUST** be treated as cancellation of the `Note` object, not of the patch itself. + +Example: +```json5 +{ + "type": "Undo", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19" +} +```