From 09255e8beae5a59f06cd4522cbd5a6ec4d80c54b Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 5 Jul 2019 17:01:54 +0200 Subject: [PATCH] Start converting to readthedocs Signed-off-by: Joas Schilling --- .gitignore | 3 + docs/api-v1.md | 692 ---------------------------- docs/call.md | 42 ++ docs/capabilities.md | 34 ++ docs/chat.md | 151 ++++++ docs/commands.md | 22 +- docs/constants.md | 25 + docs/conversation.md | 218 +++++++++ docs/index.md | 12 + docs/internal-signaling.md | 40 ++ docs/participant.md | 182 ++++++++ docs/standalone-signaling-api-v1.md | 4 +- mkdocs.yml | 29 ++ 13 files changed, 751 insertions(+), 703 deletions(-) delete mode 100644 docs/api-v1.md create mode 100644 docs/call.md create mode 100644 docs/capabilities.md create mode 100644 docs/chat.md create mode 100644 docs/constants.md create mode 100644 docs/conversation.md create mode 100644 docs/index.md create mode 100644 docs/internal-signaling.md create mode 100644 docs/participant.md create mode 100644 mkdocs.yml diff --git a/.gitignore b/.gitignore index 84b64c151..a18f82bd2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ build node_modules +# Local docs +/site + # Karma/jasmine coverage data coverage tests/php/coverage-html diff --git a/docs/api-v1.md b/docs/api-v1.md deleted file mode 100644 index 380470d3d..000000000 --- a/docs/api-v1.md +++ /dev/null @@ -1,692 +0,0 @@ -# API v1 Documentation - -- [Constants](#constants) - * [Conversation types](#conversation-types) - * [Read-only states](#read-only-states) - * [Participant types](#participant-types) - * [Actor types of chat messages](#actor-types-of-chat-messages) -- [Conversation management](#conversation-management) - * [Creating a new conversation](#creating-a-new-conversation) - * [Get user´s conversations](#get-user-s-conversations) - * [Get single conversation (also for guests)](#get-single-conversation-also-for-guests) - * [Rename a conversation](#rename-a-conversation) - * [Set read-only for a conversation](#set-read-only-for-a-conversation) - * [Set password for a conversation](#set-password-for-a-conversation) - * [Delete a conversation](#delete-a-conversation) - * [Allow guests in a conversation (public conversation)](#allow-guests-in-a-conversation-public-conversation) - * [Disallow guests in a conversation (group conversation)](#disallow-guests-in-a-conversation-group-conversation) - * [Add conversation to favorites](#add-conversation-to-favorites) - * [Remove conversation from favorites](#remove-conversation-from-favorites) - * [Set notification level](#set-notification-level) -- [Participant management](#participant-management) - * [Get list of participants in a conversation](#get-list-of-participants-in-a-conversation) - * [Add a participant to a conversation](#add-a-participant-to-a-conversation) - * [Delete a participant from a conversation](#delete-a-participant-from-a-conversation) - * [Remove yourself from a conversation](#remove-yourself-from-a-conversation) - * [Promote a user to a moderator](#promote-a-user-to-a-moderator) - * [Demote a moderator to a user](#demote-a-moderator-to-a-user) -- [Call management](#call-management) - * [Get list of connected participants](#get-list-of-connected-participants) - * [Join a call](#join-a-call) - * [Send ping to keep the call alive](#send-ping-to-keep-the-call-alive) - * [Leave a call (but staying in the conversation for future calls)](#leave-a-call-but-staying-in-the-conversation-for-future-calls) -- [Chat](#chat) - * [Receive chat messages of a conversation](#receive-chat-messages-of-a-conversation) - * [Sending a new chat message](#sending-a-new-chat-message) - * [Get mention autocomplete suggestions](#get-mention-autocomplete-suggestions) - * [System messages](#system-messages) -- [Guests](#guests) - * [Set display name](#set-display-name) -- [Signaling](#signaling) - * [Get signaling settings](#get-signaling-settings) - * [External signaling API](#external-signaling-api) - - -Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` - -## Constants - -### Conversation types -* `1` "one to one" -* `2` group -* `3` public -* `4` changelog - -### Read-only states -* `0` read-write -* `1` read-only - -### Participant types -* `1` owner -* `2` moderator -* `3` user -* `4` guest -* `5` user following a public link - -### Actor types of chat messages -* `guests` - guest users -* `users` - logged-in users -* `bots` - used by commands (actor-id is the used `/command`) and the changelog conversation (actor-id is `changelog`) - -## Capabilities - -### 3.0 (Initial Talk release) -* `audio` - audio is supported -* `video` - video + screensharing is supported -* `chat` - simple text chat is supported, superseded by `chat-v2` - -### 3.1 -* `guest-signaling` - Guests can do signaling via api endpoints -* `empty-group-room` - Group conversations can be created without inviting a Nextcloud user group by default - -### 3.2 -* `guest-display-names` - Display names of guests are stored in the database, can be set via API (not WebRTC only) and are used on returned comments/participants/etc. -* `multi-room-users` - Users can be in multiple conversations at the same time now, therefor signaling now also requires the conversation token on the URL. -* `chat-v2` - Chat messages are now [Rich Object Strings](https://github.com/nextcloud/server/issues/1706) and pagination is available, the previous `chat` is not available anymore. - -### 4.0 -* `favorites` - Conversations can be marked as favorites which will pin them to the top of the conversation list. -* `last-room-activity` - Conversations have the `lastActivity` attribute and should be sorted by that instead of the last ping of the user. -* `no-ping` - The ping endpoint has been removed. Ping is updated with a call to fetch the signaling or chat messages instead. -* `system-messages` - Chat messages have a `systemMessage` attribute and can be generated by the system -* `mention-flag` - The conversation list populates the boolean `unreadMention` when the user was mentioned since their last visit -* `in-call-flags` - A new flag `participantFlags` has been introduced and is replacing the `participantInCall` boolean. - -### 5.0 -* `invite-by-mail` - *Replaced by `invite-groups-and-mails`* Guests can be invited with their email address -* `notification-levels` - Users can select when they want to be notified in conversations -* `invite-groups-and-mails` - Groups can be added to existing conversations via the add participant endpoint - -### 6.0 -* `locked-one-to-one-rooms` - One-to-one conversations are now locked to the users. Neither guests nor other participants can be added, so the options to do that should be hidden as well. Also a user can only leave a one-to-one conversation (not delete). It will be deleted when the other participant left too. If the other participant posts a new chat message or starts a call, the left-participant will be re-added. -* `read-only-rooms` - Conversations can be in `read-only` mode which means people can not do calls or write chat messages. - -## Conversation management - -### Creating a new conversation - -* Method: `POST` -* Endpoint: `/room` -* Data: - - field | type | Description - ------|------|------------ - `roomType` | int | - `invite` | string | user id (`roomType = 1`), group id (`roomType = 2` - optional) - `roomName` | string | conversation name (Not available for `roomType = 1`) - -* Response: - - Header: - + `200 OK` when the "one to one" conversation already exists - + `201 Created` when the conversation was created - + `400 Bad Request` when an invalid conversation type was given - + `401 Unauthorized` when the user is not logged in - + `404 Not Found` when the user or group does not exist - - - Data: - - field | type | Description - ------|------|------------ - `token` | string | Token identifier of the conversation which is used for further interaction - `name` | string | Name of the conversation (can also be empty) - `displayName` | string | `name` if non empty, otherwise it falls back to a list of participants - -### Get user´s conversations - -* Method: `GET` -* Endpoint: `/room` - -* Response: - - Header: - + `200 OK` - + `401 Unauthorized` when the user is not logged in - - - Data: - Array of conversations, each conversation has at least: - - field | type | Description - ------|------|------------ - `token` | string | Token identifier of the conversation which is used for further interaction - `type` | int | - `name` | string | Name of the conversation (can also be empty) - `displayName` | string | `name` if non empty, otherwise it falls back to a list of participants - `participantType` | int | Permissions level of the current user - `participantInCall` | bool | Flag if the current user is in the call (deprecated, use `participantFlags` instead) - `participantFlags` | int | Flags of the current user (only available with `in-call-flags` capability) - `readOnly` | int | Read-only state for the current user (only available with `read-only-rooms` capability) - `count` | int | Number of active users - `numGuests` | int | Number of active guests - `lastPing` | int | Timestamp of the last ping of the current user (should be used for sorting) - `sessionId` | string | `'0'` if not connected, otherwise a 512 character long string - `hasPassword` | bool | Flag if the conversation has a password - `hasCall` | bool | Flag if the conversation has an active call - `lastActivity` | int | Timestamp of the last activity in the conversation, in seconds and UTC time zone - `isFavorite` | bool | Flag if the conversation is favorited by the user - `notificationLevel` | int | The notification level for the user (one of `Participant::NOTIFY_*` (1-3)) - `unreadMessages` | int | Number of unread chat messages in the conversation (only available with `chat-v2` capability) - `unreadMention` | bool | Flag if the user was mentioned since their last visit - `lastMessage` | message | Last message in a conversation if available, otherwise empty - `objectType` | string | The type of object that the conversation is associated with; "share:password" if the conversation is used to request a password for a share, otherwise empty - `objectId` | string | Share token if "objectType" is "share:password", otherwise empty - -### Get single conversation (also for guests) - -* Method: `GET` -* Endpoint: `/room/{token}` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant - - - Data: See array definition in `Get user´s conversations` - -### Rename a conversation - -* Method: `PUT` -* Endpoint: `/room/{token}` -* Data: - - field | type | Description - ------|------|------------ - `roomName` | string | New name for the conversation (1-200 characters) - -* Response: - - Header: - + `200 OK` - + `400 Bad Request` When the name is too long or empty - + `403 Forbidden` When the current user is not a moderator/owner - + `404 Not Found` When the conversation could not be found for the participant - + `405 Method Not Allowed` When the conversation is a one to one conversation - -### Set read-only for a conversation - -* Method: `PUT` -* Endpoint: `/room/{token}/read-only` -* Data: - - field | type | Description - ------|------|------------ - `state` | int | New state for the conversation - -* Response: - - Header: - + `200 OK` - + `400 Bad Request` When the conversation type does not support read-only (only group and public conversation atm) - + `403 Forbidden` When the current user is not a moderator/owner or the conversation is not a public conversation - + `404 Not Found` When the conversation could not be found for the participant - -### Set password for a conversation - -* Method: `PUT` -* Endpoint: `/room/{token}/password` -* Data: - - field | type | Description - ------|------|------------ - `password` | string | New password for the conversation - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the current user is not a moderator/owner or the conversation is not a public conversation - + `404 Not Found` When the conversation could not be found for the participant - -### Delete a conversation - -* Method: `DELETE` -* Endpoint: `/room/{token}` - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the current user is not a moderator/owner - + `404 Not Found` When the conversation could not be found for the participant - -### Allow guests in a conversation (public conversation) - -* Method: `POST` -* Endpoint: `/room/{token}/public` - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the current user is not a moderator/owner - + `404 Not Found` When the conversation could not be found for the participant - -### Disallow guests in a conversation (group conversation) - -* Method: `DELETE` -* Endpoint: `/room/{token}/public` - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the current user is not a moderator/owner - + `404 Not Found` When the conversation could not be found for the participant - -### Set conversation password - -* Method: `PUT` -* Endpoint: `/room/{token}/password` -* Data: - - field | type | Description - ------|------|------------ - `password` | string | Set a new password for the conversation - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the current user is not a moderator/owner - + `403 Forbidden` When the conversation is not a public conversation - + `404 Not Found` When the conversation could not be found for the participant - -### Add conversation to favorites - -* Method: `POST` -* Endpoint: `/room/{token}/favorite` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant or the participant is a guest - -### Remove conversation from favorites - -* Method: `DELETE` -* Endpoint: `/room/{token}/favorite` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant or the participant is a guest - -### Set notification level - -* Method: `POST` -* Endpoint: `/room/{token}/notify` -* Data: - - field | type | Description - ------|------|------------ - `level` | int | The notification level (one of `Participant::NOTIFY_*` (1-3)) - -* Response: - - Header: - + `200 OK` - + `400 Bad Request` When the the given level is invalid - + `404 Not Found` When the conversation could not be found for the participant or the participant is a guest - -## Participant management - -### Get list of participants in a conversation - -* Method: `GET` -* Endpoint: `/room/{token}/participants` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant - - - Data: - Array of participants, each participant has at least: - - field | type | Description - ------|------|------------ - `userId` | string | Is empty for guests - `displayName` | string | Can be empty for guests - `participantType` | int | Permissions level of the participant - `lastPing` | int | Timestamp of the last ping of the user (should be used for sorting) - `sessionId` | string | `'0'` if not connected, otherwise a 512 character long string - -### Add a participant to a conversation - -* Method: `POST` -* Endpoint: `/room/{token}/participants` -* Data: - - field | type | Description - ------|------|------------ - `newParticipant` | string | User, group or email to add - `source` | string | Source of the participant(s) as returned by the autocomplete suggestion endpoint (default is `users`) - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the current user is not a moderator/owner - + `400 Bad Request` When the source type is unknown - + `404 Not Found` When the conversation could not be found for the participant - + `404 Not Found` When the user or group to add could not be found - - - Data: - - field | type | Description - ------|------|------------ - `type` | int | In case the conversation type changed, the new value is returned - -### Delete a participant from a conversation - -* Method: `DELETE` -* Endpoint: `/room/{token}/participants` -* Data: - - field | type | Description - ------|------|------------ - `participant` | string | User to remove - -* Response: - - Header: - + `200 OK` - + `400 Bad Request` When the participant is a moderator/owner and there are no other moderators/owners left. - + `403 Forbidden` When the current user is not a moderator/owner - + `403 Forbidden` When the participant to remove is an owner - + `404 Not Found` When the conversation could not be found for the participant - + `404 Not Found` When the participant to remove could not be found - -### Remove a guest from a conversation - -* Method: `DELETE` -* Endpoint: `/room/{token}/participants/guests` -* Data: - - field | type | Description - ------|------|------------ - `participant` | string | Session ID of the guest to remove - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the current user is not a moderator/owner - + `403 Forbidden` When the target participant is not a guest - + `404 Not Found` When the conversation could not be found for the participant - + `404 Not Found` When the target participant could not be found - -### Remove yourself from a conversation - -* Method: `DELETE` -* Endpoint: `/room/{token}/participants/self` - -* Response: - - Header: - + `200 OK` - + `400 Bad Request` When the participant is a moderator/owner and there are no other moderators/owners left. - + `404 Not Found` When the conversation could not be found for the participant - -### Join a conversation (available for call and chat) - -* Method: `POST` -* Endpoint: `/room/{token}/participants/active` -* Data: - - field | type | Description - ------|------|------------ - `password` | string | Optional: Password is only required for users which are of type `4` or `5` and only when the conversation has `hasPassword` set to true. - -* Response: - - Header: - + `200 OK` - + `403 Forbidden` When the password is required and didn't match - + `404 Not Found` When the conversation could not be found for the participant - - - Data: - - field | type | Description - ------|------|------------ - `sessionId` | string | 512 character long string - -### Leave a conversation (not available for call and chat anymore) - -* Method: `DELETE` -* Endpoint: `/room/{token}/participants/active` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant - -### Promote a user to a moderator - -* Method: `POST` -* Endpoint: `/room/{token}/moderators` -* Data: - - field | type | Description - ------|------|------------ - `participant` | string | User to promote - -* Response: - - Header: - + `200 OK` - + `400 Bad Request` When the participant to promote is not a normal user (type `3`) - + `403 Forbidden` When the current user is not a moderator/owner - + `403 Forbidden` When the participant to remove is an owner - + `404 Not Found` When the conversation could not be found for the participant - + `404 Not Found` When the participant to remove could not be found - -### Demote a moderator to a user - -* Method: `DELETE` -* Endpoint: `/room/{token}/moderators` -* Data: - - field | type | Description - ------|------|------------ - `participant` | string | User to promote - -* Response: - - Header: - + `200 OK` - + `400 Bad Request` When the participant to demote is not a moderator (type `2`) - + `403 Forbidden` When the current user is not a moderator/owner - + `404 Not Found` When the conversation could not be found for the participant - + `404 Not Found` When the participant to demote could not be found - - -## Call management - -### Get list of connected participants - -* Method: `GET` -* Endpoint: `/call/{token}` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant - - - Data: - Array of participants, each participant has at least: - - field | type | Description - ------|------|------------ - `userId` | string | Is empty for guests - `lastPing` | int | Timestamp of the last ping of the user (should be used for sorting) - `sessionId` | string | 512 character long string - -### Join a call - -* Method: `POST` -* Endpoint: `/call/{token}` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant - -### Leave a call (but staying in the conversation for future calls and chat) - -* Method: `DELETE` -* Endpoint: `/call/{token}` - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant - -## Chat - -### Receive chat messages of a conversation - -* Method: `GET` -* Endpoint: `/chat/{token}` -* Data: - - field | type | Description - ------|------|------------ - `lookIntoFuture` | int | `1` Poll and wait for new message or `0` get history of a conversation - `limit` | int | Number of chat messages to receive (100 by default, 200 at most) - `timeout` | int | `$lookIntoFuture = 1` only, Number of seconds to wait for new messages (30 by default, 60 at most) - `lastKnownMessageId` | int | Serves as an offset for the query. The lastKnownMessageId for the next page is available in the `X-Chat-Last-Given` header. - -* Response: - - Status code: - + `200 OK` - + `304 Not Modified` When there were no older/newer messages - + `404 Not Found` When the conversation could not be found for the participant - - - Header: - - field | type | Description - ------|------|------------ - `X-Chat-Last-Given` | int | Offset (lastKnownMessageId) for the next page. - - - Data: - Array of messages, each message has at least: - - field | type | Description - ------|------|------------ - `id` | int | ID of the comment - `token` | string | Conversation token - `actorType` | string | `guests` or `users` - `actorId` | string | User id of the message author - `actorDisplayName` | string | Display name of the message author - `timestamp` | int | Timestamp in seconds and UTC time zone - `systemMessage` | string | empty for normal chat message or the type of the system message (untranslated) - `message` | string | Message string with placeholders (see [Rich Object String](https://github.com/nextcloud/server/issues/1706)) - `messageParameters` | array | Message parameters for `message` (see [Rich Object String](https://github.com/nextcloud/server/issues/1706)) - -### Sending a new chat message - -* Method: `POST` -* Endpoint: `/chat/{token}` -* Data: - - field | type | Description - ------|------|------------ - `message` | string | The message the user wants to say - `actorDisplayName` | string | Guest display name (ignored for logged in users) - -* Response: - - Header: - + `201 Created` - + `400 Bad Request` In case of any other error - + `404 Not Found` When the conversation could not be found for the participant - + `413 Payload Too Large` When the message was longer than the allowed limit of 32000 characters (or 1000 until Nextcloud 16.0.1, check the `spreed => config => chat => max-length` capability for the limit) - - - Data: - The full message array of the new message, as defined in [Receive chat messages of a conversation](#receive-chat-messages-of-a-conversation) - -### Get mention autocomplete suggestions - -* Method: `GET` -* Endpoint: `/chat/{token}/mentions` -* Data: - - field | type | Description - ------|------|------------ - `search` | string | Search term for name suggestions (should at least be 1 character) - `limit` | int | Number of suggestions to receive (20 by default) - -* Response: - - Status code: - + `200 OK` - + `404 Not Found` When the conversation could not be found for the participant - - - Data: - Array of suggestions, each suggestion has at least: - - field | type | Description - ------|------|------------ - `id` | string | The user id which should be sent as `@` in the message - `label` | string | The displayname of the user - `source` | string | The type of the user, currently only `users` - -### System messages - -* `conversation_created` - {actor} created the conversation -* `conversation_renamed` - {actor} renamed the conversation from "foo" to "bar" -* `call_started` - {actor} started a call -* `call_joined` - {actor} joined the call -* `call_left` - {actor} left the call -* `call_ended` - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23) -* `guests_allowed` - {actor} allowed guests in the conversation -* `guests_disallowed` - {actor} disallowed guests in the conversation -* `password_set` - {actor} set a password for the conversation -* `password_removed` - {actor} removed the password for the conversation -* `user_added` - {actor} added {user} to the conversation -* `user_removed` - {actor} removed {user} from the conversation -* `moderator_promoted` - {actor} promoted {user} to moderator -* `moderator_demoted` - {actor} demoted {user} from moderator -* `guest_moderator_promoted` - {actor} promoted {user} to moderator -* `guest_moderator_demoted` - {actor} demoted {user} from moderator -* `read_only_off` - {actor} unlocked the conversation -* `read_only` - {actor} locked the conversation - -## Guests - -### Set display name - -* Method: `POST` -* Endpoint: `/guest/{token}/name` -* Data: - - field | type | Description - ------|------|------------ - `displayName` | string | The new display name - -* Response: - - Header: - + `200 OK` - + `404 Not Found` When the conversation is not found or the session does not exist in the conversation - + `403 Forbidden` When the user is logged in - - -## Signaling - -### Get signaling settings - -* Method: `GET` -* Endpoint: `/signaling/settings` -* Data: - - field | type | Description - ------|------|------------ - `stunservers` | array | STUN servers - `turnservers` | array | TURN servers - `server` | string | URL of the external signaling server - `ticket` | string | Ticket for the external signaling server - - - STUN server - - field | type | Description - ------|------|------------ - `url` | string | STUN server URL - - - TURN server - - field | type | Description - ------|------|------------ - `url` | array | One element array with TURN server URL - `urls` | array | One element array with TURN server URL - `username` | string | User name for the TURN server - `credential` | string | User password for the TURN server - -* Response: - - Header: - + `200 OK` - + `404 Not Found` - -### External signaling API -See External Signaling API [Draft](https://github.com/nextcloud/spreed/wiki/Signaling-API) in the wiki… diff --git a/docs/call.md b/docs/call.md new file mode 100644 index 000000000..7c1dae4e6 --- /dev/null +++ b/docs/call.md @@ -0,0 +1,42 @@ +# Call API + +Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` + +## Get list of connected participants + +* Method: `GET` +* Endpoint: `/call/{token}` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant + + - Data: + Array of participants, each participant has at least: + + field | type | Description + ------|------|------------ + `userId` | string | Is empty for guests + `lastPing` | int | Timestamp of the last ping of the user (should be used for sorting) + `sessionId` | string | 512 character long string + +## Join a call + +* Method: `POST` +* Endpoint: `/call/{token}` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant + +## Leave a call (but staying in the conversation for future calls and chat) + +* Method: `DELETE` +* Endpoint: `/call/{token}` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant diff --git a/docs/capabilities.md b/docs/capabilities.md new file mode 100644 index 000000000..494c06272 --- /dev/null +++ b/docs/capabilities.md @@ -0,0 +1,34 @@ +--- +title: Capabilities +--- + +## 3.0 (Initial Talk release) +* `audio` - audio is supported +* `video` - video + screensharing is supported +* `chat` - simple text chat is supported, superseded by `chat-v2` + +## 3.1 +* `guest-signaling` - Guests can do signaling via api endpoints +* `empty-group-room` - Group conversations can be created without inviting a Nextcloud user group by default + +## 3.2 +* `guest-display-names` - Display names of guests are stored in the database, can be set via API (not WebRTC only) and are used on returned comments/participants/etc. +* `multi-room-users` - Users can be in multiple conversations at the same time now, therefor signaling now also requires the conversation token on the URL. +* `chat-v2` - Chat messages are now [Rich Object Strings](https://github.com/nextcloud/server/issues/1706) and pagination is available, the previous `chat` is not available anymore. + +## 4.0 +* `favorites` - Conversations can be marked as favorites which will pin them to the top of the conversation list. +* `last-room-activity` - Conversations have the `lastActivity` attribute and should be sorted by that instead of the last ping of the user. +* `no-ping` - The ping endpoint has been removed. Ping is updated with a call to fetch the signaling or chat messages instead. +* `system-messages` - Chat messages have a `systemMessage` attribute and can be generated by the system +* `mention-flag` - The conversation list populates the boolean `unreadMention` when the user was mentioned since their last visit +* `in-call-flags` - A new flag `participantFlags` has been introduced and is replacing the `participantInCall` boolean. + +## 5.0 +* `invite-by-mail` - *Replaced by `invite-groups-and-mails`* Guests can be invited with their email address +* `notification-levels` - Users can select when they want to be notified in conversations +* `invite-groups-and-mails` - Groups can be added to existing conversations via the add participant endpoint + +## 6.0 +* `locked-one-to-one-rooms` - One-to-one conversations are now locked to the users. Neither guests nor other participants can be added, so the options to do that should be hidden as well. Also a user can only leave a one-to-one conversation (not delete). It will be deleted when the other participant left too. If the other participant posts a new chat message or starts a call, the left-participant will be re-added. +* `read-only-rooms` - Conversations can be in `read-only` mode which means people can not do calls or write chat messages. diff --git a/docs/chat.md b/docs/chat.md new file mode 100644 index 000000000..93dfe6577 --- /dev/null +++ b/docs/chat.md @@ -0,0 +1,151 @@ +# Chat API + +Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` + +## Receive chat messages of a conversation + +* Method: `GET` +* Endpoint: `/chat/{token}` +* Data: + + field | type | Description + ------|------|------------ + `lookIntoFuture` | int | `1` Poll and wait for new message or `0` get history of a conversation + `limit` | int | Number of chat messages to receive (100 by default, 200 at most) + `timeout` | int | `$lookIntoFuture = 1` only, Number of seconds to wait for new messages (30 by default, 60 at most) + `lastKnownMessageId` | int | Serves as an offset for the query. The lastKnownMessageId for the next page is available in the `X-Chat-Last-Given` header. + +* Response: + - Status code: + + `200 OK` + + `304 Not Modified` When there were no older/newer messages + + `404 Not Found` When the conversation could not be found for the participant + + - Header: + + field | type | Description + ------|------|------------ + `X-Chat-Last-Given` | int | Offset (lastKnownMessageId) for the next page. + + - Data: + Array of messages, each message has at least: + + field | type | Description + ------|------|------------ + `id` | int | ID of the comment + `token` | string | Conversation token + `actorType` | string | `guests` or `users` + `actorId` | string | User id of the message author + `actorDisplayName` | string | Display name of the message author + `timestamp` | int | Timestamp in seconds and UTC time zone + `systemMessage` | string | empty for normal chat message or the type of the system message (untranslated) + `message` | string | Message string with placeholders (see [Rich Object String](https://github.com/nextcloud/server/issues/1706)) + `messageParameters` | array | Message parameters for `message` (see [Rich Object String](https://github.com/nextcloud/server/issues/1706)) + +## Sending a new chat message + +* Method: `POST` +* Endpoint: `/chat/{token}` +* Data: + + field | type | Description + ------|------|------------ + `message` | string | The message the user wants to say + `actorDisplayName` | string | Guest display name (ignored for logged in users) + +* Response: + - Header: + + `201 Created` + + `400 Bad Request` In case of any other error + + `404 Not Found` When the conversation could not be found for the participant + + `413 Payload Too Large` When the message was longer than the allowed limit of 32000 characters (or 1000 until Nextcloud 16.0.1, check the `spreed => config => chat => max-length` capability for the limit) + + - Data: + The full message array of the new message, as defined in [Receive chat messages of a conversation](#receive-chat-messages-of-a-conversation) + +## Get mention autocomplete suggestions + +* Method: `GET` +* Endpoint: `/chat/{token}/mentions` +* Data: + + field | type | Description + ------|------|------------ + `search` | string | Search term for name suggestions (should at least be 1 character) + `limit` | int | Number of suggestions to receive (20 by default) + +* Response: + - Status code: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant + + - Data: + Array of suggestions, each suggestion has at least: + + field | type | Description + ------|------|------------ + `id` | string | The user id which should be sent as `@` in the message + `label` | string | The displayname of the user + `source` | string | The type of the user, currently only `users` + +## System messages + +* `conversation_created` - {actor} created the conversation +* `conversation_renamed` - {actor} renamed the conversation from "foo" to "bar" +* `call_started` - {actor} started a call +* `call_joined` - {actor} joined the call +* `call_left` - {actor} left the call +* `call_ended` - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23) +* `guests_allowed` - {actor} allowed guests in the conversation +* `guests_disallowed` - {actor} disallowed guests in the conversation +* `password_set` - {actor} set a password for the conversation +* `password_removed` - {actor} removed the password for the conversation +* `user_added` - {actor} added {user} to the conversation +* `user_removed` - {actor} removed {user} from the conversation +* `moderator_promoted` - {actor} promoted {user} to moderator +* `moderator_demoted` - {actor} demoted {user} from moderator +* `guest_moderator_promoted` - {actor} promoted {user} to moderator +* `guest_moderator_demoted` - {actor} demoted {user} from moderator +* `read_only_off` - {actor} unlocked the conversation +* `read_only` - {actor} locked the conversation + +## Guests + + +## Signaling + +### Get signaling settings + +* Method: `GET` +* Endpoint: `/signaling/settings` +* Data: + + field | type | Description + ------|------|------------ + `stunservers` | array | STUN servers + `turnservers` | array | TURN servers + `server` | string | URL of the external signaling server + `ticket` | string | Ticket for the external signaling server + + - STUN server + + field | type | Description + ------|------|------------ + `url` | string | STUN server URL + + - TURN server + + field | type | Description + ------|------|------------ + `url` | array | One element array with TURN server URL + `urls` | array | One element array with TURN server URL + `username` | string | User name for the TURN server + `credential` | string | User password for the TURN server + +* Response: + - Header: + + `200 OK` + + `404 Not Found` + +### External signaling API +See External Signaling API [Draft](https://github.com/nextcloud/spreed/wiki/Signaling-API) in the wiki… diff --git a/docs/commands.md b/docs/commands.md index 88abf6bb0..ee8b1c560 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1,11 +1,15 @@ # Chat commands +!!! note -## Admin defined commands + For security reasons commands can only be added via the + command line. `./occ talk:command:add --help` gives you + a short overview of the required arguments, but they are + explained here in more depth. -For security reasons commands can only be added via the command line. `./occ talk:command:add --help` gives you a short overview of the required arguments, but they are explained here in more depth: +--- -### "Add command" arguments +## "Add command" arguments Argument | Allowed chars | Description ---|---|--- @@ -15,7 +19,7 @@ Argument | Allowed chars | Description `response` | 0-2 | Who should see the response: 0 - No one, 1 - User who executed the command, 2 - Everyone `enabled` | 0-3 | Who can use the command: 0 - No one, 1 - Moderators of the room, 2 - Logged in users, 3 - Everyone -### Script parameter +## Script parameter Parameter | Description ---|--- @@ -24,11 +28,11 @@ Parameter | Description `{ARGUMENTS}` | Everything the user write after the actual command `{ARGUMENTS_DOUBLEQUOTE_ESCAPED}` | … but with double quotes `"` escaped. -### Example +## Example * `/path/to/calc.sh`: - ``` +``` while test $# -gt 0; do case "$1" in --help) @@ -43,13 +47,13 @@ Parameter | Description ;; esac done - + set -f echo "$@ =" echo $(gnome-calculator --solve="$@") - ``` +``` - Please note, that your command should also understand the argument `--help`. +Please note, that your command should also understand the argument `--help`. It should return a useful description, the first line is also displayed in a list of all commands when the user just types `/help`. * `./occ` command used to add the command: diff --git a/docs/constants.md b/docs/constants.md new file mode 100644 index 000000000..49e8da445 --- /dev/null +++ b/docs/constants.md @@ -0,0 +1,25 @@ +--- +title: Constants +--- + +## Conversation types +* `1` "one to one" +* `2` group +* `3` public +* `4` changelog + +## Read-only states +* `0` read-write +* `1` read-only + +## Participant types +* `1` owner +* `2` moderator +* `3` user +* `4` guest +* `5` user following a public link + +## Actor types of chat messages +* `guests` - guest users +* `users` - logged-in users +* `bots` - used by commands (actor-id is the used `/command`) and the changelog conversation (actor-id is `changelog`) diff --git a/docs/conversation.md b/docs/conversation.md new file mode 100644 index 000000000..d876afb97 --- /dev/null +++ b/docs/conversation.md @@ -0,0 +1,218 @@ +# Conversation API + +Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` + +## Creating a new conversation + +* Method: `POST` +* Endpoint: `/room` +* Data: + + field | type | Description + ------|------|------------ + `roomType` | int | + `invite` | string | user id (`roomType = 1`), group id (`roomType = 2` - optional) + `roomName` | string | conversation name (Not available for `roomType = 1`) + +* Response: + - Header: + + `200 OK` when the "one to one" conversation already exists + + `201 Created` when the conversation was created + + `400 Bad Request` when an invalid conversation type was given + + `401 Unauthorized` when the user is not logged in + + `404 Not Found` when the user or group does not exist + + - Data: + + field | type | Description + ------|------|------------ + `token` | string | Token identifier of the conversation which is used for further interaction + `name` | string | Name of the conversation (can also be empty) + `displayName` | string | `name` if non empty, otherwise it falls back to a list of participants + +## Get user´s conversations + +* Method: `GET` +* Endpoint: `/room` + +* Response: + - Header: + + `200 OK` + + `401 Unauthorized` when the user is not logged in + + - Data: + Array of conversations, each conversation has at least: + + field | type | Description + ------|------|------------ + `token` | string | Token identifier of the conversation which is used for further interaction + `type` | int | + `name` | string | Name of the conversation (can also be empty) + `displayName` | string | `name` if non empty, otherwise it falls back to a list of participants + `participantType` | int | Permissions level of the current user + `participantInCall` | bool | Flag if the current user is in the call (deprecated, use `participantFlags` instead) + `participantFlags` | int | Flags of the current user (only available with `in-call-flags` capability) + `readOnly` | int | Read-only state for the current user (only available with `read-only-rooms` capability) + `count` | int | Number of active users + `numGuests` | int | Number of active guests + `lastPing` | int | Timestamp of the last ping of the current user (should be used for sorting) + `sessionId` | string | `'0'` if not connected, otherwise a 512 character long string + `hasPassword` | bool | Flag if the conversation has a password + `hasCall` | bool | Flag if the conversation has an active call + `lastActivity` | int | Timestamp of the last activity in the conversation, in seconds and UTC time zone + `isFavorite` | bool | Flag if the conversation is favorited by the user + `notificationLevel` | int | The notification level for the user (one of `Participant::NOTIFY_*` (1-3)) + `unreadMessages` | int | Number of unread chat messages in the conversation (only available with `chat-v2` capability) + `unreadMention` | bool | Flag if the user was mentioned since their last visit + `lastMessage` | message | Last message in a conversation if available, otherwise empty + `objectType` | string | The type of object that the conversation is associated with; "share:password" if the conversation is used to request a password for a share, otherwise empty + `objectId` | string | Share token if "objectType" is "share:password", otherwise empty + +## Get single conversation (also for guests) + +* Method: `GET` +* Endpoint: `/room/{token}` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant + + - Data: See array definition in `Get user´s conversations` + +## Rename a conversation + +* Method: `PUT` +* Endpoint: `/room/{token}` +* Data: + + field | type | Description + ------|------|------------ + `roomName` | string | New name for the conversation (1-200 characters) + +* Response: + - Header: + + `200 OK` + + `400 Bad Request` When the name is too long or empty + + `403 Forbidden` When the current user is not a moderator/owner + + `404 Not Found` When the conversation could not be found for the participant + + `405 Method Not Allowed` When the conversation is a one to one conversation + +## Set read-only for a conversation + +* Method: `PUT` +* Endpoint: `/room/{token}/read-only` +* Data: + + field | type | Description + ------|------|------------ + `state` | int | New state for the conversation + +* Response: + - Header: + + `200 OK` + + `400 Bad Request` When the conversation type does not support read-only (only group and public conversation atm) + + `403 Forbidden` When the current user is not a moderator/owner or the conversation is not a public conversation + + `404 Not Found` When the conversation could not be found for the participant + +## Set password for a conversation + +* Method: `PUT` +* Endpoint: `/room/{token}/password` +* Data: + + field | type | Description + ------|------|------------ + `password` | string | New password for the conversation + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the current user is not a moderator/owner or the conversation is not a public conversation + + `404 Not Found` When the conversation could not be found for the participant + +## Delete a conversation + +* Method: `DELETE` +* Endpoint: `/room/{token}` + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the current user is not a moderator/owner + + `404 Not Found` When the conversation could not be found for the participant + +## Allow guests in a conversation (public conversation) + +* Method: `POST` +* Endpoint: `/room/{token}/public` + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the current user is not a moderator/owner + + `404 Not Found` When the conversation could not be found for the participant + +## Disallow guests in a conversation (group conversation) + +* Method: `DELETE` +* Endpoint: `/room/{token}/public` + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the current user is not a moderator/owner + + `404 Not Found` When the conversation could not be found for the participant + +## Set conversation password + +* Method: `PUT` +* Endpoint: `/room/{token}/password` +* Data: + + field | type | Description + ------|------|------------ + `password` | string | Set a new password for the conversation + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the current user is not a moderator/owner + + `403 Forbidden` When the conversation is not a public conversation + + `404 Not Found` When the conversation could not be found for the participant + +## Add conversation to favorites + +* Method: `POST` +* Endpoint: `/room/{token}/favorite` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant or the participant is a guest + +## Remove conversation from favorites + +* Method: `DELETE` +* Endpoint: `/room/{token}/favorite` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant or the participant is a guest + +## Set notification level + +* Method: `POST` +* Endpoint: `/room/{token}/notify` +* Data: + + field | type | Description + ------|------|------------ + `level` | int | The notification level (one of `Participant::NOTIFY_*` (1-3)) + +* Response: + - Header: + + `200 OK` + + `400 Bad Request` When the the given level is invalid + + `404 Not Found` When the conversation could not be found for the participant or the participant is a guest diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..439a37814 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,12 @@ +![Screenshot of the chat in Nextcloud Talk](chat.png) + +# Nextcloud Talk API documentation + + +* [Constants](constants.md) +* [Capabilities](capabilities.md) +* [Conversation API](conversation.md) +* [Participant API](participant.md) +* [Call API](call.md) +* [Chat API](chat.md) +* [Signaling API](internal-signaling.md) diff --git a/docs/internal-signaling.md b/docs/internal-signaling.md new file mode 100644 index 000000000..118995786 --- /dev/null +++ b/docs/internal-signaling.md @@ -0,0 +1,40 @@ +# Internal signaling API + +See [External Signaling API](standalone-signaling-api-v1.md) for the Signaling of the High-Performance Backend. + +Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` + +## Get signaling settings + +* Method: `GET` +* Endpoint: `/signaling/settings` +* Data: + + field | type | Description + ------|------|------------ + `stunservers` | array | STUN servers + `turnservers` | array | TURN servers + `server` | string | URL of the external signaling server + `ticket` | string | Ticket for the external signaling server + + - STUN server + + field | type | Description + ------|------|------------ + `url` | string | STUN server URL + + - TURN server + + field | type | Description + ------|------|------------ + `url` | array | One element array with TURN server URL + `urls` | array | One element array with TURN server URL + `username` | string | User name for the TURN server + `credential` | string | User password for the TURN server + +* Response: + - Header: + + `200 OK` + + `404 Not Found` + +### External signaling API diff --git a/docs/participant.md b/docs/participant.md new file mode 100644 index 000000000..3d34f8b7f --- /dev/null +++ b/docs/participant.md @@ -0,0 +1,182 @@ +# Participant API + +Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` + +## Get list of participants in a conversation + +* Method: `GET` +* Endpoint: `/room/{token}/participants` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant + + - Data: + Array of participants, each participant has at least: + + field | type | Description + ------|------|------------ + `userId` | string | Is empty for guests + `displayName` | string | Can be empty for guests + `participantType` | int | Permissions level of the participant + `lastPing` | int | Timestamp of the last ping of the user (should be used for sorting) + `sessionId` | string | `'0'` if not connected, otherwise a 512 character long string + +## Add a participant to a conversation + +* Method: `POST` +* Endpoint: `/room/{token}/participants` +* Data: + + field | type | Description + ------|------|------------ + `newParticipant` | string | User, group or email to add + `source` | string | Source of the participant(s) as returned by the autocomplete suggestion endpoint (default is `users`) + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the current user is not a moderator/owner + + `400 Bad Request` When the source type is unknown + + `404 Not Found` When the conversation could not be found for the participant + + `404 Not Found` When the user or group to add could not be found + + - Data: + + field | type | Description + ------|------|------------ + `type` | int | In case the conversation type changed, the new value is returned + +## Delete a participant from a conversation + +* Method: `DELETE` +* Endpoint: `/room/{token}/participants` +* Data: + + field | type | Description + ------|------|------------ + `participant` | string | User to remove + +* Response: + - Header: + + `200 OK` + + `400 Bad Request` When the participant is a moderator/owner and there are no other moderators/owners left. + + `403 Forbidden` When the current user is not a moderator/owner + + `403 Forbidden` When the participant to remove is an owner + + `404 Not Found` When the conversation could not be found for the participant + + `404 Not Found` When the participant to remove could not be found + +## Remove a guest from a conversation + +* Method: `DELETE` +* Endpoint: `/room/{token}/participants/guests` +* Data: + + field | type | Description + ------|------|------------ + `participant` | string | Session ID of the guest to remove + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the current user is not a moderator/owner + + `403 Forbidden` When the target participant is not a guest + + `404 Not Found` When the conversation could not be found for the participant + + `404 Not Found` When the target participant could not be found + +## Remove yourself from a conversation + +* Method: `DELETE` +* Endpoint: `/room/{token}/participants/self` + +* Response: + - Header: + + `200 OK` + + `400 Bad Request` When the participant is a moderator/owner and there are no other moderators/owners left. + + `404 Not Found` When the conversation could not be found for the participant + +## Join a conversation (available for call and chat) + +* Method: `POST` +* Endpoint: `/room/{token}/participants/active` +* Data: + + field | type | Description + ------|------|------------ + `password` | string | Optional: Password is only required for users which are of type `4` or `5` and only when the conversation has `hasPassword` set to true. + +* Response: + - Header: + + `200 OK` + + `403 Forbidden` When the password is required and didn't match + + `404 Not Found` When the conversation could not be found for the participant + + - Data: + + field | type | Description + ------|------|------------ + `sessionId` | string | 512 character long string + +## Leave a conversation (not available for call and chat anymore) + +* Method: `DELETE` +* Endpoint: `/room/{token}/participants/active` + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation could not be found for the participant + +## Promote a user to a moderator + +* Method: `POST` +* Endpoint: `/room/{token}/moderators` +* Data: + + field | type | Description + ------|------|------------ + `participant` | string | User to promote + +* Response: + - Header: + + `200 OK` + + `400 Bad Request` When the participant to promote is not a normal user (type `3`) + + `403 Forbidden` When the current user is not a moderator/owner + + `403 Forbidden` When the participant to remove is an owner + + `404 Not Found` When the conversation could not be found for the participant + + `404 Not Found` When the participant to remove could not be found + +## Demote a moderator to a user + +* Method: `DELETE` +* Endpoint: `/room/{token}/moderators` +* Data: + + field | type | Description + ------|------|------------ + `participant` | string | User to promote + +* Response: + - Header: + + `200 OK` + + `400 Bad Request` When the participant to demote is not a moderator (type `2`) + + `403 Forbidden` When the current user is not a moderator/owner + + `404 Not Found` When the conversation could not be found for the participant + + `404 Not Found` When the participant to demote could not be found + +## Set display name as a guest + +* Method: `POST` +* Endpoint: `/guest/{token}/name` +* Data: + + field | type | Description + ------|------|------------ + `displayName` | string | The new display name + +* Response: + - Header: + + `200 OK` + + `404 Not Found` When the conversation is not found or the session does not exist in the conversation + + `403 Forbidden` When the user is logged in diff --git a/docs/standalone-signaling-api-v1.md b/docs/standalone-signaling-api-v1.md index e5b6d78d8..1ee91550d 100644 --- a/docs/standalone-signaling-api-v1.md +++ b/docs/standalone-signaling-api-v1.md @@ -1,4 +1,4 @@ -# Spreed Signaling API +# External signaling API This document gives a rough overview on the API version 1.0 of the Spreed signaling server. Clients can use the signaling server to send realtime @@ -14,7 +14,7 @@ For WebSockets, only the API described in this document is necessary. For COMET, an extension to this API is required to identify a (virtual) connection between multiple requests. The payload for COMET is the messages as described below. -See [`api-v1.md`](api-v1.md) for the API of the regular PHP backend. +See [Internal signaling API](internal-signaling.md) for the API of the regular PHP backend. ## Request diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..6ab7fc8e3 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,29 @@ +site_name: Nextcloud Talk API documentation + +theme: + name: readthedocs + highlightjs: true + hljs_languages: + - php + - js + - bash + +markdown_extensions: + - admonition + - def_list + - toc: + permalink: "#" + baselevel: 2 + +nav: + - Nextcloud Talk API: 'index.md' + - Constants: 'constants.md' + - Capabilities: 'capabilities.md' + - API v1.0: + - 'Conversations management': 'conversation.md' + - 'Participants management': 'participant.md' + - 'Call management': 'call.md' + - 'Chat management': 'chat.md' + - 'Internal signaling API': 'internal-signaling.md' + - 'External signaling API': 'standalone-signaling-api-v1.md' + - Commands: 'commands.md'