如何获取全局配置和其他插件的配置信息?

如题如题如题如题

2 个赞

一般情况下,你不能这么做。访问其他插件的配置是危险行为,你的插件可能被标记为不安全。

特殊情况下,一个插件如果想公开配置给别的插件使用,它可以将自己实现为服务,然后其他插件可以通过 ctx.xxx.config 访问。

2 个赞

我刚找到了一个解决方法

const koishiConfig = require(ctx.baseDir + "/koishi.yml");
const larkConfig = findValue(koishiConfig, "lark");
logPrettyJson(larkConfig);

function findValue(obj: { [key: string]: any }, searchStr: string): any | null {
  for (const [key, value] of Object.entries(obj)) {
    if (key.includes(searchStr)) return value;
    if (value && typeof value === "object") {
      const found = findValue(value, searchStr);
      if (found) return found;
    }
  }
  return null;
}

确实不太安全的样子,安装一个恶意插件就可以获取其他插件、适配器的密钥了。

但是不安全就不安全吧,主要也是我自己用,我读我自己的配置。

1 个赞

在不安全的情况下,你可以访问 ctx.loader.config 来获取配置文件内容,省得你解析 yaml 了。

3 个赞

顺便,未来的版本中配置文件的格式可能发生变化,可以留意一下后续更新日志。

3 个赞

May I ask why do you want to get the configurations for lark plugin? Since it should expose several properties in the bot instance.

1 个赞

早说嘛。解决方案转给你。

1 个赞

因为我在开发企业定制的飞书机器人,需要自己对接飞书开放平台的 api 处理更多操作。

我已经在 lark 适配器插件中配置过我的应用的 api 密钥了,我不想在我自己的飞书机器人插件中重新配置一遍,所以我就重复利用一下已有的配置。

1 个赞

哦这个需求的话可以等一下 lark 的 internal API。

1 个赞

You can just bot.http(url) while bot is the instance of LarkBot.

1 个赞

我先暂时这么用吧,希望 internal API 中也能开放自动刷新的 tenant_access_token。

如果可能的话,希望增加使用 获取单个用户信息 - 服务端 API - 开发文档 - 飞书开放平台 (feishu.cn) 以及类似的 API 获取用户的更多信息以完善 username 等字段的功能。

还有一个问题是我想要获取用户的 union_id 和 user_id,目前我尝试了一下,只能通过

session.event['_data']?.event?.sender?.sender_id

来获取,有什么更好的方法吗?

1 个赞

Impossible.

That would be dangerous since other plugins could steal the token.

Yeah, this is annoying currently. There’s only one ID for each user in Koishi’s philosophy, so it is hard to define multiple IDs compatible for Koishi now. Maybe we could figure it out int the future.

1 个赞

竟然还有这种 API。它的作用是什么?文档里没找到。

该如何获取这个 bot 变量呢?
我尝试

logPrettyJson(session.bot)
logPrettyJson(session.bot.http)

结果是
image

1 个赞

It is just a ctx.http but includes tokens and other settings. It is undocumented, only for internal use.

EDIT: By the way, I think your logPrettyJson function perhaps does a JSON.stringify() before logging it to the console, you should be aware that JS functions are not stringifiable.

1 个赞

This is only available for LarkBot.

So you should first check the platform:

if (session.platform === 'lark') {
 //...
}

Then cast the session.bot to LarkBot type :

(session.bot as LarkBot).http()
1 个赞

如果像上面所说的可以通过 internal API 来共享配置,那我也可以自行拿到 tenant_access_token 。无非就是手动获取和 Koishi 代理获取的区别。

对于安全性问题,能不能出一个容器的功能。可以保证这个容器只有我一个插件和必要的官方服务在运行,相当于新开一个 Koishi 示例,这样的话可以做到插件隔离。

这样的话不仅可以保证我的指令命名不会被其他插件覆盖,也可以增强数据隐私安全性。

其实可以简单的增加一个 platformId 字段,里面包含这个平台定义的多种 id,至少不用我这么长地获取这些东西。

1 个赞

你提醒了我。

function prettyJson(obj: any) {
  return JSON.stringify(
    obj,
    (key, value) => {
      if (typeof value === "function") {
        return value.toString();
      }
      return value;
    },
    2
  );
}

function logPrettyJson(obj: any) {
  logger.info(prettyJson(obj));
}

现在可以了 :)

1 个赞

You’re right, so IMO this would be a vulnerability.

You know, Koishi and the related projects are just driven by interest, so we did not consider much about enterprise-level security. But the Cordis (the AOP framework that Koishi depends on) introduced the isolating feature several months ago, so it would be easier to implement the “container” that you mentioned above once we landed it.

Okay, I would consider it once we have more Lark API support landed.

2 个赞

我很需要隔离。

我有两个不同的插件,插件的每个指令我都加上了插件名作为命名空间,已经保证了原名的唯一性。

但是我这两个插件分别在两个不同的平台使用,功能完全不一样,为了易用性,我需要给其中的某条指令设置别名 ”重置“。而这个功能在这两个插件中都有。

虽然我通过插件的过滤器设置好了这个插件只能在这个平台上用,但是别名似乎无法设置过滤器,它是全局的。

如果我禁用了其中一个别名,在那个平台上的那个指令就会无法触发。

现在我只能通过开两个 Koishi 实例来实现这一点。 :cry:

2 个赞

此处的隔离与上文不是同一语义。

你的需求在目前设计里应该是无法实现的。我认为你可以写一个新的别名插件,使用中间件来将用户输入的别名重定向为执行对应的指令,从而绕过指令空间全局唯一的限制。

2 个赞