npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

koishi-plugin-guild-settings

v0.0.1

Published

提供一个可供其他插件使用的、层级化的群聊配置服务

Downloads

154

Readme

Guild Settings (guild-settings) 服务文档

koishi-plugin-guild-settings 是一个为 Koishi 插件开发者设计的底层服务,旨在提供一个统一、强大且类型安全的群聊配置管理方案。

通过该服务,你的插件可以轻松地为每个群聊注册和管理配置项,而无需自行处理数据库存储、类型校验和复杂的层级逻辑。它使得插件配置的开发变得标准化和模块化。

✨ 功能特性

  • 中心化管理:所有插件的群聊配置都通过同一个服务进行管理。
  • 层级化结构:支持无限层级的父子配置项,轻松组织复杂设置。
  • 逻辑联动boolean 类型的父项可以作为开关,一键禁用其下所有子项。
  • 类型安全:在注册和设置时进行严格的类型校验,杜绝非法数据。
  • 持久化存储:所有配置值都通过 Koishi 的 database 服务进行持久化。
  • 开发者友好:提供简洁的 API,易于集成到任何插件中。

核心概念

在使用 API 之前,请先理解以下几个核心概念。

1. 服务依赖

本插件向 Koishi 上下文注入一个名为 guildSettings 的服务。任何需要使用此功能的插件,都必须声明对其的依赖。

import 'koishi-plugin-guild-settings'

export const name = 'my-plugin'
export const inject = ['guildSettings'] // 声明必需依赖

export function apply(ctx) {
  // 现在你可以通过 ctx.guildSettings 访问服务了
}

2. 配置项定义 (ConfigDefinition)

当你的插件需要一个可配置的选项时,你需要先“注册”它。注册时需要提供一个 ConfigDefinition 对象,它描述了这个配置项的一切。

interface ConfigDefinition {
  name: string;
  type: 'string' | 'number' | 'boolean' | 'null';
  parent?: string;
  description?: string;
  defaultValue: any;
}
  • name: (必需) 配置项的唯一标识符。强烈建议使用 "插件名.分组名.配置名" 的格式,以避免冲突。例如:welcome.message.text
  • type: (必需) 配置项的值类型。
    • string, number, boolean: 基本数据类型。
    • null: 特殊类型,表示此配置项是一个“文件夹”或“分组”,它本身不能被赋值,仅用于组织其他配置项。
  • parent: (可选) 父配置项的 name。如果指定,此配置项将成为其子项。
  • description: (可选) 对此配置项的描述,方便未来的管理插件(如 CLI 或 Web UI)展示给用户。
  • defaultValue: (必需) 该配置项的默认值。当群聊未进行任何设置时,get 方法将返回此值。其类型必须与 type 字段严格匹配。

3. 层级结构与逻辑

父子关系是本服务的核心。

组织型父项 (type: 'null')

当一个父项的类型为 null 时,它主要起组织和分类的作用,就像文件系统中的文件夹。它本身没有值,只是一个路径节点。

// 'welcome.message' 是一个组织型父项
ctx.guildSettings.register({ name: 'welcome.message', type: 'null', defaultValue: null })
ctx.guildSettings.register({ name: 'welcome.message.text', type: 'string', parent: 'welcome.message', defaultValue: '欢迎!' })

逻辑型父项 (type: 'boolean')

当一个父项的类型为 boolean 时,它扮演着一个“总开关”的角色。

  • 当这个父项的值在某个群聊中为 true (或默认值为 true 且未被修改) 时,其所有子项功能正常。
  • 当这个父项的值在某个群聊中被设为 false 时,获取其任何子项的值都会直接返回 null,无论子项本身被设置成了什么。

这对于实现一键启用/禁用整个模块的功能非常有用。

// 'welcome.enabled' 是一个逻辑型父项
ctx.guildSettings.register({ name: 'welcome.enabled', type: 'boolean', defaultValue: true })
ctx.guildSettings.register({ name: 'welcome.text', type: 'string', parent: 'welcome.enabled', defaultValue: '...' })

// 在某个群聊中
await ctx.guildSettings.set(guildId, 'welcome.enabled', false)
// 此时,即使 'welcome.text' 曾被设为其他值,获取它也会得到 null
const text = await ctx.guildSettings.get(guildId, 'welcome.text') // text === null

📘 API 参考

guildSettings.register(definition)

注册一个新的配置项。插件应该在 apply 函数中立即调用此方法来声明自己需要的所有配置。

  • 参数:
    • definition: ConfigDefinition - 配置项的定义对象。
  • 返回值: boolean
    • true: 注册成功。
    • false: 注册失败。通常是因为 name 冲突、parent 不存在或不合法、defaultValue 类型不匹配等。失败信息会通过 ctx.logger.warn 打印。
  • 示例:
export function apply(ctx) {
  const success = ctx.guildSettings.register({
    name: 'myPlugin.feature.enabled',
    type: 'boolean',
    description: '控制 myPlugin 的核心功能开关',
    defaultValue: true,
  });

  if (!success) {
    ctx.logger.error('插件配置项注册失败,部分功能可能无法使用!');
  }
}

guildSettings.get(guildId, key)

获取在指定群聊中,某个配置项的当前值。

  • 参数:
    • guildId: string - 目标群聊的 ID。
    • key: string - 要获取的配置项的 name
  • 返回值: Promise<T | null>
    • 返回该配置项的值,类型为 T
    • 如果数据库中没有记录,则返回其 defaultValue
    • 如果其任何一个 boolean 类型的父项为 false,则返回 null
    • 如果 key 未被注册,也会返回 null
  • 示例:
ctx.command('my-feature')
  .action(async ({ session }) => {
    const isEnabled = await ctx.guildSettings.get<boolean>(session.guildId, 'myPlugin.feature.enabled');
    if (!isEnabled) { // 包含了 false 和 null 两种情况
      return '此功能当前已禁用。';
    }
    // ... 执行功能
  });

guildSettings.set(guildId, key, value)

为指定群聊设置一个配置项的值。

  • 参数:
    • guildId: string - 目标群聊的 ID。
    • key: string - 要设置的配置项的 name
    • value: any - 要设置的值。其类型必须与注册时定义的 type 严格匹配。
  • 返回值: Promise<void>
  • 抛出错误:
    • 如果 key 未注册、key 的类型是 null、或 value 的类型不匹配,将抛出 ErrorTypeError
  • 示例:
ctx.command('my-feature.enable', '启用 my-feature 功能')
  .action(async ({ session }) => {
    try {
      await ctx.guildSettings.set(session.guildId, 'myPlugin.feature.enabled', true);
      return '功能已启用。';
    } catch (e) {
      ctx.logger.error(e);
      return '设置失败,请联系管理员。';
    }
  });

guildSettings.list()

获取所有已注册的配置项定义的列表。这对于开发设置管理插件非常有用。

  • 参数: 无。
  • 返回值: ConfigInfo[] - 一个包含所有 ConfigDefinition 对象的数组。
  • 示例:
ctx.command('settings.listall', '列出所有可配置项')
  .action(({ session }) => {
    const allSettings = ctx.guildSettings.list();
    const output = allSettings.map(s => `${s.name} (${s.type}) - 默认值: ${s.defaultValue}`).join('\n');
    return output;
  });

🚀 最佳实践:综合示例

下面是一个虚构的 welcome 插件,展示了如何综合运用所有 API。

import { Context } from 'koishi'
import 'koishi-plugin-guild-settings'

export const name = 'welcome'
export const inject = ['guildSettings']

export function apply(ctx: Context) {
  // --- 1. 注册配置项 ---
  ctx.guildSettings.register({
    name: 'welcome.enabled',
    type: 'boolean',
    description: '是否启用欢迎新成员功能',
    defaultValue: true,
  })

  ctx.guildSettings.register({
    name: 'welcome.message',
    type: 'string',
    parent: 'welcome.enabled',
    description: '欢迎语内容,{user} 会被替换为新成员的艾特',
    defaultValue: '欢迎新成员 {user}!',
  })

  // --- 2. 在事件中使用配置 ---
  ctx.on('guild-member-added', async (session) => {
    // get() 自动处理了父项 `welcome.enabled` 为 false 的情况
    const messageTemplate = await ctx.guildSettings.get<string>(session.guildId, 'welcome.message');

    if (messageTemplate) {
      const output = messageTemplate.replace('{user}', `<at id="${session.userId}"/>`);
      await session.send(output);
    }
  })

  // --- 3. 提供管理命令 ---
  ctx.command('welcome.set <message:text>', '设置欢迎语')
    .action(async ({ session }, message) => {
      if (!message) return '请输入欢迎语内容。';
      try {
        await ctx.guildSettings.set(session.guildId, 'welcome.message', message);
        return '欢迎语设置成功!';
      } catch (e) {
        return '设置失败,可能是因为欢迎功能被总开关关闭了。';
      }
    })
}