mirror of
https://github.com/Blah-IM/blahrs.git
synced 2025-05-01 00:31:09 +00:00

Now a group can only be created with the creator as the only initial member. This forbids group creator from adding other members without their consent. Additional members can join the group later at their own will.
635 lines
18 KiB
YAML
635 lines
18 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Blah Chatserver Proto
|
|
version: 0.0.1
|
|
|
|
paths:
|
|
# OAPI does not support WebSocket interface definitions.
|
|
# See: https://github.com/OAI/OpenAPI-Specification/issues/55#issuecomment-929382279
|
|
/ws:
|
|
get:
|
|
summary: WebSocket endpoint
|
|
description: |
|
|
This endpoint is for server-side-event dispatching.
|
|
|
|
Once connected, client must send a JSON text message of type
|
|
`Signed-Auth` for authentication.
|
|
If server does not close it immediately, it means success.
|
|
|
|
Since OAPI does not support WebSocket interface, we use request and
|
|
response types documented here mean outgoing and incoming JSON text
|
|
messages.
|
|
|
|
parameters:
|
|
- name: Connection
|
|
in: header
|
|
required: true
|
|
- name: Upgrade
|
|
in: header
|
|
required: true
|
|
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WSClientToServer'
|
|
|
|
responses:
|
|
101:
|
|
headers:
|
|
Connection:
|
|
required: true
|
|
Upgrade:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WSServerToClient'
|
|
|
|
/room:
|
|
get:
|
|
summary: List rooms
|
|
parameters:
|
|
- name: filter
|
|
in: query
|
|
required: true
|
|
schema:
|
|
enum:
|
|
- public
|
|
- joined
|
|
- unseen
|
|
description: |
|
|
Must be one of following values:
|
|
- "public": list all public rooms on the server.
|
|
- "joined": list rooms the user have joined.
|
|
Requires `Authorization`.
|
|
- "unseen": list rooms the user have joined and have unseen
|
|
messages.
|
|
Requires `Authorization`.
|
|
|
|
- name: top
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description:
|
|
The maximum count of rooms returned in a single response. This is
|
|
only an advice and server can clamp it to a smaller value.
|
|
|
|
- name: skipToken
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description:
|
|
The page token returned from a previous list response to fetch the
|
|
next page. NB. Other parameters (eg. `joined` and `page_len`)
|
|
should be included (as the same value) for each page fetch.
|
|
|
|
- name: Authorization
|
|
in: header
|
|
description: Optional proof of membership for private rooms.
|
|
schema:
|
|
$ref: '#/components/schemas/Signed-Auth'
|
|
|
|
responses:
|
|
200:
|
|
description: Filtered and paged rooms.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RoomList'
|
|
|
|
401:
|
|
description: Missing or invalid Authorization header.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
/room/create:
|
|
post:
|
|
summary: Create a room
|
|
|
|
description:
|
|
When `typ="create_room"`, create a multi-user room.
|
|
|
|
When `typ="create_peer_chat"`, create a peer-to-peer room between two
|
|
users. There can be at most one peer room for each given user pair.
|
|
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Signed-CreateRoom'
|
|
|
|
responses:
|
|
200:
|
|
description: Room created.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: string
|
|
description: Newly created room `rid`.
|
|
|
|
403:
|
|
description: The user does not have permission to create room.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
404:
|
|
description: The peer user does not exist or disallows peer chat.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
409:
|
|
description: There is already a peer chat room between the user pair.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
/room/{rid}:
|
|
get:
|
|
summary: Get room metadata
|
|
parameters:
|
|
- name: Authorization
|
|
in: header
|
|
description: Optional proof of membership for private rooms.
|
|
schema:
|
|
$ref: '#/components/schemas/Signed-Auth'
|
|
|
|
responses:
|
|
200:
|
|
description: The metadata of the specified room.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RoomMetadata'
|
|
|
|
404:
|
|
description: |
|
|
Room does not exist or the user does not have permission to get metadata of it.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
/room/{rid}/admin:
|
|
post:
|
|
summary: Room management
|
|
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Signed-RoomAdmin'
|
|
|
|
responses:
|
|
204:
|
|
description: Operation completed.
|
|
|
|
404:
|
|
description: |
|
|
Room does not exist or the user does not have permission for the
|
|
operation.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
409:
|
|
description:
|
|
Operation is already done, eg. joining an already joined room.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
/room/{rid}/feed.json:
|
|
get:
|
|
summary: Get JSON feed of room
|
|
description: |
|
|
Get room {rid}'s content in JSON feed v1.1 format. The room must be
|
|
public. For human and feed reader consumption only.
|
|
responses:
|
|
200:
|
|
description: The JSON feed.
|
|
content:
|
|
text/feed+json:
|
|
schema:
|
|
$ref: 'https://www.jsonfeed.org/version/1.1/'
|
|
|
|
404:
|
|
description: Room does not exist or is private.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
/room/{rid}/msg:
|
|
get:
|
|
summary: List messages in a room
|
|
description: |
|
|
Return a list of messages in reversed server time order, up to length `top`
|
|
in a single response, from room {rid}.
|
|
The last (oldest) message's `cid` will be returned as `skipToken` in
|
|
response, which can be used as query parameter for the next GET, to
|
|
repeatedly fetch more history.
|
|
|
|
parameters:
|
|
- name: Authorization
|
|
in: header
|
|
description: Optional proof of membership for private rooms.
|
|
schema:
|
|
$ref: '#/components/schemas/Signed-Auth'
|
|
|
|
- name: top
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
description: |
|
|
The number of items returned in a single response. This is
|
|
an advice and may be further clamped by the server. It must not be
|
|
zero.
|
|
|
|
- name: skipToken
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: |
|
|
Return items after (older than) an existing `cid`. Useful for
|
|
pagination.
|
|
|
|
responses:
|
|
200:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RoomMsgs'
|
|
|
|
404:
|
|
description: |
|
|
Room does not exist or the user does not have permission to read it.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
post:
|
|
summary: Post a `Msg` into a room
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Signed-Chat'
|
|
|
|
responses:
|
|
200:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: string
|
|
description: Newly created message id `cid`.
|
|
|
|
403:
|
|
description: The user does not have permission to post in this room.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
404:
|
|
description: The room does not exist or the user is not a room member.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
/room/{rid}/msg/{cid}/seen:
|
|
post:
|
|
summary: Mark a message seen
|
|
description: |
|
|
Mark message {cid} and everything before it in room {rid} seen by the
|
|
current user.
|
|
|
|
Server may enforce that last seen message does not go backward. Marking
|
|
an older message seen or sending the same request multiple times can be
|
|
a no-op.
|
|
|
|
parameters:
|
|
- name: Authorization
|
|
in: header
|
|
required: true
|
|
description: Proof of membership for private rooms.
|
|
schema:
|
|
$ref: '#/components/schemas/Signed-Auth'
|
|
|
|
responses:
|
|
204:
|
|
description: Operation completed.
|
|
|
|
404:
|
|
description: |
|
|
Room does not exist or the user is not in the room.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiError'
|
|
|
|
# Ideally we should generate these from src, but we need to
|
|
# WAIT: https://github.com/juhaku/utoipa/pull/1034
|
|
components:
|
|
schemas:
|
|
WSClientToServer:
|
|
anyOf:
|
|
- $ref: '#/components/schemas/Signed-Auth'
|
|
|
|
WSServerToClient:
|
|
anyOf:
|
|
- type: object
|
|
properties:
|
|
chat:
|
|
$ref: '#/components/schemas/Signed-Chat'
|
|
|
|
- type: object
|
|
properties:
|
|
lagged:
|
|
type: object
|
|
const: {}
|
|
|
|
ApiError:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
description: A machine-readable error code string.
|
|
example: invalid_signature
|
|
message:
|
|
type: string
|
|
description: A human-readable error message.
|
|
example: signature verification failed
|
|
|
|
RoomList:
|
|
type: object
|
|
required:
|
|
- rooms
|
|
properties:
|
|
rooms:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RoomMetadataForList'
|
|
next_token:
|
|
type: string
|
|
description: An opaque token to fetch the next page.
|
|
|
|
RoomMetadataForList:
|
|
type: object
|
|
required: ['rid', 'title', 'attrs']
|
|
properties:
|
|
rid:
|
|
type: string
|
|
title:
|
|
type: string
|
|
attrs:
|
|
description: Room attributes bitset, see `RoomAttrs`.
|
|
type: integer
|
|
format: int64
|
|
last_msg:
|
|
$ref: '#/components/schemas/WithMsgId-Signed-Chat'
|
|
last_seen_cid:
|
|
description: The `cid` of the last chat being marked as seen.
|
|
type: string
|
|
unseen_cnt:
|
|
description: |
|
|
The number of unseen messages. Only available for
|
|
GET `/room?filter=unseen`.
|
|
type: integer
|
|
format: uint64
|
|
member_permission:
|
|
type: integer
|
|
format: int64
|
|
peer_user:
|
|
type: string
|
|
description: |
|
|
For peer chat room, this gives the identity of the peer user.
|
|
|
|
RoomMetadata:
|
|
type: object
|
|
required: ['rid', 'title', 'attrs']
|
|
properties:
|
|
rid:
|
|
type: string
|
|
title:
|
|
type: string
|
|
attrs:
|
|
type: integer
|
|
format: int64
|
|
|
|
RoomMsgs:
|
|
type: object
|
|
required:
|
|
- msgs
|
|
properties:
|
|
msgs:
|
|
description: Room messages in reversed server-received time order.
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WithMsgId-Signed-Chat'
|
|
skip_token:
|
|
description: The token for fetching the next page.
|
|
type: string
|
|
|
|
RichText:
|
|
type: array
|
|
items:
|
|
anyOf:
|
|
- type: string
|
|
description: Unstyled text piece.
|
|
- type: array
|
|
items: false
|
|
prefixItems:
|
|
- type: string
|
|
description: The text piece to apply styles on.
|
|
- type: object
|
|
properties:
|
|
b:
|
|
type: boolean
|
|
description: Bold.
|
|
m:
|
|
type: boolean
|
|
description: Monospace.
|
|
i:
|
|
type: boolean
|
|
description: Italic.
|
|
s:
|
|
type: boolean
|
|
description: Strikethrough.
|
|
u:
|
|
type: boolean
|
|
description: Underline.
|
|
hashtag:
|
|
type: boolean
|
|
description: Hashtag.
|
|
link:
|
|
type: string
|
|
description: Link target.
|
|
|
|
|
|
Signed-Auth:
|
|
type: object
|
|
properties:
|
|
sig:
|
|
type: string
|
|
signee:
|
|
type: object
|
|
properties:
|
|
nonce:
|
|
type: integer
|
|
format: uint32
|
|
payload:
|
|
type: object
|
|
properties:
|
|
typ:
|
|
type: string
|
|
const: 'auth'
|
|
|
|
Signed-RoomAdmin:
|
|
type: object
|
|
properties:
|
|
sig:
|
|
type: string
|
|
signee:
|
|
type: object
|
|
properties:
|
|
nonce:
|
|
type: integer
|
|
format: uint32
|
|
payload:
|
|
oneOf:
|
|
|
|
- description: Add member to the room.
|
|
type: object
|
|
properties:
|
|
typ:
|
|
type: string
|
|
const: 'add_member'
|
|
room:
|
|
type: string
|
|
permission:
|
|
type: integer
|
|
format: uint64
|
|
user:
|
|
type: string
|
|
|
|
- description: Remove member from the room.
|
|
type: object
|
|
properties:
|
|
typ:
|
|
type: string
|
|
const: 'remove_member'
|
|
room:
|
|
type: string
|
|
user:
|
|
type: string
|
|
|
|
|
|
example:
|
|
sig: 99a77e836538268839ed3419c649eefb043cb51d448f641cc2a1c523811aab4aacd09f92e7c0688ffd659bfc6acb764fea79979a491e132bf6a56dd23adc1d09
|
|
signee:
|
|
nonce: 670593955
|
|
payload:
|
|
permission: 1
|
|
room: 7ed9e067-ec37-4054-9fc2-b1bd890929bd
|
|
typ: add_member
|
|
user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7
|
|
timestamp: 1724966284
|
|
user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7
|
|
|
|
Signed-Chat:
|
|
type: object
|
|
properties:
|
|
sig:
|
|
type: string
|
|
signee:
|
|
type: object
|
|
properties:
|
|
nonce:
|
|
type: integer
|
|
format: uint32
|
|
payload:
|
|
type: object
|
|
properties:
|
|
typ:
|
|
type: string
|
|
const: 'chat'
|
|
room:
|
|
type: string
|
|
rich_text:
|
|
$ref: '$/components/schemas/RichText'
|
|
example:
|
|
sig: 99a77e836538268839ed3419c649eefb043cb51d448f641cc2a1c523811aab4aacd09f92e7c0688ffd659bfc6acb764fea79979a491e132bf6a56dd23adc1d09
|
|
signee:
|
|
nonce: 670593955
|
|
payload:
|
|
typ: chat
|
|
room: 7ed9e067-ec37-4054-9fc2-b1bd890929bd
|
|
rich_text: ["before ",["bold ",{"b":true}],["italic bold ",{"b":true,"i":true}],"end"]
|
|
timestamp: 1724966284
|
|
user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7
|
|
|
|
WithMsgId-Signed-Chat:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Signed-Chat'
|
|
- type: object
|
|
properties:
|
|
cid:
|
|
type: string
|
|
description: An opaque server-specific identifier.
|
|
|
|
Signed-CreateRoom:
|
|
type: object
|
|
properties:
|
|
sig:
|
|
type: string
|
|
signee:
|
|
type: object
|
|
properties:
|
|
nonce:
|
|
type: integer
|
|
format: uint32
|
|
payload:
|
|
oneOf:
|
|
- type: object
|
|
properties:
|
|
typ:
|
|
type: string
|
|
const: 'create_room'
|
|
title:
|
|
type: string
|
|
- type: object
|
|
properties:
|
|
typ:
|
|
type: string
|
|
const: 'create_peer_chat'
|
|
peer:
|
|
type: string
|
|
|
|
example:
|
|
sig: 99a77e836538268839ed3419c649eefb043cb51d448f641cc2a1c523811aab4aacd09f92e7c0688ffd659bfc6acb764fea79979a491e132bf6a56dd23adc1d09
|
|
signee:
|
|
nonce: 670593955
|
|
payload:
|
|
typ: create_room
|
|
attrs: 1 # PUBLIC_READABLE
|
|
title: 'hello room'
|
|
members:
|
|
- user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7
|
|
permission: -1
|
|
timestamp: 1724966284
|
|
user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7
|