漫展查询助手
对接 B 站会员购数据,在聊天框中查询全国漫展,支持地区订阅管理。
作者: 蜥蜴
背景
二次元爱好者追漫展是每个季度的重要活动。以往查询漫展信息,通常需要经历以下步骤:
- 打开 B 站,进入会员购页面
- 手动输入城市名搜索
- 在搜索结果中逐个翻看活动详情
- 截图并转发至群聊分享
该流程操作繁琐,若同时关注多个城市,每次查询都需重复执行上述步骤。
在搭建 Koishi 机器人之后,便产生了将漫展查询集成至群聊机器人的想法,anime-convention-lizard 由此而来。
工具定位
anime-convention-lizard 是一款基于 Koishi 框架的漫展查询与订阅插件,主要能力如下:
| 能力 | 说明 |
|---|---|
| 聊天框内查询 | 无需打开网页,在群聊或私聊中直接使用指令 |
| 地区订阅 | 订阅常去城市,一条指令查看所有订阅地区的漫展 |
| 三级行政区识别 | 省、市、区/县三级行政单位均可识别 |
| 详情图文推送 | 选中序号后返回活动封面图与文字详情 |
| 多频道隔离 | 群聊与私聊的订阅数据相互独立 |
当前版本为 3.1.0,依赖 Koishi ^4.18.11。
安装
前置条件
- 已搭建并可正常运行的 Koishi 项目(
koishi-app) - 已启用 Koishi 的数据库服务(插件声明
inject: ['database'],订阅功能依赖数据库)
方式一:通过插件市场安装(推荐)
- 启动 Koishi 项目,打开控制台(默认地址
http://localhost:5140)。 - 进入左侧「插件市场」。
- 在搜索框中输入
anime-convention-lizard。 - 找到插件后点击「添加」,Koishi 会自动完成依赖安装与配置写入。
方式二:通过 npm 安装
在 Koishi 项目根目录执行:
1 | npm install koishi-plugin-anime-convention-lizard |
随后在 koishi.yml 中手动添加配置:
1 | plugins: |
方式三:通过 yarn / pnpm 安装
若项目使用 yarn 或 pnpm,可执行:
1 | # yarn |
启用数据库
插件订阅功能依赖数据库。若项目尚未配置,可在控制台「插件配置」中找到 database-sqlite(或 database-mysql)并启用:
1 | plugins: |
保存配置后重启 Koishi 项目,即可正常使用订阅功能。
验证安装
在任意已接入机器人的聊天窗口输入:
1 | 漫展 查询 北京 |
若能返回漫展列表,则说明安装成功。
配置
配置项
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|
timeout |
number | 15000 | ≤ 60000 | 序号选择会话的超时时长(毫秒) |
配置示例
1 | plugins: |
timeout 控制用户查询后选择序号的等待时长。超时后缓存自动清除,并提示需重新查询。默认 15 秒足以浏览列表并做出选择。
使用流程
所有指令均绑定在父指令 漫展 之下。
完整指令列表
| 指令 | 说明 | 示例 |
|---|---|---|
漫展 查询 <地区> |
查询指定地区的漫展 | 漫展 查询 北京 |
漫展 一键查询 |
查询所有订阅地区的漫展 | 漫展 一键查询 |
漫展 订阅 <地区> |
订阅某地区 | 漫展 订阅 朝阳区 |
漫展 取消订阅 [地区] |
取消订阅(不填则取消全部) | 漫展 取消订阅 北京 |
漫展 订阅列表 |
查看当前订阅列表 | 漫展 订阅列表 |
流程一:查询单个地区的漫展
步骤 1:发送查询指令
在聊天窗口输入地区名称:
1 | 漫展 查询 北京 |
支持省、市、区/县三级输入:
1 | 漫展 查询 朝阳区 |
步骤 2:从列表中确认目标活动
插件会返回该地区正在展出的漫展列表,并附带序号:
1 | 找到以下漫展: |
步骤 3:输入序号查看详情
输入对应序号(如 1),机器人将返回:
- 活动封面图
- 活动名称
- 销售状态
- 活动地址(区 + 场馆)
- 活动时间(起止时间)
- 想去人数
- 售票链接
- 活动链接
- 宣传卖点
- 活动标签
步骤 4:取消或超时
- 输入
0:主动取消,清除缓存 - 超过
timeout未操作:缓存自动清除,并提示需重新查询
流程二:订阅地区并一键查询
适用于同时关注多个城市的用户。
步骤 1:订阅目标地区
依次发送订阅指令:
1 | 漫展 订阅 北京 |
每次订阅成功后会收到确认提示,例如「已订阅「北京」的漫展」。
步骤 2:查看订阅列表
1 | 漫展 订阅列表 |
返回结果:
1 | 你订阅的地区: |
步骤 3:一键查询
1 | 漫展 一键查询 |
插件将并发查询所有订阅地区,合并结果后统一以带序号的列表返回。后续操作与流程一相同(输入序号查看详情)。
流程三:管理订阅
取消单个地区的订阅
1 | 漫展 取消订阅 北京 |
取消全部订阅
1 | 漫展 取消订阅 |
机器人将询问:
1 | 确定取消所有订阅?(是/否) |
回复「是」即可完成取消,回复其他内容则取消本次操作。
使用场景
场景一:群聊内查询
社团成员在群聊中讨论周末活动时,可直接在群内发起查询并分享详情,无需切换至 B 站页面。
场景二:多城市订阅追踪
同时关注北京、上海、广州三地漫展,可先完成订阅,之后每日通过一条指令查看全部地区的漫展动态。
场景三:私聊使用
若不便在群聊中操作,可在私聊中使用相同指令。私聊与群聊的订阅数据相互隔离,互不影响。
技术实现
技术栈
| 技术 | 用途 |
|---|---|
| Koishi | 机器人框架 |
| B 站会员购 API | 漫展数据来源 |
| TypeScript | 开发语言 |
数据抓取
插件请求 B 站会员购的展览列表接口:
1 | https://show.bilibili.com/api/ticket/project/listV2 |
接口返回的 data.result 即该地区的漫展条目,包含活动名称、时间、地址、封面、标签、嘉宾等信息。
核心设计
地区编码系统
src/area.ts 内置了全国 3000+ 个行政区划的名称与编码对照表,覆盖省、市、区/县四级。resolveAreaCode 函数通过后缀试探进行匹配:
1 | const suffixes = ['', '省', '市', '区', '县'] |
输入「北京」时,依次尝试匹配「北京」「北京省」「北京市」「北京区」「北京县」,命中「北京市」即返回编码 110000。因此需要保证输入与标准行政区划名称一致。
会话缓存
用户查询后,结果缓存在内存中,并设置一个 timeout 毫秒的定时器。用户在超时前输入序号即可查看详情;超时后缓存清除并提示需重新查询。选择序号或输入 0 取消后,缓存立即清除。
多频道隔离
订阅数据按 userId + channelId 组合存储,不同群组之间互不影响。私聊场景下使用 private:${userId} 作为频道标识:
1 | const getChannelId = (s: Session) => s.guildId ? s.channelId : `private:${s.userId}`; |
图文详情推送
选中序号后,插件下载活动封面图并以 base64 形式发送,同时附带格式化的文字详情;若图片下载失败,则降级为纯文字推送。
订阅存储
订阅记录通过 ctx.database 持久化至 anime_convention 表,主键为 userId + channelId + area。使用 upsert 写入,重复订阅同一地区不会产生冗余记录。
注意事项
1. API 限制
B 站会员购 API 并非官方开放接口,可能出现:
- 请求频率过高时被限流
- 接口变动导致数据获取失败
建议不要过于频繁地查询同一地区。
2. 地区匹配
插件采用精确匹配 + 后缀试探,而非模糊匹配。需要注意:
- 输入名称必须与标准行政区划名称一致
- 部分地区名与标准名存在差异(例如输入「萧山」不会匹配「萧山区」)
若提示「未识别的地区」,可尝试加上「省」「市」「区」「县」后缀重新输入。
3. 缓存超时
查询结果缓存的有效期由 timeout 配置决定(默认 15 秒)。若超时前未选择序号,需重新查询。
4. 订阅数量
插件未限制订阅数量,但订阅过多地区会导致「一键查询」时并发请求增多、响应变慢。建议按需订阅,控制在 10 个以内。
5. 数据库依赖
插件声明了 inject: ['database'],订阅功能依赖 Koishi 的数据库服务。若未启用数据库,订阅相关指令将不可用。
常见问题
Q1:查询时提示「未识别的地区」如何解决?
插件采用精确匹配,需与标准行政区划名称一致,尝试加上「省」「市」「区」「县」后缀,例如输入「朝阳区」而非「朝阳」。若仍失败,可能是该地名未收录于标准行政区划中。
Q2:为什么查询不到漫展?
可能的原因包括:
- 该地区没有正在展出的漫展
- B 站 API 暂时限流
- 漫展数据尚未同步至会员购平台
此外,插件仅查询 p_type=展览 类别,不含演出与本地生活。
Q3:是否支持查询演出或本地生活类活动?
目前仅支持「展览」类别。API 本身也支持演出与本地生活数据,后续可能会扩展支持。
Q4:订阅数据会丢失吗?
订阅记录存储于数据库中,机器人重启不会丢失。需确保 Koishi 已启用数据库服务。
Q5:序号选择有超时限制吗?
有。默认 timeout 为 15 秒,可在配置中调整,最大不超过 60 秒。超时后缓存清除,需重新查询。
Q6:安装后输入指令无响应?
依次检查以下项:
- 插件是否已在控制台启用
- 机器人是否已成功连接至目标平台
- 指令是否完整输入(父指令
漫展与子指令之间以空格分隔) - 数据库中是否已启用
database-sqlite等服务
开发计划
- 支持演出和本地生活类别
- 自定义查询条件(时间、类型等)
- 漫展开始前自动提醒
- 地区名称模糊匹配
获取工具
- npm 包:
koishi-plugin-anime-convention-lizard - GitHub 仓库:lizard0126/anime-convention-lizard
- 反馈建议:GitHub Issues
- 支持作者:请我喝可乐