多群数据分离

刚开始步入机器人插件的制作行列,对应分群的操作我想复杂了。以为得开多线程等操作…

实际上只要在全局创建一个对象。这个对象的 key 是每个群的 标识,它的 value 就是对应的分群数据即可。

{"ASMLWDNMGKDBYT":{isplaying:false,win:"AEEEDEGEGOWOWFASV"}} // 单个群数据

分群独立是最基础的操作了,我看社区没有写,我这个肛写插件的小白可以试着讲讲。希望补充说明

如何获取 群的标识

session.guildId 是群信息对象,该信息具有唯一性

ctx.command(Argv) 的 群标识id 它位于 Argv.session.guild.guildId 中,而 ctx.middleware(session,next) 的 群标识id 位于 session.guild.guildId 上。 通过它作为数据存储的 key 后,因此它就可以来访问目标群的独立数据。

如何自由获取 分群的数据

在全局创建一个函数和全局变量,传入 群标识id 或 群信息对象。并以构造函数的方式设置模板即可

// 公共数据模板
const guildData = {}

// 获取分群数据
function getguildData(guild) {
  const info = String(guild.guildId)
  // 若不存在数据 赋值模板样式
  if (!guildData[info]) guildData[info] = {
    // 存的值
    a:'123',
    b:'234',
    // 存的方法
    getData(){
      // 直接操作构造函数值
      return this.a
    }
  };
  // 返回分群数据
  return guildData[info];
}

在每次 command 函数调用时、或者 事件触发时。先获取对应分群信息。得到的数据就是分群独立的。

ctx.command('1a2b').option('/1a2b', '开始玩猜数字').action((Argv) => {

    const temp = getguildData(Argv.session.guild);

    // ...
  })
ctx.middleware(async (session, next) => {

    const temp = getguildData(session.guild);
    
    // ...
  })

该操作简单方便,注意this 指向即可。

3 个赞

注意,此种方法保存的数据在koishi或者插件重启后就会消失,如果你需要长期保存数据,请使用数据库

另外,如果你的数据需要在类似QQ频道的子频道间隔离,需要用session.event.channel.id获取ID,在QQ群之类的地方与session.guildId并无区别

4 个赞

找到个bug,没有session.guild.guildId这个属性(
还有,在入参的时候就直接把argv解构赋值了会更方便,比如

.action(({session}) => {
  session.something
})

有什么新属性要用就再加上,比方说({session, options}) =>

3 个赞

不太冷的温知识:在每一次会话中,session 是贯穿整个生命周期的。

因此你可以扩展 Session 类型,在 session 中置入并传递你需要的内容,例子:

interface MyData {
  foo: 114514
}

declare module 'koishi' {
  interface Session{
    myData: MyData
  }
}

ctx.command('1a2b').option('/1a2b', '开始玩猜数字')
  .action(({ session }) => {
    //        ^此处为 Argv 的解构语法
    session.myData.foo = 123456
    // ...
})

ctx.middleware(async (session, next) => {
    console.log(session.myData.foo) // 123456
    // ...
})

补充:

  1. ctx.command 是一个特殊的 ctx.middleware,因此也拥有 middleware 的所有特性。
  2. ctx.middleware 以程序文档内的注册顺序执行,因此当 command 在 middleware 前时,会先执行 command 所在的 middleware,然后是底下的 middleware(除非主动后置或前置)。
  3. 每一个用户的会话算作一次生命周期,所以不太需要额外为群与用户做特殊处理。
  4. Koishi 数据库自带 ChannelUser,并且为 ctx.command 加入了 Observe。如果你需要为每一个群或用户保存数据可以使用 session.channelsession.user,记得扩展字段。
3 个赞

hso

叼着笔写
6fba42c231ee71697d4bebf90da21d21

2 个赞

小学总是有奇妙的关注点呢

1 个赞