Plugins are installed to SOGS by placing directory with plugin to /plugins directory. They can then be enabled per-room by SOGS administrator.
Start by running bun init
in directory. Edit README.md for users and explain why your plugin is useful. You can decide to use src/ directory but this is not neccessary. You shouldn't build or compile your plugin, as Bun can interpret TypeScript on fly.
Name field in package.json will be used as display name in CLI. You can change it between updates, as SOGS only store enabled plugins by path to plugin directory. Your package.json must have module
or main
property that points to index file.
Add config.json to root directory. This file will be used to configure the plugin's settings. You can optionally allow user to configure settings per-room, this is handled by your code.
Bunsogs uses Worker interface to load your plugin. Add listener for message
to start listening for hooks. Respond with postMessage global method. Refer to section below to see examples.
Your plugin receives events via worker events, responds to it with specific logic and bunsogs will do the rest.
worker/index.ts
self.addEventListener('message', event => {
if(event.data.ref) {
// hooks that you must respond to
// Always return `ref` — it tells SOGS that the message you sent is a response to the specific request
switch(event.data.type) {
case 'onBeforePost':
console.log(event.data.payload.message)
postMessage({ ok: true, action: 'send', ref: event.data.ref })
break
default:
// return { ok: false } because other hooks are not implemented
postMessage({ ok: false, ref: event.data.ref })
// this is important because otherwise SOGS will indefinetely wait for your plugin response
break
}
} else {
// callbacks that act as notifications
switch(event.data.type) {
case 'onRecentMessagesRequest':
console.log(event.data.payload)
break
default:
// callbacks do not require answer
break
}
}
})
If your plugin returns {"ok": false}
on hook, bunsogs will ignore it and depend on other plugins result. You can optionally add error
to your failure response and bunsogs will log it into terminal.
Hooks are requests made to your plugin that block SOGS. You must respond to them. They also have ref
property in event's data.
Callbacks are events that notify your plugin about certain events happened in SOGS. They do not require answer and won't process it. They don't have ref
property in event's data.
Called when new message is posted to the SOGS.
Payload:
message
— object with message contentserver
— this sogs. Class: Server
Example payload:
event.data.payload = {
message: {
author: user,
text: 'Foo bar'
}
}
You should return action
property where :
send
means allow to sendreject
means throw error visible to Session clientdrop
means send message, but it will be only visible to user who sent it
Example response:
response.data = {
ok: true,
action: 'reject',
ref: event.data.ref
}
How it works with multiple plugins? If any of plugins return reject
— the message is rejected, otherwise if any of plugins return drop
, it is dropped, otherwise it is sent as normal.
Called when plugin is loaded by bunsogs.
Payload:
Example payload:
event.data.payload = {
rooms: [room],
server: server
}
Called when user requested /room/:token/messages/recent
Payload:
room
— room, that was requested. Class: Roomuser
— user that made request, might benull
if request made anonymously. Class: Userserver
— this sogs. Class: Server
Example payload:
event.data.payload = {
user: user, // can be null
room: room,
server: server
}
No response required.
Represents User in SOGS.
id
— user's numeric unique identificator in this sogs serversession_id
— blinded Session ID of author, starting with15
; blinded session ids are different among sogsadmin
— is global adminmoderator
— is global moderatorroomPermissions
— permissions in current roombanned
- is user banned in current roomread
- can user read messagesaccessible
- can user access roomwrite
- can user post messages to this roomupload
- can user upload files to this roommoderator
- is user room's moderatoradmin
- is user room's admin
Example:
user = {
id: 0,
session_id: '15383d0a3ba605abe3b5b7343102be3fc0026056b9812e06f6daee3be62a6a56e3',
admin: false,
moderator: false,
roomPermissions: {
banned: false,
read: true,
accessible: true,
write: true,
upload: true,
moderator: true,
admin: false
}
}
Represents Room in SOGS.
id
— room numeric identificatortoken
— room string token
Example:
room = {
id: 1,
token: 'test'
}
Represents current SOGS.
pk
— sogs public key in hex string formaturl
— publicly accessible URL of the sogs
Example:
server = {
pk: 'ac9c872e525a58970df6971655abb944a30b38853442a793b29843d20795e840',
url: 'http://localhost:3000'
}
Your plugin may call async methods in any point in time to interact with bunsogs. For example, that's what bunsogs-auto-dm plugin does to check new users with captcha and then add write permission to verified users.
Call methods by sending postMessage in plugin's code:
postMessage({
method: 'banUser',
user: '15b9460609fc38171c9afbec8411f55ef206c4e836461b32c19aac436bf187d4c6',
room: 'test'
})
Some methods return responses. You can pass ref
to your message and bunsogs will return response_ref
with its value with response, you can receive it with message
event:
postMessage({
method: 'uploadFile',
file: new Uint8Array(/* ... */)
ref: '1234567890'
})
self.addEventListener('message', async event => {
if (event.data.response_ref === '1234567890') {
console.log(event.data.id) // file id
}
})
Bans specified user in specified room. Restricts user from accessing room, room's content or writing anything to it. If you want to mute user, use setUserPermissions method with write=false permission.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number (optional) |
Optional: if not specified, user will be banned globally. If string, must be room's token. If number, must be room's id on this bunsogs server. |
timeout | number (optional) |
If specified, ban will be lifted automatically after that number of seconds |
Does not return answer.
Removes ban from specified user in (optionally) specified room.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number (optional) |
Optional: if not specified, user will be banned globally. If string, must be room's token. If number, must be room's id on this bunsogs server. |
Modifies specified user's permissions in (optionally) specified room. Do not use this to ban person, instead use banUser
method.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number |
If string, must be room's token. If number, must be room's id on this bunsogs server. |
accessible | boolean or null (optional) |
Optional: only specify this if you want to change that permission from the current user permission override. Pass true or false to allow or deny user to see this room. Pass null to reset this permission to default, provided by this room. |
read | boolean or null (optional) |
Optional: only specify this if you want to change that permission from the current user permission override. Pass true or false to allow or deny user to read messages in this room. Pass null to reset this permission to default, provided by this room. |
write | boolean or null (optional) |
Optional: only specify this if you want to change that permission from the current user permission override. Pass true or false to allow or deny sending messages for that user. Pass null to reset this permission to default, provided by this room. |
upload | boolean or null (optional) |
Optional: only specify this if you want to change that permission from the current user permission override. Pass true or false to allow or deny uploading files for this user. Pass null to reset this permission to default, provided by this room. |
No response.
Docs TBD
No response.
Sends message.
Request: Docs TBD
Response:
Key | Type | Description |
---|---|---|
id | number |
Message ID |
Deletes message.
Request:
Key | Type | Description |
---|---|---|
room | string or number |
If string, must be room's token. If number, must be room's id on this bunsogs server. |
messageId | number |
Message ID in this room |
Response:
Key | Type | Description |
---|---|---|
id | number |
Message ID |
Makes the specified user admin of the specified room.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number |
If string, must be room's token. If number, must be room's id on this bunsogs server. |
visible | boolean |
If this admin is visible to other users |
No response.
Removes the specified admin from the specified room.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number |
If string, must be room's token. If number, must be room's id on this bunsogs server. |
No response.
Makes the specified user moderator of the specified room.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number |
If string, must be room's token. If number, must be room's id on this bunsogs server. |
visible | boolean |
If this moderator is visible to other users |
No response.
Removes the specified moderator from the specified room.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number |
If string, must be room's token. If number, must be room's id on this bunsogs server. |
No response.
Makes the specified user global admin.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
visible | boolean |
If this admin is visible to other users |
No response.
Removes global admin.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
No response.
Makes the specified user global moderator.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
visible | boolean |
If this moderator is visible to other users |
No response.
Removes global moderator.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
No response.
Upload a file to SOGS.
Request:
Key | Type | Description |
---|---|---|
uploader | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number |
Room that will have this file. If string, must be room's token. If number, must be room's id on this bunsogs server. |
file | Uint8Array |
File contents |
Response:
Key | Type | Description |
---|---|---|
id | number |
Uploaded file id |
Add reaction to message as the specified user.
Upload a file to SOGS.
Request:
Key | Type | Description |
---|---|---|
user | string or number |
If string, must be either blinded (prefix 15) or unblinded (prefix 05) Session ID. If number, must be user ID on this bunsogs |
room | string or number |
If string, must be room's token. If number, must be room's id on this bunsogs server. |
messageId | number |
Message id in this room |
reaction | string |
Emoji reaction |
Use postMessage with { type: 'log', message: 'any string you like' }
to log messages to operator's console.
For example (plugin code):
postMessage({ type: 'log', message: profanityWords.size + ' words loaded' })
Bunsogs console:
Plugin bunsogs-profanity-filter: 4499 words loaded
Additionally you might want to add dev: true
to your message payload so it's only visible when bunsogs is started in development mode with BUNSOGS_DEV=true:
postMessage({ type: 'log', message: profanityWords.size + ' words loaded', dev: true })
// only visible when bunsogs is started with BUNSOGS_DEV=true env variable