Skip to content

Commit

Permalink
feat(server): implement ws server
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Sep 15, 2023
1 parent f14d120 commit e79bda0
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 34 deletions.
1 change: 1 addition & 0 deletions packages/core/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export abstract class Bot<T extends Bot.Config = Bot.Config> {

dispatch(session: Session) {
if (!this.ctx.lifecycle.isActive) return
this.context.emit('internal/session', session)
const events: string[] = [session.type]
if (session.subtype) {
events.unshift(events[0] + '/' + session.subtype)
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Quester.createConfig = function createConfig(this, endpoint) {
type EventCallback<T = void, R extends any[] = []> = (this: Session, session: Session, ...args: R) => T

export interface Events<C extends Context = Context> extends cordis.Events<C>, Record<keyof Satori.Events, EventCallback> {
'internal/session'(session: Session): void
'before-send': EventCallback<Awaitable<void | boolean>, [SendOptions]>
'bot-added'(client: Bot): void
'bot-removed'(client: Bot): void
Expand Down
33 changes: 0 additions & 33 deletions packages/server-basic/src/index.ts

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@satorijs/server-basic",
"name": "@satorijs/server",
"description": "Basic API server for Satori protocol",
"version": "0.0.1",
"main": "lib/index.js",
Expand Down
92 changes: 92 additions & 0 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Context, Schema, snakeCase, Universal } from '@satorijs/satori'

const kClient = Symbol('state')

class Client {
authorized = false
}

export interface Config {
path: string
}

type Message = Message.Identify | Message.Heartbeat

namespace Message {
export interface Base {
type: string
}

export interface Identify extends Base {
type: 'identify'
}

export interface Heartbeat extends Base {
type: 'heartbeat'
}
}

export const Config: Schema<Config> = Schema.object({
path: Schema.string().default('/v1'),
})

function snakeCaseKeys(source: any) {
if (!source || typeof source !== 'object') return source
if (Array.isArray(source)) return source.map(snakeCaseKeys)
return Object.fromEntries(Object.entries(source).map(([key, value]) => [snakeCase(key), snakeCaseKeys(value)]))
}

export function apply(ctx: Context, config: Config) {
ctx.router.post(config.path + '/:name', async (koa) => {
const method = Universal.Methods[koa.params.name]
if (!method) {
koa.body = 'method not found'
return koa.status = 404
}

const json = koa.request.body
const selfId = json.self_id
const platform = json.platform
const bot = ctx.bots.find(bot => bot.selfId === selfId && bot.platform === platform)
if (!bot) {
koa.body = 'bot not found'
return koa.status = 403
}

const args = method.fields.map(field => json[field])
const result = await bot[method.name](...args)
koa.body = snakeCaseKeys(result)
koa.status = 200
})

const layer = ctx.router.ws(config.path, (socket) => {
const client = socket[kClient] = new Client()

socket.addEventListener('message', (event) => {
let payload: Message
try {
payload = JSON.parse(event.data.toString())
} catch (error) {
return socket.close(4000, 'invalid message')
}

if (payload.type === 'identify') {
client.authorized = true
} else if (payload.type === 'heartbeat') {
socket.send(JSON.stringify({ type: 'heartbeat' }))
} else {
return socket.close(4000, 'invalid message')
}
})
})

ctx.on('internal/session', (session) => {
for (const socket of layer.clients) {
if (!socket[kClient]?.authorized) continue
socket.send(JSON.stringify({
type: 'dispatch',
body: snakeCaseKeys(session),
}))
}
})
}
File renamed without changes.

0 comments on commit e79bda0

Please sign in to comment.