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-user-settings

v0.0.1

Published

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

Readme

User Settings (user-settings) 服务文档

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

guild-settings 专注于群聊配置不同,本服务允许用户为自己设置全局配置(在所有群聊中生效)和分群配置(仅在特定群聊中生效,且优先级更高)。

通过该服务,你的插件可以轻松地为每个用户注册和管理配置项,而无需自行处理数据库存储、作用域优先级和复杂的层级逻辑。

✨ 功能特性

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

核心概念

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

1. 服务依赖

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

import 'koishi-plugin-user-settings'

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

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

2. 配置项定义 (ConfigDefinition)

这与 guild-settings 完全相同。注册配置时需要提供一个 ConfigDefinition 对象。

interface ConfigDefinition {
  name: string;
  type: 'string' | 'number' | 'boolean' | 'null';
  parent?: string;
  description?: string;
  defaultValue: any;
}
  • name: (必需) 配置项的唯一标识符。建议使用 "插件名.分组名.配置名" 的格式。
  • type: (必需) 配置项的值类型。null 类型代表一个“文件夹”,用于组织。
  • parent: (可选) 父配置项的 name
  • description: (可选) 配置项的描述。
  • defaultValue: (必需) 配置项的默认值,类型必须与 type 匹配。

3. 作用域与优先级 (Scope & Precedence)

这是 user-settings 的核心特性。

  • 全局配置 (Global Setting): 用户的一个配置项,不关联任何特定群聊。这是用户的通用偏好。
  • 分群配置 (Per-Guild Setting): 用户在特定群聊中为同一个配置项设置的值。这会覆盖用户的全局配置。

当调用 get 方法时,服务会自动按以下顺序查找并返回第一个找到的值:

  1. 分群配置:用户在指定群聊中的设置。
  2. 全局配置:用户的全局设置。
  3. 默认值:在 ConfigDefinition 中定义的 defaultValue

4. 层级结构与逻辑

这与 guild-settings 完全相同。boolean 类型的父项可以作为其所有子项的总开关。如果一个父项在某个作用域(分群或全局)下被设为 false,那么获取其子项的值时将直接返回 null,无视子项自身的配置和更低优先级的配置。

📘 API 参考

userSettings.register(definition)

注册一个新的用户配置项。

  • 参数: definition: ConfigDefinition
  • 返回值: boolean (成功或失败)
  • guild-settingsregister 方法完全相同。

userSettings.get(userId, key, guildId?)

获取指定用户某个配置项的当前值,自动处理作用域优先级

  • 参数:
    • userId: string - 目标用户的 ID。
    • key: string - 要获取的配置项的 name
    • guildId?: string - (可选) 目标群聊的 ID。如果提供此参数,将启用“分群配置”的查找。
  • 返回值: Promise<T | null>
    • 返回根据优先级策略计算出的最终值。
    • 如果其任何一个 boolean 类型的父项为 false,则返回 null
    • 如果 key 未被注册,也会返回 null
  • 示例:
ctx.command('my-profile')
  .action(async ({ session }) => {
    // 获取用户简介。这是一个全局设置,所以不传入 guildId。
    const bio = await ctx.userSettings.get<string>(session.userId, 'profile.bio');

    // 检查用户是否希望在本群展示简介。这是一个分群设置。
    const showInGuild = await ctx.userSettings.get<boolean>(session.userId, 'profile.showInGuild', session.guildId);

    if (!showInGuild) return '用户已设置在本群隐藏简介。';

    return `用户 ${session.author.name} 的简介:${bio || '未设置'}`;
  });

userSettings.set(userId, key, value, guildId?)

为指定用户设置一个配置项的值。

  • 参数:
    • userId: string - 目标用户的 ID。
    • key: string - 要设置的配置项的 name
    • value: any - 要设置的值。
    • guildId?: string - (可选) 目标群聊的 ID。
      • 如果提供 guildId,则设置的是分群配置
      • 如果省略 guildId,则设置的是全局配置
  • 返回值: Promise<void>
  • 抛出错误: 与 guild-settings 相同,在 key 未注册、类型为 nullvalue 类型不匹配时抛出。
  • 示例:
// 设置全局简介
ctx.command('profile.bio <text:text>', '设置你的全局简介')
  .action(async ({ session }, text) => {
    // 省略 guildId,设置为全局配置
    await ctx.userSettings.set(session.userId, 'profile.bio', text);
    return '全局简介设置成功!';
  });

// 在当前群聊隐藏简介
ctx.command('profile.hide', '在本群隐藏你的简介')
  .action(async ({ session }) => {
    // 传入 guildId,设置为分群配置
    await ctx.userSettings.set(session.userId, 'profile.showInGuild', false, session.guildId);
    return '已在本群隐藏你的简介。';
  });

userSettings.list()

获取所有已注册的配置项定义的列表。

  • guild-settingslist 方法完全相同。

🚀 最佳实践:综合示例

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

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

export const name = 'user-profile'
export const inject = ['userSettings']

export function apply(ctx: Context) {
  // --- 1. 注册配置项 ---
  ctx.userSettings.register({
    name: 'profile.enabled',
    type: 'boolean',
    description: '是否启用个人资料卡功能',
    defaultValue: true,
  })

  ctx.userSettings.register({
    name: 'profile.bio',
    type: 'string',
    parent: 'profile.enabled',
    description: '用户的个人简介(全局)',
    defaultValue: '这个人很懒,什么都没留下。',
  })
  
  ctx.userSettings.register({
    name: 'profile.showInGuild',
    type: 'boolean',
    parent: 'profile.enabled',
    description: '是否在当前群聊显示个人资料卡(分群设置)',
    defaultValue: true,
  })

  // --- 2. 在命令中使用配置 ---
  ctx.command('profile', '查看你的个人资料')
    .action(async ({ session }) => {
      // get() 自动处理了父项 `profile.enabled` 和作用域优先级
      const show = await ctx.userSettings.get<boolean>(session.userId, 'profile.showInGuild', session.guildId)
      if (!show) return // 包含 false 和 null (被父项禁用)

      const bio = await ctx.userSettings.get<string>(session.userId, 'profile.bio')
      return `[个人资料]\n简介:${bio}`
    })

  // --- 3. 提供管理命令 ---
  ctx.command('profile.set.bio <bio:text>', '设置你的全局简介')
    .action(async ({ session }, bio) => {
      if (!bio) return '请输入简介内容。'
      // 省略 guildId,设置全局配置
      await ctx.userSettings.set(session.userId, 'profile.bio', bio)
      return '简介设置成功!'
    })

  ctx.command('profile.toggle', '切换在本群是否显示你的资料')
    .action(async ({ session }) => {
      // 获取当前分群设置(如果不存在则获取全局,最后是默认值)
      const current = await ctx.userSettings.get<boolean>(session.userId, 'profile.showInGuild', session.guildId)
      // 传入 guildId,设置分群配置
      await ctx.userSettings.set(session.userId, 'profile.showInGuild', !current, session.guildId)
      return `资料卡在本群的显示状态已切换为:${!current}`
    })
}