Skip to content

Commit

Permalink
feat(satori): rename satori to internal
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Dec 8, 2024
1 parent 55949f3 commit 5080750
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 42 deletions.
7 changes: 2 additions & 5 deletions adapters/satori/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,8 @@ export class SatoriBot<C extends Context = Context> extends Bot<C, Universal.Log
super(ctx, config, 'satori')
Object.assign(this, config)

this.defineVirtualRoute('/*path', async ({ method, params, query }) => {
const search = query.toString()
let path = `/v1/proxy/satori:${this.platform}/${this.selfId}/${params.path}`
if (search) path += '?' + search
return await this.http(path, {
this.defineInternalRoute('/*path', async ({ method, params, query }) => {
return await this.http(`/v1/${this.getInternalUrl(params.path, query, true)}`, {
method,
responseType: 'arraybuffer',
})
Expand Down
22 changes: 12 additions & 10 deletions packages/core/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import h from '@satorijs/element'
import { Adapter } from './adapter'
import { MessageEncoder } from './message'
import { defineAccessor, Session } from './session'
import { ExtractParams, VirtualRequest, VirtualRouter } from './virtual'
import { ExtractParams, InternalRequest, InternalRouter } from './internal'
import { Event, List, Login, Methods, Response, SendOptions, Status, Upload, User } from '@satorijs/protocol'

/* eslint-enable @typescript-eslint/no-unused-vars */
Expand Down Expand Up @@ -41,15 +41,15 @@ export abstract class Bot<C extends Context = Context, T = any> {
public callbacks: Dict<Function> = {}
public logger: Logger

public _virtual: VirtualRouter
public _internalRouter: InternalRouter

// Same as `this.ctx`, but with a more specific type.
protected context: Context
protected _status: Status = Status.OFFLINE

constructor(public ctx: C, public config: T, platform?: string) {
this.internal = null
this._virtual = new VirtualRouter(ctx)
this._internalRouter = new InternalRouter(ctx)
this.context = ctx
ctx.bots.push(this)
this.context.emit('bot-added', this)
Expand All @@ -58,7 +58,7 @@ export abstract class Bot<C extends Context = Context, T = any> {
this.platform = platform
}

this.proxyUrls = [`satori://temp/${ctx.satori.uid}/`]
this.proxyUrls = []
this.features = Object.entries(Methods)
.filter(([, value]) => this[value.name])
.map(([key]) => key)
Expand All @@ -77,12 +77,14 @@ export abstract class Bot<C extends Context = Context, T = any> {
})
}

getVirtualUrl(path: string) {
return `satori:${this.platform}/${this.selfId}${path}`
getInternalUrl(path: string, init?: ConstructorParameters<typeof URLSearchParams>[0], slash?: boolean) {
let search = new URLSearchParams(init).toString()
if (search) search = '?' + search
return `internal${slash ? '/' : ':'}${this.platform}/${this.selfId}${path}${search}`
}

defineVirtualRoute<P extends string>(path: P, callback: (request: VirtualRequest<ExtractParams<P>>) => Promise<Response>) {
return this._virtual.define(path, callback)
defineInternalRoute<P extends string>(path: P, callback: (request: InternalRequest<ExtractParams<P>>) => Promise<Response>) {
return this._internalRouter.define(path, callback)
}

update(login: Login) {
Expand Down Expand Up @@ -215,7 +217,7 @@ export abstract class Bot<C extends Context = Context, T = any> {
}
this.ctx.satori._tempStore[id] = {
status: 200,
data: upload.data,
body: upload.data,
headers,
}
ids.push(id)
Expand All @@ -229,7 +231,7 @@ export abstract class Bot<C extends Context = Context, T = any> {
}
}
const _dispose = this.ctx.on('dispose', dispose)
return ids.map(id => this.getVirtualUrl(`/_tmp/${id}`))
return ids.map(id => this.getInternalUrl(`/_tmp/${id}`))
}

async supports(name: string, session: Partial<C[typeof Context.session]> = {}) {
Expand Down
26 changes: 13 additions & 13 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Context, Logger, Service, z } from 'cordis'
import { Awaitable, defineProperty, Dict } from 'cosmokit'
import { Bot } from './bot'
import { ExtractParams, VirtualRequest, VirtualRouter } from './virtual'
import { ExtractParams, InternalRequest, InternalRouter } from './internal'
import { Session } from './session'
import { HTTP } from '@cordisjs/plugin-http'
import { Response, SendOptions } from '@satorijs/protocol'
Expand All @@ -23,7 +23,7 @@ export * as Universal from '@satorijs/protocol'
export * from './bot'
export * from './adapter'
export * from './message'
export * from './virtual'
export * from './internal'
export * from './session'

declare module 'cordis' {
Expand Down Expand Up @@ -120,15 +120,15 @@ export class Satori<C extends Context = Context> extends Service<unknown, C> {

public uid = Math.random().toString(36).slice(2)

public _virtual: VirtualRouter
public _internalRouter: InternalRouter
public _tempStore: Dict<Response> = Object.create(null)

constructor(ctx?: C) {
super(ctx)
ctx.mixin('satori', ['bots', 'component'])

this._virtual = new VirtualRouter(ctx)
this.defineVirtualRoute('/_tmp/:id', async ({ params }) => {
this._internalRouter = new InternalRouter(ctx)
this.defineInternalRoute('/_tmp/:id', async ({ params }) => {
return this._tempStore[params.id] ?? { status: 404 }
})

Expand All @@ -137,16 +137,16 @@ export class Satori<C extends Context = Context> extends Service<unknown, C> {
const self = this
;(ctx as Context).on('http/file', async function (_url, options) {
const url = new URL(_url)
if (url.protocol !== 'satori:') return
const { status, data, headers } = await self.handleVirtualRoute('GET', url)
if (url.protocol !== 'internal:') return
const { status, body, headers } = await self.handleInternalRoute('GET', url)
if (status >= 400) throw new Error(`Failed to fetch ${_url}, status code: ${status}`)
if (status >= 300) {
const location = headers?.get('location')
return this.file(location, options)
}
const type = headers?.get('content-type')
const filename = headers?.get('content-disposition')?.split('filename=')[1]
return { data, filename, type, mime: type }
return { data: body, filename, type, mime: type }
})
}

Expand Down Expand Up @@ -179,18 +179,18 @@ export class Satori<C extends Context = Context> extends Service<unknown, C> {
return this.ctx.set('component:' + name, render)
}

defineVirtualRoute<P extends string>(path: P, callback: (request: VirtualRequest<ExtractParams<P>>) => Promise<Response>) {
return this._virtual.define(path, callback)
defineInternalRoute<P extends string>(path: P, callback: (request: InternalRequest<ExtractParams<P>>) => Promise<Response>) {
return this._internalRouter.define(path, callback)
}

async handleVirtualRoute(method: HTTP.Method, url: URL): Promise<Response> {
async handleInternalRoute(method: HTTP.Method, url: URL, headers = new Headers(), body?: any): Promise<Response> {
const capture = /^([^/]+)\/([^/]+)(\/.+)$/.exec(url.pathname)
if (!capture) return { status: 400 }
const [, platform, selfId, path] = capture
const bot = this.bots[`${platform}:${selfId}`]
if (!bot) return { status: 404 }
let response = await bot._virtual.handle(method, path, url.searchParams)
response ??= await this._virtual.handle(method, path, url.searchParams)
let response = await bot._internalRouter.handle(method, path, url.searchParams, headers, body)
response ??= await this._internalRouter.handle(method, path, url.searchParams, headers, body)
if (!response) return { status: 404 }
return response
}
Expand Down
26 changes: 17 additions & 9 deletions packages/core/src/virtual.ts → packages/core/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import { Response } from '@satorijs/protocol'
import { Key, pathToRegexp } from 'path-to-regexp'
import { Context } from '.'

export interface VirtualRequest<P = any> {
export interface InternalRequest<P = any> {
method: HTTP.Method
params: P
query: URLSearchParams
headers: Dict<string> // Headers
body: any
}

export interface VirtualRoute {
export interface InternalRoute {
regexp: RegExp
keys: Key[]
callback: (request: VirtualRequest) => Promise<Response>
callback: (request: InternalRequest) => Promise<Response>
}

type Upper =
Expand Down Expand Up @@ -63,18 +65,18 @@ export type ExtractParams<S extends string, O extends {} = {}, A extends 0[] = [
: ExtractParams<S, O, A>
: O

export class VirtualRouter {
export class InternalRouter {
public [Service.tracker] = {
property: 'ctx',
}

routes: VirtualRoute[] = []
routes: InternalRoute[] = []

constructor(public ctx: Context) {}

define<P extends string>(path: P, callback: (request: VirtualRequest<ExtractParams<P>>) => Promise<Response>) {
define<P extends string>(path: P, callback: (request: InternalRequest<ExtractParams<P>>) => Promise<Response>) {
return this.ctx.effect(() => {
const route: VirtualRoute = {
const route: InternalRoute = {
...pathToRegexp(path),
callback,
}
Expand All @@ -83,15 +85,21 @@ export class VirtualRouter {
})
}

handle(method: HTTP.Method, path: string, query: URLSearchParams): undefined | Promise<Response> {
handle(method: HTTP.Method, path: string, query: URLSearchParams, headers: Headers, body: any): undefined | Promise<Response> {
for (const route of this.routes) {
const capture = route.regexp.exec(path)
if (!capture) continue
const params: Dict<string> = {}
route.keys.forEach(({ name }, index) => {
params[name] = capture[index + 1]
})
return route.callback({ method, params, query })
return route.callback({
method,
params,
query,
body,
headers: Object.fromEntries(headers.entries()),
})
}
}
}
2 changes: 1 addition & 1 deletion packages/protocol/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface Upload {
export interface Response {
status: number
statusText?: string
data?: ArrayBuffer
body?: ArrayBuffer
headers?: Headers
}

Expand Down
7 changes: 3 additions & 4 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Binary, camelCase, Context, Dict, makeArray, sanitize, Schema, Service,
import {} from '@cordisjs/plugin-server'
import WebSocket from 'ws'
import { Readable } from 'node:stream'
import { ReadableStream } from 'node:stream/web'
import { readFile } from 'node:fs/promises'
import { ParameterizedContext } from 'koa'

Expand Down Expand Up @@ -166,14 +165,14 @@ class SatoriServer extends Service<SatoriServer.Config> {
}

koa.header['Access-Control-Allow-Origin'] = ctx.server.config.selfUrl || '*'
if (url.protocol === 'satori:') {
const { status, statusText, data, headers } = await ctx.satori.handleVirtualRoute('GET', url)
if (url.protocol === 'internal:') {
const { status, statusText, body, headers } = await ctx.satori.handleInternalRoute('GET', url)
koa.status = status
for (const [key, value] of headers || new Headers()) {
koa.set(key, value)
}
if (status >= 200 && status < 300) {
koa.body = data instanceof ReadableStream ? Readable.fromWeb(data) : data ? Buffer.from(data) : null
koa.body = body ? Buffer.from(body) : null
} else {
koa.body = statusText
}
Expand Down

0 comments on commit 5080750

Please sign in to comment.