漫展查询助手

对接 B 站会员购数据,在聊天框中查询全国漫展,支持地区订阅管理。
作者: 蜥蜴


背景

二次元爱好者追漫展是每个季度的重要活动。以往查询漫展信息,通常需要经历以下步骤:

  1. 打开 B 站,进入会员购页面
  2. 手动输入城市名搜索
  3. 在搜索结果中逐个翻看活动详情
  4. 截图并转发至群聊分享

该流程操作繁琐,若同时关注多个城市,每次查询都需重复执行上述步骤。

在搭建 Koishi 机器人之后,便产生了将漫展查询集成至群聊机器人的想法,anime-convention-lizard 由此而来。


工具定位

anime-convention-lizard 是一款基于 Koishi 框架的漫展查询与订阅插件,主要能力如下:

能力 说明
聊天框内查询 无需打开网页,在群聊或私聊中直接使用指令
地区订阅 订阅常去城市,一条指令查看所有订阅地区的漫展
三级行政区识别 省、市、区/县三级行政单位均可识别
详情图文推送 选中序号后返回活动封面图与文字详情
多频道隔离 群聊与私聊的订阅数据相互独立

当前版本为 3.1.0,依赖 Koishi ^4.18.11。


安装

前置条件

  • 已搭建并可正常运行的 Koishi 项目(koishi-app)
  • 已启用 Koishi 的数据库服务(插件声明 inject: ['database'],订阅功能依赖数据库)

方式一:通过插件市场安装(推荐)

  1. 启动 Koishi 项目,打开控制台(默认地址 http://localhost:5140)。
  2. 进入左侧「插件市场」。
  3. 在搜索框中输入 anime-convention-lizard。
  4. 找到插件后点击「添加」,Koishi 会自动完成依赖安装与配置写入。

方式二:通过 npm 安装

在 Koishi 项目根目录执行:

1
npm install koishi-plugin-anime-convention-lizard

随后在 koishi.yml 中手动添加配置:

1
2
3
plugins:
anime-convention-lizard:
timeout: 15000

方式三:通过 yarn / pnpm 安装

若项目使用 yarn 或 pnpm,可执行:

1
2
3
4
5
# yarn
yarn add koishi-plugin-anime-convention-lizard

# pnpm
pnpm add koishi-plugin-anime-convention-lizard

启用数据库

插件订阅功能依赖数据库。若项目尚未配置,可在控制台「插件配置」中找到 database-sqlite(或 database-mysql)并启用:

1
2
3
plugins:
database-sqlite:
path: data/koishi.db

保存配置后重启 Koishi 项目,即可正常使用订阅功能。

验证安装

在任意已接入机器人的聊天窗口输入:

1
漫展 查询 北京

若能返回漫展列表,则说明安装成功。


配置

配置项

参数 类型 默认值 取值范围 说明
timeout number 15000 ≤ 60000 序号选择会话的超时时长(毫秒)

配置示例

1
2
3
plugins:
anime-convention-lizard:
timeout: 15000

timeout 控制用户查询后选择序号的等待时长。超时后缓存自动清除,并提示需重新查询。默认 15 秒足以浏览列表并做出选择。


使用流程

所有指令均绑定在父指令 漫展 之下。

完整指令列表

指令 说明 示例
漫展 查询 <地区> 查询指定地区的漫展 漫展 查询 北京
漫展 一键查询 查询所有订阅地区的漫展 漫展 一键查询
漫展 订阅 <地区> 订阅某地区 漫展 订阅 朝阳区
漫展 取消订阅 [地区] 取消订阅(不填则取消全部) 漫展 取消订阅 北京
漫展 订阅列表 查看当前订阅列表 漫展 订阅列表

流程一:查询单个地区的漫展

步骤 1:发送查询指令

在聊天窗口输入地区名称:

1
漫展 查询 北京

支持省、市、区/县三级输入:

1
2
3
漫展 查询 朝阳区
漫展 查询 南京
漫展 查询 广东省

步骤 2:从列表中确认目标活动

插件会返回该地区正在展出的漫展列表,并附带序号:

1
2
3
4
5
找到以下漫展:
1. 北京动漫嘉年华
2. 2025北京国际动漫展
3. 北京二次元文化节
请输入序号查看详情,输入"0"取消。

步骤 3:输入序号查看详情

输入对应序号(如 1),机器人将返回:

  • 活动封面图
  • 活动名称
  • 销售状态
  • 活动地址(区 + 场馆)
  • 活动时间(起止时间)
  • 想去人数
  • 售票链接
  • 活动链接
  • 宣传卖点
  • 活动标签

步骤 4:取消或超时

  • 输入 0:主动取消,清除缓存
  • 超过 timeout 未操作:缓存自动清除,并提示需重新查询

流程二:订阅地区并一键查询

适用于同时关注多个城市的用户。

步骤 1:订阅目标地区

依次发送订阅指令:

1
2
3
漫展 订阅 北京
漫展 订阅 上海
漫展 订阅 广州

每次订阅成功后会收到确认提示,例如「已订阅「北京」的漫展」。

步骤 2:查看订阅列表

1
漫展 订阅列表

返回结果:

1
2
3
4
你订阅的地区:
- 北京市
- 上海市
- 广州市

步骤 3:一键查询

1
漫展 一键查询

插件将并发查询所有订阅地区,合并结果后统一以带序号的列表返回。后续操作与流程一相同(输入序号查看详情)。


流程三:管理订阅

取消单个地区的订阅

1
漫展 取消订阅 北京

取消全部订阅

1
漫展 取消订阅

机器人将询问:

1
确定取消所有订阅?(是/否)

回复「是」即可完成取消,回复其他内容则取消本次操作。


使用场景

场景一:群聊内查询

社团成员在群聊中讨论周末活动时,可直接在群内发起查询并分享详情,无需切换至 B 站页面。

场景二:多城市订阅追踪

同时关注北京、上海、广州三地漫展,可先完成订阅,之后每日通过一条指令查看全部地区的漫展动态。

场景三:私聊使用

若不便在群聊中操作,可在私聊中使用相同指令。私聊与群聊的订阅数据相互隔离,互不影响。


技术实现

技术栈

技术 用途
Koishi 机器人框架
B 站会员购 API 漫展数据来源
TypeScript 开发语言

数据抓取

插件请求 B 站会员购的展览列表接口:

1
2
https://show.bilibili.com/api/ticket/project/listV2
?version=134&page=1&pagesize=20&area=<地区编码>&p_type=展览

接口返回的 data.result 即该地区的漫展条目,包含活动名称、时间、地址、封面、标签、嘉宾等信息。

核心设计

地区编码系统

src/area.ts 内置了全国 3000+ 个行政区划的名称与编码对照表,覆盖省、市、区/县四级。resolveAreaCode 函数通过后缀试探进行匹配:

1
2
3
4
5
const suffixes = ['', '省', '市', '区', '县']
for (const suffix of suffixes) {
const key = text + suffix
if (map[key]) return map[key]
}

输入「北京」时,依次尝试匹配「北京」「北京省」「北京市」「北京区」「北京县」,命中「北京市」即返回编码 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 等服务

开发计划

  • 支持演出和本地生活类别
  • 自定义查询条件(时间、类型等)
  • 漫展开始前自动提醒
  • 地区名称模糊匹配

获取工具