请问应该如何用 HTTP API 与 Bot 交互?(记录了satori-server 的失败尝试)

我的最终需求:我已经有一个接入了官方QQ的bot。希望能暴露一个 HTTP API,接受 POST(query信息),在回复中包含 bot 回应,功能与上述bot一致

通过检索论坛,看起来satori是最适合做这件事情的,我也根据文档使用了satori-server。我在本地测试环境搭建了一个沙盒,但所有请求都会报错login not found(我不敢直接上生产环境,用户太多了)。我定位到了相关源码,并且debug发现satori-server的ctx.bots为空,导致鉴权不可能成功,代码如下。

请问:

  1. 我这套解决思路是否正确?(即这是否是个X/Y问题,我解决的思路就不对)
  2. 为什么在测试环境下,我可以通过沙盒通信,但ctx.bots为空?
import requests

headers = {
    # 'Content-Type': 'application/json',
    # 'Authorization': 'Bearer 1',
    'Satori-Platform': 'sandbox:db5fyc81f34',
    'Satori-User-ID': 'Alice'
}
#
content = 'thpt xxx'
r = requests.post('http://localhost:5140/satori/v1/message.create', data={
    'channel_id': 'API', 'content': content
}, headers=headers)
print(r.text)
print(r.status_code)
1 个赞

satori-server 的用途是暴露 koishi/satori 本身所连接的 Bots

而根据你的描述,你需要的应该是一个适配器(或者至少可以以类似的形式实现)

至于社区里似乎没有现成的实现(其实nnhr有一个古老的 koishi-plugin-api,不过我不确定大概是不能用了罢)我认为是因为 koishi 本身并非是线性设计,收到消息未必有回复(也未必是单一的、一次性的回复),即使有这之间的处理时间也是未知的,从而如果用 http 的 req → resp 模型来抽象会相当受限。以及作为适配器还需考虑其他 channel/user 资源等问题。

不过对于具体的情况,我突然有个简单的想法。很久以前我写了个 @hieuzest/koishi-plugin-execute 所以你只需要

import { Context } from 'koishi'
import {} from '@koishijs/plugin-server'
import {} from '@hieuzest/koishi-plugin-execute'

export const inject = ['server', 'execute']

export function apply(ctx: Context) {
  ctx.server.post('/api', async (kCtx) => {
    const { content } = kCtx.request.body
    const result = await ctx.execute(content)
    kCtx.body = result.toString()
  })
}

是不是就可以实现你的需求了【】

2 个赞

太棒了,解答的很好,方案也可以解决当前问题。写Adapter的方案我也评估过(在Q群里问了一下,得到的答案就是要写adapter)。但是感觉Adapter方案太重了(而且我吭哧吭哧写了几行跑不起来,雾);所以又回来看了satori然后一头雾水 :smiling_face_with_tear:

想额外问下,你基于execute的这个方案会有什么隐患吗,我看起来还挺合理的,也挺泛用的

Edit: 如果有人有类似需求,已基于楼上的代码发布了包 koishi-plugin-adapter-api-exec。API路径写死为 /api/adapter ;通过content字段表示输入

1 个赞

应该不会有什么大的隐患,要说的话就是因为所有消息共享了一个固定且虚拟的 bot/channel/user,因此试图去对应 channel/user 的行为是无法成立的 (比如bind)

看了一下你群里发的原始场景,那你实际上是有 channel/user 的,那完善的做法肯定是写一个完整的适配器【】

1 个赞

没事,我那边的用户比较少,而且都是可控用户(熟人),能把主功能都做好就行。更完善的做法可以是基于execute去继续实现channel/user,在headers/payload里带用户信息。但这样也会有新的零信任鉴权问题,要保证全流程受控,还不如继续摆烂等koishi-原始场景平台-adapter(

1 个赞