Skip to content

Commit

Permalink
feat(matrix): add prefix to routes (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anillc authored Aug 21, 2023
1 parent fffa2be commit 516790d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 41 deletions.
2 changes: 2 additions & 0 deletions adapters/matrix/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export namespace MatrixBot {
hsToken?: string
asToken?: string
host?: string
path?: string
}

export const Config: Schema<Config> = Schema.object({
Expand All @@ -172,6 +173,7 @@ export namespace MatrixBot {
hsToken: Schema.string().description('hs_token').role('secret').required(),
asToken: Schema.string().description('as_token').role('secret').required(),
endpoint: Schema.string().description('Matrix Homeserver 地址。默认为 `https://{host}`。'),
path: Schema.string().description('Matrix Application Service 的路径。默认为 `/matrix`。').default('/matrix'),
...omit(Quester.Config.dict, ['endpoint']),
})
}
73 changes: 32 additions & 41 deletions adapters/matrix/src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,37 @@ import { MatrixBot } from './bot'
import { dispatchSession } from './utils'
import { ClientEvent, M_ROOM_MEMBER } from './types'

declare module 'koa' {
interface Context {
bots: MatrixBot[]
}
}

const logger = new Logger('matrix')

export class HttpAdapter extends Adapter.Server<MatrixBot> {
private txnId: string = null

hook(callback: (ctx: KoaContext) => void) {
return (ctx: KoaContext) => {
const bots = this.bots.filter(bot => (bot instanceof MatrixBot) && (bot.config.hsToken === ctx.query.access_token))
public constructor(ctx: Context) {
super()
ctx.router.all('/(.*)', (koaCtx, next) => {
const match = this.bots.filter(bot => koaCtx.path.startsWith(bot.config.path + '/'))
if (match.length === 0) return next()
const bots = match.filter(bot => bot.config.hsToken === koaCtx.query.access_token)
if (!bots.length) {
ctx.status = 403
ctx.body = { errcode: 'M_FORBIDDEN' }
koaCtx.status = 403
koaCtx.body = { errcode: 'M_FORBIDDEN' }
return
}
ctx.bots = bots
callback.call(this, ctx)
}
}

public constructor(ctx: Context) {
super()
const put = (path: string, callback: (ctx: KoaContext) => void) => {
ctx.router.put(path, this.hook(callback).bind(this))
ctx.router.put('/_matrix/app/v1' + path, this.hook(callback).bind(this))
}
const get = (path: string, callback: (ctx: KoaContext) => void) => {
ctx.router.get(path, this.hook(callback).bind(this))
ctx.router.get('/_matrix/app/v1' + path, this.hook(callback).bind(this))
}
put('/transactions/:txnId', this.transactions)
get('/users/:userId', this.users)
get('/room/:roomAlias', this.rooms)
const trimmed = koaCtx.path.substring(bots[0].config.path.length)
const path = trimmed.startsWith('/_matrix/app/v1/') ? trimmed.substring(15) : trimmed
if (koaCtx.method === 'PUT' && path.startsWith('/transactions/')) {
const txnId = path.substring(14)
this.transactions(koaCtx, bots, txnId)
} else if (koaCtx.method === 'GET' && path.startsWith('/users/')) {
const user = path.substring(7)
this.users(koaCtx, bots, user)
} else if (koaCtx.method === 'GET' && path.startsWith('/rooms/')) {
const room = path.substring(7)
this.rooms(koaCtx, bots, room)
} else {
koaCtx.status = 404
}
})
}

async start(bot: MatrixBot): Promise<void> {
Expand All @@ -53,37 +47,34 @@ export class HttpAdapter extends Adapter.Server<MatrixBot> {
}
}

private transactions(ctx: KoaContext) {
const { txnId } = ctx.params
private transactions(ctx: KoaContext, bots: MatrixBot[], txnId: string) {
const events = ctx.request.body.events as ClientEvent[]
ctx.body = {}
if (txnId === this.txnId) return
this.txnId = txnId
for (const event of events) {
const bots = ctx.bots
.filter(bot => bot.userId !== event.sender && bot.rooms.includes(event.room_id))
const inRoom = bots.filter(bot => bot.userId !== event.sender && bot.rooms.includes(event.room_id))
let bot: MatrixBot
if (event.type === 'm.room.member'
&& (event.content as M_ROOM_MEMBER).membership === 'invite'
&& (bot = ctx.bots.find(bot => bot.userId === event.state_key))
&& !bots.includes(bot)) {
bots.push(bot)
&& (bot = bots.find(bot => bot.userId === event.state_key))
&& !inRoom.includes(bot)) {
inRoom.push(bot)
}
bots.forEach(bot => dispatchSession(bot, event))
inRoom.forEach(bot => dispatchSession(bot, event))
}
}

private users(ctx: KoaContext) {
const { userId } = ctx.params
if (!ctx.bots.find(bot => bot.userId === userId)) {
private users(ctx: KoaContext, bots: MatrixBot[], userId: string) {
if (!bots.find(bot => bot.userId === userId)) {
ctx.status = 404
ctx.body = { 'errcode': 'CHAT.SATORI.NOT_FOUND' }
return
}
ctx.body = {}
}

private rooms(ctx: KoaContext) {
private rooms(ctx: KoaContext, bots: MatrixBot[], room: string) {
ctx.status = 404
ctx.body = { 'errcode': 'CHAT.SATORI.NOT_FOUND' }
}
Expand Down

0 comments on commit 516790d

Please sign in to comment.