koishi-plugin-noah 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,7 @@ import { SDVXMusic } from '../types';
4
4
  export declare class MusicService {
5
5
  private static instance;
6
6
  private sdvx_data_url;
7
+ private sdvx_search_url;
7
8
  private constructor();
8
9
  /**
9
10
  * 获取 MusicService 实例
@@ -18,4 +19,11 @@ export declare class MusicService {
18
19
  * @returns 音乐信息数组
19
20
  */
20
21
  getMusic(ctx: Context, musicIds: number[]): Promise<SDVXMusic[]>;
22
+ /**
23
+ * 根据曲名查询歌曲
24
+ * @param ctx - Koishi 上下文对象
25
+ * @param query - 查询字符串
26
+ * @returns 音乐信息数组
27
+ */
28
+ searchMusic(ctx: Context, query: string): Promise<SDVXMusic[]>;
21
29
  }
package/lib/index.cjs CHANGED
@@ -4076,6 +4076,73 @@ function getDiffStringFromAbbr(diffAbbr) {
4076
4076
  }
4077
4077
  __name(getDiffStringFromAbbr, "getDiffStringFromAbbr");
4078
4078
 
4079
+ // src/games/sdvx/services/music-service.ts
4080
+ var MusicService = class _MusicService {
4081
+ static {
4082
+ __name(this, "MusicService");
4083
+ }
4084
+ static instance;
4085
+ sdvx_data_url;
4086
+ sdvx_search_url;
4087
+ constructor(config) {
4088
+ this.sdvx_data_url = config.sdvx_data_url;
4089
+ this.sdvx_search_url = config.sdvx_search_url;
4090
+ }
4091
+ /**
4092
+ * 获取 MusicService 实例
4093
+ * @param config - SDVX 配置对象
4094
+ * @returns MusicService 实例
4095
+ */
4096
+ static getInstance(config) {
4097
+ if (!_MusicService.instance) {
4098
+ _MusicService.instance = new _MusicService(config);
4099
+ }
4100
+ return _MusicService.instance;
4101
+ }
4102
+ /**
4103
+ * 获取音乐信息
4104
+ * @param ctx - Koishi 上下文对象
4105
+ * @param musicIds - 音乐 ID 数组
4106
+ * @returns 音乐信息数组
4107
+ */
4108
+ async getMusic(ctx, musicIds) {
4109
+ const response = await ctx.http.post(
4110
+ `/music`,
4111
+ {
4112
+ ids: musicIds
4113
+ },
4114
+ {
4115
+ baseURL: this.sdvx_data_url
4116
+ }
4117
+ );
4118
+ const musicInfo = await response;
4119
+ return musicInfo;
4120
+ }
4121
+ /**
4122
+ * 根据曲名查询歌曲
4123
+ * @param ctx - Koishi 上下文对象
4124
+ * @param query - 查询字符串
4125
+ * @returns 音乐信息数组
4126
+ */
4127
+ async searchMusic(ctx, query) {
4128
+ let musicInfo;
4129
+ try {
4130
+ const response = await ctx.http.get(
4131
+ `/sdvx/get?query=${query}&isnocase=true&isfuzzy=true&isalias=true`,
4132
+ {
4133
+ baseURL: this.sdvx_search_url
4134
+ }
4135
+ );
4136
+ const musicIds = response.map((item) => item.id).filter((n) => Number.isInteger(n));
4137
+ const infoRes = this.getMusic(ctx, musicIds);
4138
+ musicInfo = await infoRes;
4139
+ return musicInfo;
4140
+ } catch {
4141
+ return null;
4142
+ }
4143
+ }
4144
+ };
4145
+
4079
4146
  // src/games/sdvx/commands/chart.ts
4080
4147
  function mapArrangementToken(tok) {
4081
4148
  const t = tok.toLowerCase();
@@ -4100,16 +4167,74 @@ function isBarcode(s) {
4100
4167
  return /^\d+\.[A-Za-z]+$/.test(s);
4101
4168
  }
4102
4169
  __name(isBarcode, "isBarcode");
4170
+ function parseDiffAndTitle(rawTokens) {
4171
+ let diffStr = null;
4172
+ let diffIndex = null;
4173
+ const titleParts = [];
4174
+ const fullMap = {
4175
+ novice: "novice",
4176
+ nov: "novice",
4177
+ advanced: "advanced",
4178
+ adv: "advanced",
4179
+ exhaust: "exhaust",
4180
+ exh: "exhaust",
4181
+ infinite: "infinite",
4182
+ inf: "infinite",
4183
+ gravity: "infinite",
4184
+ grv: "infinite",
4185
+ heavenly: "infinite",
4186
+ hvn: "infinite",
4187
+ vivid: "infinite",
4188
+ vvd: "infinite",
4189
+ exceed: "infinite",
4190
+ xcd: "infinite",
4191
+ maximum: "maximum",
4192
+ mxm: "maximum"
4193
+ };
4194
+ for (const tok of rawTokens) {
4195
+ const trimmed = tok.trim();
4196
+ if (!trimmed) continue;
4197
+ if (diffIndex === null && /^[1-5]$/.test(trimmed)) {
4198
+ diffIndex = Number(trimmed) - 1;
4199
+ continue;
4200
+ }
4201
+ const lettersOnly = trimmed.replace(/[^A-Za-z]/g, "");
4202
+ if (lettersOnly) {
4203
+ const byAbbr = getDiffStringFromAbbr(lettersOnly);
4204
+ if (byAbbr) {
4205
+ diffStr = byAbbr.diffStr;
4206
+ continue;
4207
+ }
4208
+ const lower = lettersOnly.toLowerCase();
4209
+ if (fullMap[lower]) {
4210
+ diffStr = fullMap[lower];
4211
+ continue;
4212
+ }
4213
+ }
4214
+ titleParts.push(trimmed);
4215
+ }
4216
+ return {
4217
+ diffStr,
4218
+ diffIndex,
4219
+ titleQuery: titleParts.join(" ").trim()
4220
+ };
4221
+ }
4222
+ __name(parseDiffAndTitle, "parseDiffAndTitle");
4223
+ function getHighestDifstr(diffs) {
4224
+ return diffs[diffs.length - 1].difstr;
4225
+ }
4226
+ __name(getHighestDifstr, "getHighestDifstr");
4103
4227
  function chart(ctx, config, logger5) {
4104
- ctx.command("sdvx.chart [query:text]").alias("sdvx.c").option("lossless", "-l").action(async ({ session, options }, query) => {
4228
+ ctx.command("sdvx.chart [query:text]").alias("sdvx.c").action(async ({ session }, query) => {
4105
4229
  if (!query) {
4106
4230
  await session.send(session.text(".prompt"));
4107
4231
  query = await session.prompt();
4108
4232
  if (!query) return session.text("commands.timeout");
4109
4233
  }
4234
+ const musicService = MusicService.getInstance(config);
4110
4235
  try {
4111
4236
  let arrangement_mode = "normal";
4112
- let laser_l_color = "GREEN";
4237
+ let laser_l_color = "BLUE";
4113
4238
  let laser_r_color = "RED";
4114
4239
  const tokens = query.split(/\s+/).filter(Boolean);
4115
4240
  const remaining = [];
@@ -4140,7 +4265,7 @@ function chart(ctx, config, logger5) {
4140
4265
  const music_id = Number(midRaw);
4141
4266
  const { diffStr } = getDiffStringFromAbbr(diffAbbrRaw);
4142
4267
  const difstr = diffStr;
4143
- const output_format = options?.lossless ? "PNG" : "JPEG";
4268
+ const output_format = "PNG";
4144
4269
  const payload = {
4145
4270
  music_id,
4146
4271
  difstr,
@@ -4158,7 +4283,55 @@ function chart(ctx, config, logger5) {
4158
4283
  });
4159
4284
  return import_koishi10.h.image(res, "image/png");
4160
4285
  } else {
4161
- return session.text(".error");
4286
+ const {
4287
+ diffStr: parsedDiff,
4288
+ diffIndex,
4289
+ titleQuery
4290
+ } = parseDiffAndTitle(remaining);
4291
+ if (!titleQuery) return session.text(".no-result");
4292
+ const musicInfo = await musicService.searchMusic(
4293
+ ctx,
4294
+ titleQuery
4295
+ );
4296
+ if (!musicInfo || musicInfo.length === 0) return session.text(".no-result");
4297
+ const picked = musicInfo[0];
4298
+ const music_id = Number(picked?.id);
4299
+ if (!Number.isFinite(music_id)) {
4300
+ logger5.warn("search result missing id", picked);
4301
+ return session.text(".error");
4302
+ }
4303
+ let difstr = null;
4304
+ if (parsedDiff) {
4305
+ difstr = parsedDiff;
4306
+ } else if (diffIndex !== null && Array.isArray(picked?.difficulty) && diffIndex >= 0 && diffIndex < picked.difficulty.length) {
4307
+ const d = picked.difficulty[diffIndex];
4308
+ difstr = d?.difstr ?? null;
4309
+ }
4310
+ if (!difstr) {
4311
+ difstr = getHighestDifstr(picked?.difficulty);
4312
+ }
4313
+ const output_format = "PNG";
4314
+ const payload = {
4315
+ music_id,
4316
+ difstr,
4317
+ arrangement_mode,
4318
+ rng_seed: null,
4319
+ output_format,
4320
+ laser_l_color,
4321
+ laser_r_color,
4322
+ px_per_second: 600,
4323
+ column_height: 2800
4324
+ };
4325
+ session.send(
4326
+ session.text(".drawing", {
4327
+ name: picked.title_name,
4328
+ difstr
4329
+ })
4330
+ );
4331
+ const res = await ctx.http.post(`${config.sdvx_data_url}/chart`, payload, {
4332
+ headers: { "Content-Type": "application/json" }
4333
+ });
4334
+ return import_koishi10.h.image(res, "image/png");
4162
4335
  }
4163
4336
  } catch (err) {
4164
4337
  logger5.warn(err);
@@ -4202,48 +4375,6 @@ var IIDXService = class _IIDXService {
4202
4375
  }
4203
4376
  };
4204
4377
 
4205
- // src/games/sdvx/services/music-service.ts
4206
- var MusicService = class _MusicService {
4207
- static {
4208
- __name(this, "MusicService");
4209
- }
4210
- static instance;
4211
- sdvx_data_url;
4212
- constructor(config) {
4213
- this.sdvx_data_url = config.sdvx_data_url;
4214
- }
4215
- /**
4216
- * 获取 MusicService 实例
4217
- * @param config - SDVX 配置对象
4218
- * @returns MusicService 实例
4219
- */
4220
- static getInstance(config) {
4221
- if (!_MusicService.instance) {
4222
- _MusicService.instance = new _MusicService(config);
4223
- }
4224
- return _MusicService.instance;
4225
- }
4226
- /**
4227
- * 获取音乐信息
4228
- * @param ctx - Koishi 上下文对象
4229
- * @param musicIds - 音乐 ID 数组
4230
- * @returns 音乐信息数组
4231
- */
4232
- async getMusic(ctx, musicIds) {
4233
- const response = await ctx.http.post(
4234
- `/music`,
4235
- {
4236
- ids: musicIds
4237
- },
4238
- {
4239
- baseURL: this.sdvx_data_url
4240
- }
4241
- );
4242
- const musicInfo = await response;
4243
- return musicInfo;
4244
- }
4245
- };
4246
-
4247
4378
  // src/servers/utils/grade.ts
4248
4379
  function getSDVXGrade(score) {
4249
4380
  if (score >= 99e5) return "S";
@@ -5197,10 +5328,10 @@ function apply12(ctx) {
5197
5328
  __name(apply12, "apply");
5198
5329
 
5199
5330
  // src/games/sdvx/locales/en-US.yml
5200
- var en_US_default4 = { _config: { $desc: "SDVX Module Settings", default_model: "<p>Default model value (e.g. `2024110700`)</p>", sdvx_data_url: "<p>The URL of the SDVX data service</p>" }, commands: { vf: { description: "Show Noah help information", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>" } }, sdvx: { recent: { description: "Show recent scores", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>" } }, chart: { description: "Show SDVX chart", messages: { prompt: "<p>Which song's chart would you like to view?</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>" } }, calculate: { description: "Calculate volforce value or score", messages: { "invalid-query": "<p>Invalid query parameters, please check your input~</p>", "no-results": "<p>No results found~</p>", "too-many-results": "<p>Too many results! Found {0} results, please narrow down your query (current limit: 500 results)</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", error: "<p>An error occurred(っ °Д °;)っ</p>" } } } } };
5331
+ var en_US_default4 = { _config: { $desc: "SDVX Module Settings", default_model: "<p>Default model value (e.g. `2024110700`)</p>", sdvx_data_url: "<p>The URL of the SDVX data service</p>", sdvx_search_url: "<p>The URL of the SDVX search service</p>" }, commands: { vf: { description: "Show Noah help information", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing {name} [{difstr}], please wait patiently~</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>" } }, sdvx: { recent: { description: "Show recent scores", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>" } }, chart: { description: "Show SDVX chart", messages: { prompt: "<p>Which song's chart would you like to view?</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", "no-result": "<p>Aww, Noah couldn’t find that song~ try another keyword, okay?</p>" } }, calculate: { description: "Calculate volforce value or score", messages: { "invalid-query": "<p>Invalid query parameters, please check your input~</p>", "no-results": "<p>No results found~</p>", "too-many-results": "<p>Too many results! Found {0} results, please narrow down your query (current limit: 500 results)</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", error: "<p>An error occurred(っ °Д °;)っ</p>" } } } } };
5201
5332
 
5202
5333
  // src/games/sdvx/locales/zh-CN.yml
5203
- var zh_CN_default4 = { _config: { $desc: "SDVX 模块设置", default_model: "<p>默认的 model 值(如 `2024110700`)</p>", sdvx_data_url: "<p>SDVX 数据服务的 URL</p>" }, commands: { vf: { description: "查询 SDVX VOLFORCE", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>" } }, sdvx: { recent: { description: "查询最近分数", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>" } }, chart: { description: "查询 SDVX 谱面", messages: { prompt: "<p>要查哪首歌的铺面呢?</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>" } }, calculate: { description: "计算 volforce 值或分数", messages: { "invalid-query": "<p>查询参数无效,请检查你的输入~</p>", "no-results": "<p>没有找到符合条件的结果~</p>", "too-many-results": "<p>结果太多啦!共找到 {0} 条结果,请缩小查询范围(当前限制:500 条)</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>" } } } } };
5334
+ var zh_CN_default4 = { _config: { $desc: "SDVX 模块设置", default_model: "<p>默认的 model 值(如 `2024110700`)</p>", sdvx_data_url: "<p>SDVX 数据服务的 URL</p>", sdvx_search_url: "<p>SDVX 搜索服务的 URL</p>" }, commands: { vf: { description: "查询 SDVX VOLFORCE", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>" } }, sdvx: { recent: { description: "查询最近分数", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>" } }, chart: { description: "查询 SDVX 谱面", messages: { prompt: "<p>要查哪首歌的铺面呢?</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在绘制 {name} [{difstr}],请耐心等待~</p>", "no-result": "<p>Noah 没有找到这首歌,换个关键词试试吧~</p>" } }, calculate: { description: "计算 volforce 值或分数", messages: { "invalid-query": "<p>查询参数无效,请检查你的输入~</p>", "no-results": "<p>没有找到符合条件的结果~</p>", "too-many-results": "<p>结果太多啦!共找到 {0} 条结果,请缩小查询范围(当前限制:500 条)</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>" } } } } };
5204
5335
 
5205
5336
  // src/games/sdvx/index.ts
5206
5337
  var name13 = "Noah-SDVX";
@@ -5289,7 +5420,8 @@ var generalConfig = import_koishi19.Schema.object({
5289
5420
  var import_koishi20 = require("koishi");
5290
5421
  var sdvxConfig = import_koishi20.Schema.object({
5291
5422
  default_model: import_koishi20.Schema.string().default("2024110700"),
5292
- sdvx_data_url: import_koishi20.Schema.string().required()
5423
+ sdvx_data_url: import_koishi20.Schema.string().required(),
5424
+ sdvx_search_url: import_koishi20.Schema.string().required()
5293
5425
  }).i18n({
5294
5426
  "en-US": en_US_default4._config,
5295
5427
  "zh-CN": zh_CN_default4._config
@@ -26,6 +26,8 @@ export interface SDVXConfig extends BaseConfig {
26
26
  default_model: string;
27
27
  /** SDVX 数据 URL */
28
28
  sdvx_data_url: string;
29
+ /** SDVX 搜索 URL */
30
+ sdvx_search_url: string;
29
31
  }
30
32
  /**
31
33
  * 戳一戳功能配置接口
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-noah",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "contributors": [
5
5
  "Logthm <logthm@outlook.com>"
6
6
  ],