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-giveaway

v1.0.1

Published

A versatile giveaway plugin for Koishi: interactive giveaway creation, scheduled auto-draw, reminders, i18n and multi-timezone support.

Readme

koishi-plugin-giveaway

npm license CI

一个多功能的 Koishi 群抽奖插件:复制模板即可创建抽奖、支持参与门槛(群聊等级 / 活跃度 / QQ 群互动标识)、口令或指令两种参与方式、定时自动开奖与开奖前提醒、可选图片卡片,权限沿用 Koishi 原生等级,内置简体中文 / English / Deutsch 三语与多时区。

A giveaway plugin for Koishi: create a giveaway by filling in a text template, join conditions (group level / activity / QQ group honors), keyword or command joining, scheduled auto-draw with reminders, optional image cards, Koishi-native permissions, i18n (zh-CN / en-US / de-DE) and multi-timezone support.

本项目派生自 Roll-Bot-Project/roll-bot(MIT),本仓库独立维护与发布,问题请提到本仓库。

目录

完整的功能清单与交互矩阵见 docs/features-and-interactions.md;发版步骤与冒烟清单见 docs/release-checklist.md。

维护状态

  • 1.0.0 是首个正式版本,功能面已稳定:1.0 起配置项与数据结构只增不删,小版本只修缺陷
  • 预期使用规模不大,因此 1.0 之后不做常规迭代:只有在社区反馈缺陷或有明确需求时才更新
  • 不承诺与 0.x 的兼容:从 0.x 升级请按本 README 重新配置(配置项含义与数据模型都按当前版本为准); 0.x 的变更历史见 CHANGELOG-0.x.md
  • 遇到问题请提 Issue,附上 抽奖接口诊断 的输出与插件日志

特性

创建与参与

  • 复制模板创建:创建抽奖 发一份纯文本模板(含当前控制台的参与条件),逐项填写后发回即可;留空即默认,按标签解析,群里随口一句不会被误当成奖品
  • 每个抽奖可单独设置参与条件:模板里的「参与条件」一行可沿用控制台配置、删空(该抽奖不限制)或改写(自定义门槛)
  • 两种参与方式:在群里发送抽奖的加入口令,或使用 加入抽奖 <编号>
  • 拒绝时说明原因:等级不足 / 最近没发言 / 连续天数不够 / 缺少标识;参与者被拒之前也能在详情里看到当前生效的条件

抽奖流程

  • 定时自动开奖:创建时填了开奖时间即到点自动开奖,也可随时手动 开奖;开奖后按 cacheHours 自动清理记录
  • 开奖消息 @ 中奖者:中奖行是真正的 @ 元素(QQ 里会提醒到人),并保留 QQ 号便于留档
  • 开奖前提醒:按「创建时距开奖的剩余时长」分档,在剩余时长的百分比处自动播报(默认每场只提醒一次)
  • 可选的图片卡片:安装并启用 koishi-plugin-puppeteer 后,创建结果 / 抽奖详情 / 参与名单 / 抽奖列表 / 开奖结果都可渲染成图片;未安装或渲染失败时自动回退为文字消息

参与条件(可组合,任一不满足即拒绝并说明原因)

  • 群聊等级下限(QQ 群聊等级 1~100)
  • 最近 N 天内发过言(不依赖 QQ 网页接口,最稳的条件)
  • 最长连续发言天数(可自定义门槛,如「连续 ≥ 14 天」)
  • QQ 群互动标识:群聊之火 / 群聊炽焰 / 龙王,可选「满足任一」或「必须全部」;龙王还可在「昨日活跃榜」与「仅当前龙王」之间切换口径

其它

  • 权限沿用 Koishi 原生等级(0 封禁 / 1 用户 / 3 管理员 / 4 超管),创建者始终可管理自己的抽奖
  • 三语 + 多时区:群消息、指令表、控制台配置说明、图片卡片标签都跟随语言;开奖时间按用户 / 频道 / 默认时区逐级解析
  • 参与名单:详情与 抽奖成员 都能列出参与者(头像 + 昵称 + QQ 号),图片里可限制最多显示几人
  • 诊断指令:管理员可一键排查群成员 / 群荣誉取数接口,原始返回写入插件日志

安装

# Koishi 控制台:插件市场搜索 giveaway 安装
# 或
npm i koishi-plugin-giveaway
  • 必需服务:database(抽奖记录)、assets(图片资源)
  • 可选服务:puppeteer(图片卡片;不装则全部走文字消息)

指令列表

所有指令都挂在根指令 giveaway(别名 抽奖)下。子指令可写全路径(giveaway.detail)或直接用别名(抽奖详情);giveaway.h 这类短别名需连同 giveaway 一起输入。前缀由应用配置决定。

| 指令 | 中文别名 / 短别名 | 参数 / 选项 | 权限 | | --- | --- | --- | --- | | giveaway | 抽奖 | — | 任何人(输出指令一览) | | giveaway.help | 抽奖帮助、giveaway.h | — | 任何人 | | giveaway.add | 创建抽奖 | [奖品] [开奖时间] [口令];-t 标题 / -d 描述 / -r 允许重复中奖 | ≥ authorityCreate(默认 1)或群主/群管理员 | | giveaway.list | 抽奖列表、在抽啥、giveaway.ls | [平台] [频道id] | 任何人 | | giveaway.detail | 抽奖详情 | <编号> | 任何人 | | giveaway.member | 抽奖成员、giveaway.mem | <编号> | 任何人 | | giveaway.join | 加入抽奖、giveaway.j | <编号> | 任何人(需满足参与条件) | | giveaway.quit | 退出抽奖、giveaway.q | <编号> | 任何人 | | giveaway.end | 开奖、giveaway.draw | [编号] | ≥ authorityManage(默认 3)、创建者,或群主/群管理员(可关) | | giveaway.delete | 删除抽奖、giveaway.rm | <编号> | ≥ authorityManage、创建者,或群主/群管理员(可关) | | giveaway.time | 时区 | [偏移];-c 本频道 / -d 默认 | ≥ authorityManage 或群主/群管理员 | | giveaway.locale | 语言 | [语言];-c 本频道 / -d 默认 | ≥ authorityManage 或群主/群管理员 | | giveaway.channel | 频道id | — | 任何人(查看当前频道 id) | | giveaway.debug.honor | 抽奖接口诊断 | — | ≥ authorityManage | | giveaway.debug.member | 抽奖成员诊断 | [用户] | ≥ authorityManage |

直接发 抽奖(或 抽奖帮助)会输出一份按语言分组的指令一览:中文环境显示中文别名,英文 / 德文环境显示注册名,管理员额外看到诊断指令。

交互详解

创建抽奖

> 创建抽奖
< 请复制下面这份模板,把每一项填好后发回给我(不需要的项留空即可):
< 奖品:
< 开奖时间:
< 加入口令:
< 标题:
< 描述:
< 参与条件:等级≥40 活跃≥1 标识=群聊炽焰,龙王
< 说明一:奖品格式为「名称*数量」,多个奖品用逗号或空格分隔;开奖时间格式为「月-日-时-分」或「年-月-日-时-分」,留空表示不自动开奖。
< 说明二:「参与条件」一行可以不改(沿用控制台配置)、删空(本抽奖不做限制),或照「等级≥40 活跃≥1 连续≥7 标识=群聊炽焰,龙王」改写。
> 奖品:显卡*1,鼠标*2
> 开奖时间:09-15-20-00
> 加入口令:参加
> 标题:双十一抽奖
> 描述:满 40 级可参加
  • 一次往返即可完成;解析按标签取值,顺序无关,中 / 英 / 德标签与全角冒号都能识别,整段复制粘贴(含说明行)也可用
  • 留空的项按默认处理:开奖时间留空 = 不自动开奖、口令留空 = 不用口令、标题 / 描述留空 = 默认值;只有奖品必填
  • 奖品格式 名称*数量(数量可省略,默认 1);多个奖品可用逗号 / 顿号 / 空格分隔
  • 取消创建:回复 q / quit / cancel / 取消 / abbrechen、超时不回、缺奖品或格式非法都会取消
  • 开奖时间必须晚于当前时间(填过去的时间会要求重新填写,避免出现永远不会自动开奖的抽奖)
  • 位置参数写法(跳过模板步骤):抽奖 add 显卡*1 09-15-20-00 参加,-t / -d / -r 同样可用
  • 参与条件一行的三种改法:不改 = 沿用控制台配置;删空 = 这个抽奖不做任何限制;改写 = 只覆盖写了的项(如 等级≥60 标识=龙王)。文本表达不了的口径(多标识判定、龙王口径)只在控制台配置、对所有抽奖动态生效

参与与查询

  • 关键词加入:直接在群里发送抽奖的加入口令(消息内容需与口令完全一致)
  • 加入抽奖 <编号> / 退出抽奖 <编号>:指令式参与与退出;重复加入、未加入退出都会给出对应提示
  • 开奖后名单即固定:已经开奖的抽奖不能再加入、也不能退出(口令与指令两条路径一致拦截)
  • 不满足参与条件时会回复具体原因(当前等级、上次发言距今天数、缺少哪个标识、数据暂不可用)
  • 抽奖列表 [平台] [频道id]:列出本频道的抽奖(进行中 / 已结束),带上平台与频道 id 可跨频道查询
  • 抽奖详情 <编号>:标题、截止时间、描述、当前生效的参与条件、口令、奖品、参与名单;已开奖的抽奖附中奖名单
  • 抽奖成员 <编号>:参与名单(头像 + 昵称 + QQ 号,图片版最多显示 render.memberLimit 人,超出会提示剩余人数)

开奖与删除

  • 开奖 [编号]:不填编号时会列出你创建的、尚未开奖的抽奖,回复编号即可开奖
  • 参与人数少于奖品数时:未开启「允许重复中奖」的抽奖只抽出与参与人数相同的名额(剩余奖品不发放,不会同一个人重复拿走多个奖品)
  • 到点自动开奖:创建时填了开奖时间的抽奖会自动开奖,并把结果广播到抽奖所在的全部频道
  • 开奖结果 = 一条带真实 @中奖者 的文字行 + 结果图片(开图时仍保留文字,图片叫不动人)
  • 删除抽奖 <编号>:删除抽奖(同时清理参与名单与已排定的提醒)
  • 开奖后记录按 cacheHours(默认 72 小时)保留,到期自动清理

开奖提醒

提醒由控制台配置驱动,配置是一张按剩余时长分档的规则表:每行 = 「时长上限」+「提醒位置(剩余时长的百分比)」。

默认规则:

| 时长上限 maxDuration | 提醒位置 percent | 含义 | | --- | --- | --- | | 1h | 20 | 创建时距开奖 ≤1 小时:开奖前 20% 处提醒(1 小时场次 → 开奖前 12 分钟) | | 5h | 15 | 1~5 小时:开奖前 15% 处(5 小时场次 → 开奖前 45 分钟) | | 1d | 10 | 5 小时~1 天:开奖前 10% 处(1 天场次 → 开奖前约 2.4 小时) | | 0(不限) | 10 | 1 天以上:开奖前 10% 处(7 天场次 → 开奖前约 16.8 小时) |

  • 一个抽奖只命中一行(上限最小且不小于自身时长的那行)→ 默认每场只提醒一次;提醒时机随时长自动缩放
  • maxDuration 支持 30m / 1h / 5h / 1d / 7d(纯数字 = 分钟),0 或留空 = 不限(兜底行)
  • percent 填 1~99;同一行写多个(如 20,10)即多次提醒
  • 到点在抽奖所在的全部频道播报倒计时(按频道语言本地化)
  • 提醒任务随抽奖生命周期自动清理:开奖、删除、记录过期时一并取消;机器人重启时按当前配置重建
  • 只对填了开奖时间的抽奖生效;整张表清空 = 不提醒

设置与帮助

  • 时区 [偏移]:查看 / 修改时区,-c 只改本频道、-d 改默认值(影响开奖时间与提醒的本地时间显示)
  • 语言 [语言]:查看 / 修改语言偏好,-c 只改本频道、-d 改默认值
  • 频道id:显示当前频道 id(跨频道查询抽奖或排查绑定时用)
  • 抽奖帮助 / 直接发 抽奖:输出指令一览

管理员诊断

  • 抽奖接口诊断:逐个打印 Cookie、NapCat 群荣誉接口、QQ 网页荣誉接口的可用性与返回条数,便于定位「取不到数据」的原因
  • 抽奖成员诊断 [用户]:打印某个群成员的 level / last_sent_time / join_time / role
  • 两者都会把完整原始返回写入插件日志,群里只显示摘要

配置

| 组 | 键 | 说明 | | --- | --- | --- | | basic | cacheHours | 开奖后抽奖记录的保留时长(小时),默认 72 | | | defaultTimeOffset | 未设置时区的用户默认使用的时区偏移,默认 +8 | | permission | authorityCreate | 创建抽奖所需的最低权限等级,默认 1 | | | authorityManage | 管理他人抽奖(删除 / 手动开奖)所需的最低权限等级,默认 3 | | | allowGuildAdminDelete | 群主与群管理员是否可删除本群抽奖,默认开启 | | | allowGuildAdminEnd | 群主与群管理员是否可对本群抽奖手动开奖,默认开启 | | join | minGroupLevel | 参与所需最低群聊等级(0 = 不限) | | | minActiveDays | 最近 N 天内需发过言(0 = 不限) | | | minContinuousDays | 最长连续发言天数下限(0 = 不限,建议 ≥7) | | | requiredHonors | 需持有的群互动标识:群聊之火 / 群聊炽焰 / 龙王(可多选) | | | honorMode | 多标识判定:满足任一(默认)/ 必须全部 | | | dragonScope | 「龙王」口径:昨日活跃榜(默认)/ 仅当前龙王 | | | onFetchError | 取不到成员 / 荣誉数据时:放行(默认)/ 拒绝 | | | cacheMinutes | 群荣誉数据的缓存时长(分钟),默认 5 | | render | style | 图片卡片风格:default(Koishi 品牌蓝紫渐变)/ anime(二次元:樱花粉 + 薰衣草紫、圆润描边、表情与星光)/ avemujica(暗紫黑 + 玫红 + 哥特金、衬线字体、纹章装饰、罗马数字名次) | | | banner | 卡片顶部头图(可选):http(s) / data: / file: URL 或本机绝对路径(自动转 file://),留空不显示 | | | width | 卡片宽度(CSS px,320~900,默认 420):图片会按聊天窗口缩放,越窄字体显示越大 | | | create | 创建成功后把抽奖内容渲染成图片(图片代替文字成功提示),默认开启 | | | detail | 抽奖详情 用图片重新渲染抽奖卡片,默认开启 | | | member | 抽奖成员 用图片渲染参与名单,默认开启 | | | memberLimit | 图片里参与名单最多显示几人(1~100,默认 12),超出提示「…… 等共 X 人」 | | | list | 抽奖列表 用图片渲染,默认开启 | | | result | 开奖结果用图片渲染,默认开启 | | | avatar | 开奖结果图片里显示中奖者头像与昵称,默认开启 | | remind | rules | 开奖提醒规则表(见「开奖提醒」),默认 4 行:1h→20 / 5h→15 / 1d→10 / 0→10 |

图片渲染(可选)

装上并启用 koishi-plugin-puppeteer 后,下列消息会改用内置 HTML 模板渲染成图片:

| 消息 | 图片内容 | 渲染失败 / 未装 puppeteer 时 | | --- | --- | --- | | 创建成功(创建抽奖) | 标题、编号、开奖时间、描述、加入口令、奖品、参与条件(图片代替文字) | 回退为文字成功提示 | | 抽奖详情 <编号> | 与创建时同一张卡片 + 状态、参与人数、参与名单;已开奖附中奖名单 | 回退为文字详情 | | 抽奖成员 <编号> | 参与名单:头像 + 昵称 + QQ 号 | 回退为文字名单 | | 抽奖列表 | 进行中 / 已结束状态、编号、标题、截止时间 | 回退为文字列表 | | 开奖广播 | 开奖编号、中奖者(头像 + 昵称 + QQ 号)、每人获得的奖品 | 回退为完整文字消息 |

交互矩阵(是否出图只取决于「装了 puppeteer」+「对应开关」):

| 依赖 / 开关 | 创建结果 | 抽奖详情 | 抽奖成员 | 抽奖列表 | 开奖结果 | | --- | --- | --- | --- | --- | --- | | 未装(或未启用)puppeteer | 文字 | 文字 | 文字 | 文字 | 文字(含 @ 中奖者) | | 装了 puppeteer 且 render.* 开启 | 图片 | 图片 | 图片 | 图片 | 文字(@ 中奖者)+ 图片 | | 装了 puppeteer 但对应开关关闭 | 文字 | 文字 | 文字 | 文字 | 文字 |

设计取舍:

  • 图片宽度 = 卡片宽度:渲染服务截取的是 body 包围盒,因此 body 收缩到卡片大小,不铺满浏览器视口(否则截图会按视口宽度带上大片背景,且图片过宽导致群里字体很小);默认卡片宽 420px,可用 render.width 调整
  • 开奖消息始终保留文字部分:图片没法提醒到人,所以出图时仍会发一条带真实 @中奖者 的文字行,图片附在后面
  • 渲染失败只打一条 warn 日志(含原因)并回退文字,不会影响开奖 / 列表本身的逻辑
  • 图片里的标签随语言变化(简体中文 / English / Deutsch),用户输入(标题、昵称)会做 HTML 转义
  • 中奖者与参与者头像:优先用 OneBot 用户资料里的 avatar,取不到就按 QQ 号拼 qlogo 地址;昵称取不到时退化为只显示 QQ 号,头像加载失败时显示昵称首字
  • 参与名单有人数上限:头像行很高,人数一多图片会长到没法看,所以按 render.memberLimit(默认 12)截断并提示剩余人数
  • 头图(render.banner):可给卡片顶部加一张横幅图,三种风格通用;插件不内置任何第三方美术素材

参与条件

  • 数据来源:OneBot 的 get_group_member_info(level 群聊等级、last_sent_time 最后发言)+ QQ 群荣誉接口(群聊之火 / 群聊炽焰 / 龙王,含连续天数)
  • 荣誉取数走插件自实现的新版网页接口(qun.qq.com 的 honor_* 接口 + CSRF 令牌 bkn),并会自动探测可用的鉴权方式
  • 取不到数据时按 onFetchError 处理:放行(默认,跳过取不到的条件)或拒绝(提示稍后再试);荣誉结果按 cacheMinutes 缓存
  • 每个抽奖可覆盖:详情里显示的是实际生效的条件;与全局等价的覆盖不会额外落库
  • 连续天数门槛注意:QQ 的连续发言榜只收录连续 ≥7 天的人,门槛建议设在 7 以上,并配合「最近发过言」一起使用

权限模型

  • 只使用 Koishi 原生权限等级(0 封禁 / 1 普通用户 / 3 管理员 / 4 超级管理员),可用 admin user.authorize <等级> 或控制台的用户页面调整
  • 创建者始终可以管理自己的抽奖;群主 / 群管理员默认可以删除与手动开奖(两个开关可关)
  • 管理类指令(开奖 / 删除抽奖 / 时区 / 语言 / 诊断)按 authorityManage 判定
  • 参与条件与权限无关:任何人都要满足条件才能加入

数据与事件

插件使用以下数据表(均由插件自动创建):

| 表 | 用途 | | --- | --- | | roll | 抽奖主体(编号 / 标题 / 描述 / 口令 / 开奖时间 / 是否自动开奖 / 是否已开奖 / 中奖人可否重复) | | prize、roll_prize | 奖品与「抽奖 × 奖品」关联 | | roll_creator | 抽奖创建者 | | roll_member | 参与名单(按加入顺序);对 (roll_id, user_id) 建唯一索引(老库在表首次被访问时自动补建),同一抽奖里同一用户只会有一条记录 | | roll_channel | 抽奖与频道的关联(决定广播范围) | | user_prize | 中奖记录(用户 × 奖品 × 数量) | | roll_policy | per-roll 参与条件覆盖 |

插件通过 Koishi 事件总线暴露以下生命周期事件(前缀 giveaway/):

| 事件 | 触发时机 | | --- | --- | | giveaway/roll-add | 创建抽奖(参数:session、roll、奖品列表、可选的 per-roll 参与条件) | | giveaway/roll-end | 开奖(参数:抽奖 id) | | giveaway/roll-expired | 抽奖记录到期清理(参数:抽奖 id) | | giveaway/roll-join / giveaway/roll-quit | 用户加入 / 退出抽奖 | | giveaway/roll-key-update | 加入口令缓存需要刷新 | | giveaway/remind-broadcast | 开奖提醒到点播报(参数:抽奖 id) |

多语言

  • 内置三种语言:简体中文(zh-CN)/ English(en-US)/ Deutsch(de-DE),群消息、指令一览、控制台配置说明、图片卡片标签、诊断输出都随语言切换
  • 用户输入同样多语言:创建模板标签、参与条件写法(等级≥40 / Level>=40 / Stufe>=40)、取消词(q / quit / cancel / 取消 / abbrechen)
  • 插件日志保留中文(只面向管理员)

开发

npm install
npm run build          # tsc 生成 lib/*.d.ts + esbuild 打包 lib/index.js
npm test               # 5 套离线用例:创建流程 / 参与条件 / 控制台表单 / 权限 / 三语
npm run test:shots     # 额外跑真实 Chromium 截图验收(需 npm i -D puppeteer-core 并设置 CHROME)
npm run preview list avemujica   # 渲染一张卡片预览到 test/previews/
  • 用例全部离线运行(打桩 database / assets / puppeteer),不需要真的连 QQ;CI 在 Node 20 / 22 上跑 npm ci → build → test
  • 用例覆盖:模板创建与标签解析、取消路径、参与条件四条判定与拒绝理由、权限矩阵、控制台表单结构与默认值、三语 key / 占位符 / 元素标签一致性与「代码引用的文案键都存在」、提醒排期与生命周期
  • test:shots 会逐张渲染 6 种卡片 × 3 套主题并断言「图片宽度 = 卡片宽度、两侧无大片背景」,属于可选的像素级验收

目录结构:

src/
  command/        指令(roll / basic / i18n)
  listener/       事件监听(roll / remind)
  util/           业务工具(joinPolicy、rollPolicy、render、renderTheme、remindPlan…)
  locales/        三语文案
test/             离线用例与预览工具
docs/             功能与交互总览

许可证

MIT © firedrakeovo。派生自 Roll-Bot-Project/roll-bot(MIT),原始版权声明见 LICENSE。