mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-10-31 22:19:00 +00:00
Merge branch 'main' into reactivation-bug
This commit is contained in:
commit
0832a2fa8e
3 changed files with 334 additions and 4 deletions
2
.github/workflows/prettier.yaml
vendored
2
.github/workflows/prettier.yaml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install modules
|
||||
run: npm install prettier
|
||||
run: npm install prettier@2.5.1
|
||||
|
||||
- name: Run Prettier
|
||||
run: npx prettier --check bookwyrm/static/js/*.js
|
||||
|
|
333
FEDERATION.md
Normal file
333
FEDERATION.md
Normal file
|
@ -0,0 +1,333 @@
|
|||
# Federation
|
||||
|
||||
BookWyrm uses the [ActivityPub](http://activitypub.rocks/) protocol to send and receive user activity between other BookWyrm instances and other services that implement ActivityPub. To handle book data, BookWyrm has a handful of extended Activity types which are not part of the standard, but are legible to other BookWyrm instances.
|
||||
|
||||
## Activities and Objects
|
||||
|
||||
### Users and relationships
|
||||
User relationship interactions follow the standard ActivityPub spec.
|
||||
|
||||
- `Follow`: request to receive statuses from a user, and view their statuses that have followers-only privacy
|
||||
- `Accept`: approves a `Follow` and finalizes the relationship
|
||||
- `Reject`: denies a `Follow`
|
||||
- `Block`: prevent users from seeing one another's statuses, and prevents the blocked user from viewing the actor's profile
|
||||
- `Update`: updates a user's profile and settings
|
||||
- `Delete`: deactivates a user
|
||||
- `Undo`: reverses a `Follow` or `Block`
|
||||
|
||||
### Activities
|
||||
- `Create/Status`: saves a new status in the database.
|
||||
- `Delete/Status`: Removes a status
|
||||
- `Like/Status`: Creates a favorite on the status
|
||||
- `Announce/Status`: Boosts the status into the actor's timeline
|
||||
- `Undo/*`,: Reverses a `Like` or `Announce`
|
||||
|
||||
### Collections
|
||||
User's books and lists are represented by [`OrderedCollection`](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection)
|
||||
|
||||
### Statuses
|
||||
|
||||
BookWyrm is focused on book reading activities - it is not a general-purpose messaging application. For this reason, BookWyrm only accepts status `Create` activities if they are:
|
||||
|
||||
- Direct messages (i.e., `Note`s with the privacy level `direct`, which mention a local user),
|
||||
- Related to a book (of a custom status type that includes the field `inReplyToBook`),
|
||||
- Replies to existing statuses saved in the database
|
||||
|
||||
All other statuses will be received by the instance inbox, but by design **will not be delivered to user inboxes or displayed to users**.
|
||||
|
||||
### Custom Object types
|
||||
|
||||
With the exception of `Note`, the following object types are used in Bookwyrm but are not currently provided with a custom JSON-LD `@context` extension IRI. This is likely to change in future to make them true deserialisable JSON-LD objects.
|
||||
|
||||
##### Note
|
||||
|
||||
Within BookWyrm a `Note` is constructed according to [the ActivityStreams vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note), however `Note`s can only be created as direct messages or as replies to other statuses. As mentioned above, this also applies to incoming `Note`s.
|
||||
|
||||
##### Review
|
||||
|
||||
A `Review` is a status in response to a book (indicated by the `inReplyToBook` field), which has a title, body, and numerical rating between 0 (not rated) and 5.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://example.net/user/library_lurker/review/2",
|
||||
"type": "Review",
|
||||
"published": "2023-06-30T21:43:46.013132+00:00",
|
||||
"attributedTo": "https://example.net/user/library_lurker",
|
||||
"content": "<p>This is an enjoyable book with great characters.</p>",
|
||||
"to": ["https://example.net/user/library_lurker/followers"],
|
||||
"cc": [],
|
||||
"replies": {
|
||||
"id": "https://example.net/user/library_lurker/review/2/replies",
|
||||
"type": "OrderedCollection",
|
||||
"totalItems": 0,
|
||||
"first": "https://example.net/user/library_lurker/review/2/replies?page=1",
|
||||
"last": "https://example.net/user/library_lurker/review/2/replies?page=1",
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
},
|
||||
"summary": "Spoilers ahead!",
|
||||
"tag": [],
|
||||
"attachment": [],
|
||||
"sensitive": true,
|
||||
"inReplyToBook": "https://example.net/book/1",
|
||||
"name": "What a cracking read",
|
||||
"rating": 4.5,
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
```
|
||||
|
||||
##### Comment
|
||||
|
||||
A `Comment` on a book mentions a book and has a message body, reading status, and progress indicator.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://example.net/user/library_lurker/comment/9",
|
||||
"type": "Comment",
|
||||
"published": "2023-06-30T21:43:46.013132+00:00",
|
||||
"attributedTo": "https://example.net/user/library_lurker",
|
||||
"content": "<p>This is a very enjoyable book so far.</p>",
|
||||
"to": ["https://example.net/user/library_lurker/followers"],
|
||||
"cc": [],
|
||||
"replies": {
|
||||
"id": "https://example.net/user/library_lurker/comment/9/replies",
|
||||
"type": "OrderedCollection",
|
||||
"totalItems": 0,
|
||||
"first": "https://example.net/user/library_lurker/comment/9/replies?page=1",
|
||||
"last": "https://example.net/user/library_lurker/comment/9/replies?page=1",
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
},
|
||||
"summary": "Spoilers ahead!",
|
||||
"tag": [],
|
||||
"attachment": [],
|
||||
"sensitive": true,
|
||||
"inReplyToBook": "https://example.net/book/1",
|
||||
"readingStatus": "reading",
|
||||
"progress": 25,
|
||||
"progressMode": "PG",
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
```
|
||||
|
||||
##### Quotation
|
||||
|
||||
A quotation (aka "quote") has a message body, an excerpt from a book including position as a page number or percentage indicator, and mentions a book.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://example.net/user/mouse/quotation/13",
|
||||
"url": "https://example.net/user/mouse/quotation/13",
|
||||
"inReplyTo": null,
|
||||
"published": "2020-05-10T02:38:31.150343+00:00",
|
||||
"attributedTo": "https://example.net/user/mouse",
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"cc": [
|
||||
"https://example.net/user/mouse/followers"
|
||||
],
|
||||
"sensitive": false,
|
||||
"content": "I really like this quote",
|
||||
"type": "Quotation",
|
||||
"replies": {
|
||||
"id": "https://example.net/user/mouse/quotation/13/replies",
|
||||
"type": "Collection",
|
||||
"first": {
|
||||
"type": "CollectionPage",
|
||||
"next": "https://example.net/user/mouse/quotation/13/replies?only_other_accounts=true&page=true",
|
||||
"partOf": "https://example.net/user/mouse/quotation/13/replies",
|
||||
"items": []
|
||||
}
|
||||
},
|
||||
"inReplyToBook": "https://example.net/book/1",
|
||||
"quote": "To be or not to be, that is the question.",
|
||||
"position": 50,
|
||||
"positionMode": "PCT",
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Objects
|
||||
|
||||
##### Work
|
||||
A particular book, a "work" in the [FRBR](https://en.wikipedia.org/wiki/Functional_Requirements_for_Bibliographic_Records) sense.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://bookwyrm.social/book/5988",
|
||||
"type": "Work",
|
||||
"authors": [
|
||||
"https://bookwyrm.social/author/417"
|
||||
],
|
||||
"first_published_date": null,
|
||||
"published_date": null,
|
||||
"title": "Piranesi",
|
||||
"sort_title": null,
|
||||
"subtitle": null,
|
||||
"description": "**From the *New York Times* bestselling author of *Jonathan Strange & Mr. Norrell*, an intoxicating, hypnotic new novel set in a dreamlike alternative reality.",
|
||||
"languages": [],
|
||||
"series": null,
|
||||
"series_number": null,
|
||||
"subjects": [
|
||||
"English literature"
|
||||
],
|
||||
"subject_places": [],
|
||||
"openlibrary_key": "OL20893680W",
|
||||
"librarything_key": null,
|
||||
"goodreads_key": null,
|
||||
"attachment": [
|
||||
{
|
||||
"url": "https://bookwyrm.social/images/covers/10226290-M.jpg",
|
||||
"type": "Image"
|
||||
}
|
||||
],
|
||||
"lccn": null,
|
||||
"editions": [
|
||||
"https://bookwyrm.social/book/5989"
|
||||
],
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
```
|
||||
|
||||
##### Edition
|
||||
A particular _manifestation_ of a Work, in the [FRBR](https://en.wikipedia.org/wiki/Functional_Requirements_for_Bibliographic_Records) sense.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://bookwyrm.social/book/5989",
|
||||
"lastEditedBy": "https://example.net/users/rat",
|
||||
"type": "Edition",
|
||||
"authors": [
|
||||
"https://bookwyrm.social/author/417"
|
||||
],
|
||||
"first_published_date": null,
|
||||
"published_date": "2020-09-15T00:00:00+00:00",
|
||||
"title": "Piranesi",
|
||||
"sort_title": null,
|
||||
"subtitle": null,
|
||||
"description": "Piranesi's house is no ordinary building; its rooms are infinite, its corridors endless, its walls are lined with thousands upon thousands of statues, each one different from all the others.",
|
||||
"languages": [
|
||||
"English"
|
||||
],
|
||||
"series": null,
|
||||
"series_number": null,
|
||||
"subjects": [],
|
||||
"subject_places": [],
|
||||
"openlibrary_key": "OL29486417M",
|
||||
"librarything_key": null,
|
||||
"goodreads_key": null,
|
||||
"isfdb": null,
|
||||
"attachment": [
|
||||
{
|
||||
"url": "https://bookwyrm.social/images/covers/50202953._SX318_.jpg",
|
||||
"type": "Image"
|
||||
}
|
||||
],
|
||||
"isbn_10": "1526622424",
|
||||
"isbn_13": "9781526622426",
|
||||
"oclc_number": null,
|
||||
"asin": null,
|
||||
"pages": 272,
|
||||
"physical_format": null,
|
||||
"publishers": [
|
||||
"Bloomsbury Publishing Plc"
|
||||
],
|
||||
"work": "https://bookwyrm.social/book/5988",
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
```
|
||||
|
||||
#### Shelf
|
||||
|
||||
A user's book collection. By default, every user has a `to-read`, `reading`, `read`, and `stopped-reading` shelf which are used to track reading progress. Users may create an unlimited number of additional shelves with their own ids.
|
||||
|
||||
Example
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://example.net/user/avid_reader/books/extraspecialbooks-5",
|
||||
"type": "Shelf",
|
||||
"totalItems": 0,
|
||||
"first": "https://example.net/user/avid_reader/books/extraspecialbooks-5?page=1",
|
||||
"last": "https://example.net/user/avid_reader/books/extraspecialbooks-5?page=1",
|
||||
"name": "Extra special books",
|
||||
"owner": "https://example.net/user/avid_reader",
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"cc": [
|
||||
"https://example.net/user/avid_reader/followers"
|
||||
],
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
```
|
||||
|
||||
#### List
|
||||
|
||||
A collection of books that may have items contributed by users other than the one who created the list.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://example.net/list/1",
|
||||
"type": "BookList",
|
||||
"totalItems": 0,
|
||||
"first": "https://example.net/list/1?page=1",
|
||||
"last": "https://example.net/list/1?page=1",
|
||||
"name": "My cool list",
|
||||
"owner": "https://example.net/user/avid_reader",
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"cc": [
|
||||
"https://example.net/user/avid_reader/followers"
|
||||
],
|
||||
"summary": "A list of books I like.",
|
||||
"curation": "curated",
|
||||
"@context": "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
```
|
||||
|
||||
#### Activities
|
||||
|
||||
- `Create`: Adds a shelf or list to the database.
|
||||
- `Delete`: Removes a shelf or list.
|
||||
- `Add`: Adds a book to a shelf or list.
|
||||
- `Remove`: Removes a book from a shelf or list.
|
||||
|
||||
## Alternative Serialization
|
||||
Because BookWyrm uses custom object types that aren't listed in [the standard ActivityStreams Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary), some statuses are transformed into standard types when sent to or viewed by non-BookWyrm services. `Review`s are converted into `Article`s, and `Comment`s and `Quotation`s are converted into `Note`s, with a link to the book and the cover image attached.
|
||||
|
||||
In future this may be done with [JSON-LD type arrays](https://www.w3.org/TR/json-ld/#specifying-the-type) instead.
|
||||
|
||||
## Other extensions
|
||||
|
||||
### Webfinger
|
||||
|
||||
Bookwyrm uses the [Webfinger](https://datatracker.ietf.org/doc/html/rfc7033) standard to identify and disambiguate fediverse actors. The [Webfinger documentation on the Mastodon project](https://docs.joinmastodon.org/spec/webfinger/) provides a good overview of how Webfinger is used.
|
||||
|
||||
### HTTP Signatures
|
||||
|
||||
Bookwyrm uses and requires HTTP signatures for all `POST` requests. `GET` requests are not signed by default, but if Bookwyrm receives a `403` response to a `GET` it will re-send the request, signed by the default server user. This usually will have a user id of `https://example.net/user/bookwyrm.instance.actor`
|
||||
|
||||
#### publicKey id
|
||||
|
||||
In older versions of Bookwyrm the `publicKey.id` was incorrectly listed in request headers as `https://example.net/user/username#main-key`. As of v0.6.3 the id is now listed correctly, as `https://example.net/user/username/#main-key`. In most ActivityPub implementations this will make no difference as the URL will usually resolve to the same place.
|
||||
|
||||
### NodeInfo
|
||||
|
||||
Bookwyrm uses the [NodeInfo](http://nodeinfo.diaspora.software/) standard to provide statistics and version information for each instance.
|
||||
|
||||
## Further Documentation
|
||||
|
||||
See [docs.joinbookwyrm.com/](https://docs.joinbookwyrm.com/) for more documentation.
|
|
@ -40,9 +40,6 @@ let BookWyrm = new (class {
|
|||
|
||||
document.querySelectorAll("details.dropdown").forEach((node) => {
|
||||
node.addEventListener("toggle", this.handleDetailsDropdown.bind(this));
|
||||
node.querySelectorAll("[data-modal-open]").forEach((modal_node) =>
|
||||
modal_node.addEventListener("click", () => (node.open = false))
|
||||
);
|
||||
});
|
||||
|
||||
document
|
||||
|
|
Loading…
Reference in a new issue