koishi-plugin-delta-force 1.0.0-alpha.0 → 1.0.0-beta.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.
package/lib/api.d.ts CHANGED
@@ -28,5 +28,9 @@ export declare class ApiService {
28
28
  getMaps(): Promise<ApiResponse>;
29
29
  getOperators(): Promise<ApiResponse>;
30
30
  getDailyKeyword(): Promise<ApiResponse>;
31
+ getRankScore(): Promise<ApiResponse>;
32
+ getAudioTags(): Promise<ApiResponse>;
33
+ getAudioCharacters(): Promise<ApiResponse>;
34
+ getAudioCategories(): Promise<ApiResponse>;
31
35
  }
32
36
  //# sourceMappingURL=api.d.ts.map
package/lib/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE/G,qBAAa,UAAU;IAEnB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;gBADN,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM;YAGV,OAAO;IAqCf,UAAU,CAAC,QAAQ,GAAE,MAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAK3D,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAK9E,QAAQ,CAAC,IAAI,EAAE;QACnB,UAAU,EAAE,MAAM,CAAA;QAClB,cAAc,EAAE,MAAM,CAAA;QACtB,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;KACnB,GAAG,OAAO,CAAC,WAAW,CAAC;IAKlB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;IASvF,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAQrE,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QACjE,QAAQ,EAAE,OAAO,CAAA;QACjB,UAAU,EAAE,UAAU,CAAA;KACvB,CAAC,GAAG;QACH,QAAQ,EAAE,QAAQ,CAAA;KACnB,CAAC;IAUI,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAS3E,eAAe,CACnB,cAAc,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE,MAAM,EACb,gBAAgB,CAAC,EAAE,OAAO,EAC1B,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,CAAC;IAejB,aAAa,CACjB,cAAc,EAAE,MAAM,EACtB,IAAI,GAAE,MAAc,EACpB,IAAI,GAAE,MAAU,GACf,OAAO,CAAC,WAAW,CAAC;IASjB,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;IAK/B,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAKpC,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC;CAG9C"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE/G,qBAAa,UAAU;IAEnB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;gBADN,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM;YAGV,OAAO;IAqEf,UAAU,CAAC,QAAQ,GAAE,MAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAK3D,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAK9E,QAAQ,CAAC,IAAI,EAAE;QACnB,UAAU,EAAE,MAAM,CAAA;QAClB,cAAc,EAAE,MAAM,CAAA;QACtB,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;KACnB,GAAG,OAAO,CAAC,WAAW,CAAC;IAKlB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;IASvF,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAQrE,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QACjE,QAAQ,EAAE,OAAO,CAAA;QACjB,UAAU,EAAE,UAAU,CAAA;KACvB,CAAC,GAAG;QACH,QAAQ,EAAE,QAAQ,CAAA;KACnB,CAAC;IAUI,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAS3E,eAAe,CACnB,cAAc,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE,MAAM,EACb,gBAAgB,CAAC,EAAE,OAAO,EAC1B,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,CAAC;IAejB,aAAa,CACjB,cAAc,EAAE,MAAM,EACtB,IAAI,GAAE,MAAc,EACpB,IAAI,GAAE,MAAU,GACf,OAAO,CAAC,WAAW,CAAC;IAgBjB,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;IAK/B,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAKpC,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC;IAKvC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAKpC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAKpC,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC;IAK1C,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC;CAGjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAGnC,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,QA0OhB"}
1
+ {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAW,MAAM,QAAQ,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAGnC,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,QAkOhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAK,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAInC,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,QAwPhB"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAK,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAInC,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,QAoRhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/commands/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAIrC,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,WAAW,QAyCzB"}
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/commands/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAIrC,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,WAAW,QA2DzB"}
package/lib/data.d.ts CHANGED
@@ -3,9 +3,65 @@ import { ApiService } from './api';
3
3
  export declare class DataManager {
4
4
  private ctx;
5
5
  private api;
6
+ private cacheManager;
6
7
  constructor(ctx: Context, api: ApiService);
7
8
  init(): Promise<void>;
9
+ /**
10
+ * 从数据库加载本地缓存
11
+ */
12
+ private loadLocalCache;
13
+ /**
14
+ * 保存数据到数据库缓存
15
+ */
16
+ private saveToDatabase;
17
+ private fetchAndCacheMaps;
18
+ private fetchAndCacheOperators;
19
+ private fetchAndCacheRankScore;
20
+ private fetchAndCacheAudioData;
8
21
  getMapName(id: string | number): string;
9
22
  getOperatorName(id: string | number): string;
23
+ /**
24
+ * 根据分数获取对应的段位名称
25
+ * @param score 分数
26
+ * @param mode 模式 ('sol' 或 'tdm')
27
+ * @returns 段位名称
28
+ */
29
+ getRankByScore(score: string | number, mode?: 'sol' | 'tdm'): string;
30
+ /**
31
+ * 根据中文名或tag获取音频标签
32
+ * @param keyword 关键词(中文名或tag)
33
+ * @returns tag值
34
+ */
35
+ getAudioTag(keyword: string): string | null;
36
+ /**
37
+ * 判断字符串是否是tag格式
38
+ * @param str 字符串
39
+ * @returns 是否是tag格式
40
+ */
41
+ isTagFormat(str: string): boolean;
42
+ /**
43
+ * 根据中文名或voiceId获取角色ID
44
+ * @param keyword 关键词(中文名或voiceId)
45
+ * @returns voiceId值
46
+ */
47
+ getAudioCharacter(keyword: string): string | null;
48
+ /**
49
+ * 根据中文名或英文名获取音频分类
50
+ * @param keyword 关键词(中文名或英文名)
51
+ * @returns category值
52
+ */
53
+ getAudioCategory(keyword: string): string | null;
54
+ /**
55
+ * 检查是否是有效的音频标签
56
+ * @param keyword 关键词
57
+ * @returns 是否是有效标签
58
+ */
59
+ isValidAudioTag(keyword: string): boolean;
60
+ /**
61
+ * 检查是否是有效的角色名
62
+ * @param keyword 关键词
63
+ * @returns 是否是有效角色
64
+ */
65
+ isValidAudioCharacter(keyword: string): boolean;
10
66
  }
11
67
  //# sourceMappingURL=data.d.ts.map
package/lib/data.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAgBlC,qBAAa,WAAW;IAEpB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,GAAG;gBADH,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,UAAU;IAGnB,IAAI;IAsBV,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAKvC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;CAI7C"}
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AA6ClC,qBAAa,WAAW;IAIpB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,GAAG;IAJb,OAAO,CAAC,YAAY,CAAoB;gBAG9B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,UAAU;IAKnB,IAAI;IAgCV;;OAEG;YACW,cAAc;IA8C5B;;OAEG;YACW,cAAc;YAQd,iBAAiB;YAoBjB,sBAAsB;YAoBtB,sBAAsB;YA+BtB,sBAAsB;IAoIpC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAKvC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAK5C;;;;;OAKG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,GAAE,KAAK,GAAG,KAAa,GAAG,MAAM;IA2C3E;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAe3C;;;;OAIG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAYjC;;;;OAIG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKjD;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKhD;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;OAIG;IACH,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;CAGhD"}
package/lib/database.d.ts CHANGED
@@ -1,6 +1,48 @@
1
1
  import { Context } from 'koishi';
2
2
  import { DeltaForceToken } from './types';
3
+ interface StaticCache {
4
+ id: number;
5
+ key: string;
6
+ value: Record<string, unknown>;
7
+ updated_at: Date;
8
+ }
9
+ declare module 'koishi' {
10
+ interface Tables {
11
+ delta_force_static_cache: StaticCache;
12
+ }
13
+ }
3
14
  export declare function extendDatabase(ctx: Context): void;
15
+ export declare class StaticCacheManager {
16
+ private ctx;
17
+ constructor(ctx: Context);
18
+ /**
19
+ * 设置缓存
20
+ * @param key 缓存键
21
+ * @param value 缓存值
22
+ */
23
+ set(key: string, value: Record<string, unknown>): Promise<void>;
24
+ /**
25
+ * 获取缓存
26
+ * @param key 缓存键
27
+ * @returns 缓存值或null
28
+ */
29
+ get(key: string): Promise<Record<string, unknown> | null>;
30
+ /**
31
+ * 检查缓存是否存在
32
+ * @param key 缓存键
33
+ * @returns 是否存在
34
+ */
35
+ has(key: string): Promise<boolean>;
36
+ /**
37
+ * 删除缓存
38
+ * @param key 缓存键
39
+ */
40
+ delete(key: string): Promise<void>;
41
+ /**
42
+ * 清空所有缓存
43
+ */
44
+ clear(): Promise<void>;
45
+ }
4
46
  export declare function getTokenGroup(tokenType: string): string;
5
47
  export declare function getGroupActiveToken(ctx: Context, userId: string, platform: string, group: string): Promise<string | null>;
6
48
  export declare function setGroupActiveToken(ctx: Context, userId: string, platform: string, group: string, token: string | null): Promise<void>;
@@ -9,4 +51,5 @@ export declare function setActiveToken(ctx: Context, userId: string, platform: s
9
51
  export declare function saveToken(ctx: Context, userId: string, platform: string, frameworkToken: string, tokenType: string): Promise<void>;
10
52
  export declare function getUserTokens(ctx: Context, userId: string, platform: string): Promise<DeltaForceToken[]>;
11
53
  export declare function deleteUserToken(ctx: Context, userId: string, platform: string, frameworkToken: string): Promise<void>;
54
+ export {};
12
55
  //# sourceMappingURL=database.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,QA+B1C;AAGD,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAYvD;AAGD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYxB;AAGD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAGD,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAY3G;AAGD,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,IAAI,CAAC,CAEf;AAGD,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAGD,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAE9G;AAGD,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAMf"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAGzC,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,UAAU,EAAE,IAAI,CAAA;CACjB;AAED,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,MAAM;QACd,wBAAwB,EAAE,WAAW,CAAA;KACtC;CACF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,QAyC1C;AAGD,qBAAa,kBAAkB;IACjB,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,OAAO;IAEhC;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrE;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAK/D;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAGD,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAYvD;AAGD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYxB;AAGD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAGD,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAY3G;AAGD,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,IAAI,CAAC,CAEf;AAGD,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAGD,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAE9G;AAGD,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAYjC,eAAO,MAAM,IAAI,gBAAgB,CAAA;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,eAAO,MAAM,MAAM;;;CAGlB,CAAA;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAoDjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAYjC,eAAO,MAAM,IAAI,gBAAgB,CAAA;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,eAAO,MAAM,MAAM;;;CAGlB,CAAA;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAsDjD"}
package/lib/index.js CHANGED
@@ -23,6 +23,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
23
23
  // src/database.ts
24
24
  var database_exports = {};
25
25
  __export(database_exports, {
26
+ StaticCacheManager: () => StaticCacheManager,
26
27
  deleteUserToken: () => deleteUserToken,
27
28
  extendDatabase: () => extendDatabase,
28
29
  getActiveToken: () => getActiveToken,
@@ -65,6 +66,14 @@ function extendDatabase(ctx) {
65
66
  primary: "id",
66
67
  autoInc: true
67
68
  });
69
+ ctx.model.extend("delta_force_static_cache", {
70
+ id: "unsigned",
71
+ key: { type: "string", length: 255, initial: "" },
72
+ value: "json",
73
+ updated_at: "timestamp"
74
+ }, {
75
+ unique: ["key"]
76
+ });
68
77
  }
69
78
  function getTokenGroup(tokenType) {
70
79
  const type = tokenType.toLowerCase();
@@ -160,9 +169,61 @@ async function deleteUserToken(ctx, userId, platform, frameworkToken) {
160
169
  frameworkToken
161
170
  });
162
171
  }
172
+ var StaticCacheManager;
163
173
  var init_database = __esm({
164
174
  "src/database.ts"() {
165
175
  __name(extendDatabase, "extendDatabase");
176
+ StaticCacheManager = class {
177
+ constructor(ctx) {
178
+ this.ctx = ctx;
179
+ }
180
+ static {
181
+ __name(this, "StaticCacheManager");
182
+ }
183
+ /**
184
+ * 设置缓存
185
+ * @param key 缓存键
186
+ * @param value 缓存值
187
+ */
188
+ async set(key, value) {
189
+ await this.ctx.database.upsert("delta_force_static_cache", [{
190
+ key,
191
+ value,
192
+ updated_at: /* @__PURE__ */ new Date()
193
+ }], ["key"]);
194
+ }
195
+ /**
196
+ * 获取缓存
197
+ * @param key 缓存键
198
+ * @returns 缓存值或null
199
+ */
200
+ async get(key) {
201
+ const [cache] = await this.ctx.database.get("delta_force_static_cache", { key });
202
+ return cache?.value || null;
203
+ }
204
+ /**
205
+ * 检查缓存是否存在
206
+ * @param key 缓存键
207
+ * @returns 是否存在
208
+ */
209
+ async has(key) {
210
+ const caches = await this.ctx.database.get("delta_force_static_cache", { key });
211
+ return caches && caches.length > 0;
212
+ }
213
+ /**
214
+ * 删除缓存
215
+ * @param key 缓存键
216
+ */
217
+ async delete(key) {
218
+ await this.ctx.database.remove("delta_force_static_cache", { key });
219
+ }
220
+ /**
221
+ * 清空所有缓存
222
+ */
223
+ async clear() {
224
+ await this.ctx.database.remove("delta_force_static_cache", {});
225
+ }
226
+ };
166
227
  __name(getTokenGroup, "getTokenGroup");
167
228
  __name(getGroupActiveToken, "getGroupActiveToken");
168
229
  __name(setGroupActiveToken, "setGroupActiveToken");
@@ -199,6 +260,7 @@ var ApiService = class {
199
260
  const headers = {
200
261
  "Authorization": `Bearer ${this.config.apiKey}`
201
262
  };
263
+ this.ctx.logger("delta-force").debug(`API请求: ${method} ${url}`, data ? { params: data } : "");
202
264
  let response;
203
265
  if (method === "GET") {
204
266
  response = await this.ctx.http.get(url, {
@@ -212,11 +274,25 @@ var ApiService = class {
212
274
  }
213
275
  return response;
214
276
  } catch (error) {
215
- this.ctx.logger("delta-force").error("API请求失败:", error);
277
+ const err = error;
278
+ if (err.response) {
279
+ const responseData = typeof err.response.data === "string" ? err.response.data.substring(0, 200) : err.response.data;
280
+ this.ctx.logger("delta-force").error(
281
+ `API请求失败: ${method} ${this.config.apiBaseUrl}${endpoint}`,
282
+ `状态码: ${err.response.status}`,
283
+ `响应: ${responseData}`
284
+ );
285
+ return {
286
+ success: false,
287
+ code: err.response.status,
288
+ message: `HTTP ${err.response.status}: ${err.response.statusText}`
289
+ };
290
+ }
291
+ this.ctx.logger("delta-force").error("API请求异常:", error);
216
292
  return {
217
293
  success: false,
218
294
  code: -1,
219
- message: error.message || "请求失败"
295
+ message: err.message || "请求失败"
220
296
  };
221
297
  }
222
298
  }
@@ -257,7 +333,7 @@ var ApiService = class {
257
333
  if (type) {
258
334
  params.type = type;
259
335
  }
260
- return this.request("GET", "/df/person/daily", params);
336
+ return this.request("GET", "/df/person/dailyRecord", params);
261
337
  }
262
338
  // 获取周报数据
263
339
  async getWeeklyReport(frameworkToken, type, isShowNullFriend, date) {
@@ -271,13 +347,18 @@ var ApiService = class {
271
347
  if (date) {
272
348
  params.date = date;
273
349
  }
274
- return this.request("GET", "/df/person/weekly", params);
350
+ return this.request("GET", "/df/person/weeklyRecord", params);
275
351
  }
276
352
  // 获取战绩列表
277
353
  async getRecordList(frameworkToken, type = "sol", page = 1) {
354
+ const typeMap = {
355
+ "sol": 4,
356
+ "mp": 5
357
+ };
358
+ const numericType = typeMap[type] || 4;
278
359
  return this.request("GET", "/df/person/record", {
279
360
  frameworkToken,
280
- type,
361
+ type: numericType,
281
362
  page
282
363
  });
283
364
  }
@@ -287,42 +368,297 @@ var ApiService = class {
287
368
  }
288
369
  // 获取干员列表
289
370
  async getOperators() {
290
- return this.request("GET", "/df/object/operator");
371
+ return this.request("GET", "/df/object/operator2");
291
372
  }
292
373
  // 获取每日密码
293
374
  async getDailyKeyword() {
294
375
  return this.request("GET", "/df/tools/dailykeyword");
295
376
  }
377
+ // 获取排位分数对照表
378
+ async getRankScore() {
379
+ return this.request("GET", "/df/object/rankscore");
380
+ }
381
+ // 获取音频标签列表
382
+ async getAudioTags() {
383
+ return this.request("GET", "/df/audio/tags");
384
+ }
385
+ // 获取音频角色列表
386
+ async getAudioCharacters() {
387
+ return this.request("GET", "/df/audio/characters");
388
+ }
389
+ // 获取音频分类列表
390
+ async getAudioCategories() {
391
+ return this.request("GET", "/df/audio/categories");
392
+ }
296
393
  };
297
394
 
298
395
  // src/data.ts
396
+ init_database();
299
397
  var mapData = null;
300
398
  var operatorData = null;
399
+ var rankScoreData = null;
400
+ var audioTagsData = null;
401
+ var audioCharactersData = null;
402
+ var audioCategoriesData = null;
403
+ var CACHE_PREFIX = "delta_force_";
301
404
  var DataManager = class {
302
405
  constructor(ctx, api) {
303
406
  this.ctx = ctx;
304
407
  this.api = api;
408
+ this.cacheManager = new StaticCacheManager(ctx);
305
409
  }
306
410
  static {
307
411
  __name(this, "DataManager");
308
412
  }
413
+ cacheManager;
309
414
  async init() {
310
415
  this.ctx.logger("delta-force").info("正在初始化数据缓存...");
416
+ await this.loadLocalCache();
417
+ const results = await Promise.allSettled([
418
+ this.fetchAndCacheMaps(),
419
+ this.fetchAndCacheOperators(),
420
+ this.fetchAndCacheRankScore(),
421
+ this.fetchAndCacheAudioData()
422
+ ]);
423
+ const taskNames = ["地图", "干员", "排位分数", "音频数据"];
424
+ const failedTasks = [];
425
+ results.forEach((result, index) => {
426
+ if (result.status === "rejected") {
427
+ failedTasks.push(taskNames[index]);
428
+ this.ctx.logger("delta-force").warn(`${taskNames[index]}同步失败:`, result.reason);
429
+ }
430
+ });
431
+ if (failedTasks.length === 0) {
432
+ this.ctx.logger("delta-force").info("数据缓存初始化完成");
433
+ } else {
434
+ this.ctx.logger("delta-force").info(`数据缓存初始化完成(${failedTasks.length}个任务失败,已使用本地缓存)`);
435
+ }
436
+ }
437
+ /**
438
+ * 从数据库加载本地缓存
439
+ */
440
+ async loadLocalCache() {
441
+ try {
442
+ const [maps, operators, rankScore, audioData] = await Promise.all([
443
+ this.cacheManager.get(`${CACHE_PREFIX}maps`),
444
+ this.cacheManager.get(`${CACHE_PREFIX}operators`),
445
+ this.cacheManager.get(`${CACHE_PREFIX}rankscore`),
446
+ this.cacheManager.get(`${CACHE_PREFIX}audiodata`)
447
+ ]);
448
+ if (maps && maps.data) {
449
+ mapData = new Map(Object.entries(maps.data));
450
+ this.ctx.logger("delta-force").debug(`已从数据库加载地图数据 (${mapData.size}条记录)`);
451
+ }
452
+ if (operators && operators.data) {
453
+ operatorData = new Map(Object.entries(operators.data));
454
+ this.ctx.logger("delta-force").debug(`已从数据库加载干员数据 (${operatorData.size}条记录)`);
455
+ }
456
+ if (rankScore && rankScore.data) {
457
+ rankScoreData = rankScore.data;
458
+ this.ctx.logger("delta-force").debug(`已从数据库加载排位分数数据`);
459
+ }
460
+ if (audioData && audioData.data) {
461
+ const data = audioData.data;
462
+ if (data.tags && data.keywords) {
463
+ audioTagsData = { _tags: data.tags, _keywords: data.keywords };
464
+ }
465
+ if (data.characters) {
466
+ audioCharactersData = data.characters;
467
+ }
468
+ if (data.categories) {
469
+ audioCategoriesData = data.categories;
470
+ }
471
+ this.ctx.logger("delta-force").debug(`已从数据库加载音频数据`);
472
+ }
473
+ } catch (error) {
474
+ this.ctx.logger("delta-force").warn("从数据库加载本地缓存失败:", error.message);
475
+ }
476
+ }
477
+ /**
478
+ * 保存数据到数据库缓存
479
+ */
480
+ async saveToDatabase(key, data) {
481
+ try {
482
+ await this.cacheManager.set(`${CACHE_PREFIX}${key}`, data);
483
+ } catch (error) {
484
+ this.ctx.logger("delta-force").warn(`保存${key}到数据库失败:`, error.message);
485
+ }
486
+ }
487
+ async fetchAndCacheMaps() {
488
+ try {
489
+ const res = await this.api.getMaps();
490
+ if (res && (res.success || res.code === 0) && res.data) {
491
+ const data = res.data.map((item) => [String(item.id), item.name]);
492
+ mapData = new Map(data);
493
+ await this.saveToDatabase("maps", { data: Object.fromEntries(data) });
494
+ this.ctx.logger("delta-force").debug(`地图数据同步成功 (${mapData.size}条记录)`);
495
+ } else {
496
+ throw new Error("API返回失败状态");
497
+ }
498
+ } catch (error) {
499
+ this.ctx.logger("delta-force").warn("获取地图数据失败,使用本地缓存:", error.message);
500
+ if (!mapData) {
501
+ throw error;
502
+ }
503
+ }
504
+ }
505
+ async fetchAndCacheOperators() {
506
+ try {
507
+ const res = await this.api.getOperators();
508
+ if (res && (res.success || res.code === 0) && res.data) {
509
+ const data = res.data.map((item) => [String(item.id), item.name]);
510
+ operatorData = new Map(data);
511
+ await this.saveToDatabase("operators", { data: Object.fromEntries(data) });
512
+ this.ctx.logger("delta-force").debug(`干员数据同步成功 (${operatorData.size}条记录)`);
513
+ } else {
514
+ throw new Error("API返回失败状态");
515
+ }
516
+ } catch (error) {
517
+ this.ctx.logger("delta-force").warn("获取干员数据失败,使用本地缓存:", error.message);
518
+ if (!operatorData) {
519
+ throw error;
520
+ }
521
+ }
522
+ }
523
+ async fetchAndCacheRankScore() {
524
+ try {
525
+ const res = await this.api.getRankScore();
526
+ if (res && (res.success || res.code === 0) && res.data) {
527
+ const processedData = {};
528
+ const data = res.data;
529
+ for (const mode in data) {
530
+ processedData[mode] = {};
531
+ const modeData = data[mode];
532
+ if (Array.isArray(modeData)) {
533
+ modeData.forEach((item) => {
534
+ processedData[mode][String(item.score)] = item.name;
535
+ });
536
+ }
537
+ }
538
+ rankScoreData = processedData;
539
+ await this.saveToDatabase("rankscore", { data: processedData });
540
+ this.ctx.logger("delta-force").debug("排位分数数据同步成功");
541
+ } else {
542
+ throw new Error("API返回失败状态");
543
+ }
544
+ } catch (error) {
545
+ this.ctx.logger("delta-force").warn("获取排位分数数据失败,使用本地缓存:", error.message);
546
+ if (!rankScoreData) {
547
+ throw error;
548
+ }
549
+ }
550
+ }
551
+ async fetchAndCacheAudioData() {
311
552
  try {
312
- const mapsRes = await this.api.getMaps();
313
- if (mapsRes.code === 0 && mapsRes.data) {
314
- mapData = new Map(mapsRes.data.map((item) => [String(item.id), item.name]));
315
- this.ctx.logger("delta-force").info(`地图数据加载成功 (${mapData.size}条记录)`);
553
+ const [tagsRes, charactersRes, categoriesRes] = await Promise.all([
554
+ this.api.getAudioTags().catch((err) => {
555
+ this.ctx.logger("delta-force").warn("获取音频标签API失败:", err.message);
556
+ return null;
557
+ }),
558
+ this.api.getAudioCharacters().catch((err) => {
559
+ this.ctx.logger("delta-force").warn("获取音频角色API失败:", err.message);
560
+ return null;
561
+ }),
562
+ this.api.getAudioCategories().catch((err) => {
563
+ this.ctx.logger("delta-force").warn("获取音频分类API失败:", err.message);
564
+ return null;
565
+ })
566
+ ]);
567
+ const audioData = {
568
+ tags: {},
569
+ keywords: {},
570
+ characters: {},
571
+ categories: {}
572
+ };
573
+ let hasAnyData = false;
574
+ if (tagsRes && (tagsRes.success || tagsRes.code === 0)) {
575
+ if (tagsRes.data && Array.isArray(tagsRes.data.tags)) {
576
+ tagsRes.data.tags.forEach((tagInfo) => {
577
+ const tag = tagInfo.tag;
578
+ const desc = tagInfo.description || "";
579
+ audioData.tags[tag] = desc;
580
+ if (desc) {
581
+ const keywords = desc.split(/[\/、]/).map((k) => k.trim());
582
+ keywords.forEach((keyword) => {
583
+ if (keyword && keyword.length > 0 && keyword.length < 20) {
584
+ audioData.keywords[keyword] = tag;
585
+ }
586
+ });
587
+ }
588
+ });
589
+ this.ctx.logger("delta-force").debug(`音频标签: ${Object.keys(audioData.tags).length}个tag, ${Object.keys(audioData.keywords).length}个关键词`);
590
+ hasAnyData = true;
591
+ }
592
+ }
593
+ if (charactersRes && (charactersRes.success || charactersRes.code === 0)) {
594
+ if (charactersRes.data && Array.isArray(charactersRes.data.characters)) {
595
+ charactersRes.data.characters.forEach((char) => {
596
+ const voiceId = char.voiceId;
597
+ const name2 = char.name;
598
+ if (name2) {
599
+ audioData.characters[name2] = voiceId;
600
+ }
601
+ if (char.skins && Array.isArray(char.skins)) {
602
+ char.skins.forEach((skin) => {
603
+ if (skin.name) {
604
+ audioData.characters[skin.name] = skin.voiceId;
605
+ }
606
+ });
607
+ }
608
+ });
609
+ this.ctx.logger("delta-force").debug(`音频角色: ${Object.keys(audioData.characters).length}个映射`);
610
+ hasAnyData = true;
611
+ }
612
+ }
613
+ if (categoriesRes && (categoriesRes.success || categoriesRes.code === 0)) {
614
+ if (categoriesRes.data && Array.isArray(categoriesRes.data.categories)) {
615
+ const categoryNames = {
616
+ "Voice": "角色语音",
617
+ "CutScene": "过场动画",
618
+ "Amb": "环境音效",
619
+ "Music": "背景音乐",
620
+ "SFX": "音效",
621
+ "Festivel": "节日活动",
622
+ "Intro": "介绍",
623
+ "UI": "界面",
624
+ "Voice_SOL_MS": "单人模式"
625
+ };
626
+ categoriesRes.data.categories.forEach((catInfo) => {
627
+ const category = catInfo.category;
628
+ const cnName = categoryNames[category] || category;
629
+ audioData.categories[category] = category;
630
+ audioData.categories[cnName] = category;
631
+ audioData.categories[category.toLowerCase()] = category;
632
+ });
633
+ this.ctx.logger("delta-force").debug(`音频分类: ${categoriesRes.data.categories.length}个分类`);
634
+ hasAnyData = true;
635
+ }
316
636
  }
317
- const operatorsRes = await this.api.getOperators();
318
- if (operatorsRes.code === 0 && operatorsRes.data) {
319
- operatorData = new Map(operatorsRes.data.map((item) => [String(item.id), item.name]));
320
- this.ctx.logger("delta-force").info(`干员数据加载成功 (${operatorData.size}条记录)`);
637
+ if (hasAnyData) {
638
+ if (Object.keys(audioData.tags).length > 0 || Object.keys(audioData.keywords).length > 0) {
639
+ audioTagsData = { _tags: audioData.tags, _keywords: audioData.keywords };
640
+ }
641
+ if (Object.keys(audioData.characters).length > 0) {
642
+ audioCharactersData = audioData.characters;
643
+ }
644
+ if (Object.keys(audioData.categories).length > 0) {
645
+ audioCategoriesData = audioData.categories;
646
+ }
647
+ await this.saveToDatabase("audiodata", { data: audioData });
648
+ const tagCount = Object.keys(audioData.tags).length || 0;
649
+ const keywordCount = Object.keys(audioData.keywords).length || 0;
650
+ const charCount = Object.keys(audioData.characters).length || 0;
651
+ const catCount = Object.keys(audioData.categories).length || 0;
652
+ this.ctx.logger("delta-force").debug(`音频数据同步完成 (标签${tagCount}/${keywordCount}, 角色${charCount}, 分类${catCount})`);
321
653
  }
322
654
  } catch (error) {
323
- this.ctx.logger("delta-force").warn("数据缓存初始化失败:", error);
655
+ this.ctx.logger("delta-force").error("音频数据API请求异常:", error.message);
656
+ if (!audioTagsData && !audioCharactersData && !audioCategoriesData) {
657
+ throw error;
658
+ }
324
659
  }
325
660
  }
661
+ // ============ 数据访问方法 ============
326
662
  getMapName(id) {
327
663
  if (!mapData) return `地图(${id})`;
328
664
  return mapData.get(String(id)) || `未知地图(${id})`;
@@ -331,6 +667,99 @@ var DataManager = class {
331
667
  if (!operatorData) return `干员(${id})`;
332
668
  return operatorData.get(String(id)) || `未知干员(${id})`;
333
669
  }
670
+ /**
671
+ * 根据分数获取对应的段位名称
672
+ * @param score 分数
673
+ * @param mode 模式 ('sol' 或 'tdm')
674
+ * @returns 段位名称
675
+ */
676
+ getRankByScore(score, mode = "sol") {
677
+ if (!rankScoreData) return `${score}分`;
678
+ const numScore = typeof score === "string" ? parseInt(score) : score;
679
+ if (isNaN(numScore)) {
680
+ return `分数无效(${score})`;
681
+ }
682
+ const modeData = rankScoreData[mode];
683
+ if (!modeData) {
684
+ return `${score}分 (${mode}模式)`;
685
+ }
686
+ const thresholds = Object.keys(modeData).map((s) => parseInt(s)).sort((a, b) => b - a);
687
+ for (const threshold of thresholds) {
688
+ if (numScore >= threshold) {
689
+ const rankName = modeData[String(threshold)];
690
+ const isHighestRank = mode === "sol" && threshold === 6e3 || mode === "tdm" && threshold === 5e3;
691
+ if (isHighestRank && numScore > threshold) {
692
+ const extraScore = numScore - threshold;
693
+ const stars = Math.floor(extraScore / 50);
694
+ if (stars > 0) {
695
+ return `${rankName}${stars}星 (${numScore})`;
696
+ }
697
+ }
698
+ return `${rankName} (${numScore})`;
699
+ }
700
+ }
701
+ const lowestThreshold = thresholds[thresholds.length - 1];
702
+ const lowestRank = modeData[String(lowestThreshold)];
703
+ return `${lowestRank} (${numScore})`;
704
+ }
705
+ /**
706
+ * 根据中文名或tag获取音频标签
707
+ * @param keyword 关键词(中文名或tag)
708
+ * @returns tag值
709
+ */
710
+ getAudioTag(keyword) {
711
+ if (!audioTagsData) return null;
712
+ if (audioTagsData._tags[keyword]) {
713
+ return keyword;
714
+ }
715
+ if (audioTagsData._keywords[keyword]) {
716
+ return audioTagsData._keywords[keyword];
717
+ }
718
+ return null;
719
+ }
720
+ /**
721
+ * 判断字符串是否是tag格式
722
+ * @param str 字符串
723
+ * @returns 是否是tag格式
724
+ */
725
+ isTagFormat(str) {
726
+ if (!str || typeof str !== "string") return false;
727
+ return str.startsWith("boss-") || str.startsWith("task-") || str.startsWith("Evac-") || str.startsWith("eggs-") || str.startsWith("bf-") || str.startsWith("BF_") || ["haavk", "commander", "babel", "Beginner"].includes(str);
728
+ }
729
+ /**
730
+ * 根据中文名或voiceId获取角色ID
731
+ * @param keyword 关键词(中文名或voiceId)
732
+ * @returns voiceId值
733
+ */
734
+ getAudioCharacter(keyword) {
735
+ if (!audioCharactersData) return null;
736
+ return audioCharactersData[keyword] || null;
737
+ }
738
+ /**
739
+ * 根据中文名或英文名获取音频分类
740
+ * @param keyword 关键词(中文名或英文名)
741
+ * @returns category值
742
+ */
743
+ getAudioCategory(keyword) {
744
+ if (!audioCategoriesData) return null;
745
+ return audioCategoriesData[keyword] || null;
746
+ }
747
+ /**
748
+ * 检查是否是有效的音频标签
749
+ * @param keyword 关键词
750
+ * @returns 是否是有效标签
751
+ */
752
+ isValidAudioTag(keyword) {
753
+ return this.getAudioTag(keyword) !== null;
754
+ }
755
+ /**
756
+ * 检查是否是有效的角色名
757
+ * @param keyword 关键词
758
+ * @returns 是否是有效角色
759
+ */
760
+ isValidAudioCharacter(keyword) {
761
+ return this.getAudioCharacter(keyword) !== null;
762
+ }
334
763
  };
335
764
 
336
765
  // src/index.ts
@@ -383,7 +812,7 @@ __name(sleep, "sleep");
383
812
  // src/commands/login.ts
384
813
  function registerLoginCommands(ctx, config, api) {
385
814
  const logger = ctx.logger("delta-force");
386
- ctx.command("df.login [平台:string]", "登录账号").option("platform", "-p <platform:string> 登录平台(qq/wechat/wegame/qqsafe)", { fallback: "qq" }).action(async ({ session, options }) => {
815
+ ctx.command("df.login [平台:string]", "登录账号").option("platform", "-p <platform:string> 登录平台(qq/wechat/wegame/qqsafe/wegame/wechat)", { fallback: "qq" }).action(async ({ session, options }) => {
387
816
  let platform = options.platform || "qq";
388
817
  const userId = session.userId;
389
818
  const userPlatform = session.platform;
@@ -391,20 +820,35 @@ function registerLoginCommands(ctx, config, api) {
391
820
  if (["wx", "微信"].includes(platform)) platform = "wechat";
392
821
  if (["安全中心", "qq安全中心"].includes(platform)) platform = "qqsafe";
393
822
  if (["wegame微信", "微信wegame"].includes(platform)) platform = "wegame/wechat";
823
+ const validPlatforms = ["qq", "wechat", "wegame", "qqsafe", "wegame/wechat"];
824
+ if (!validPlatforms.includes(platform)) {
825
+ return `不支持的平台: ${platform}
826
+ 支持的登录平台: qq, wechat, wegame, qqsafe, wegame/wechat`;
827
+ }
394
828
  const originalPlatform = platform;
395
829
  await session.send("正在获取登录二维码,请稍候...");
396
830
  try {
397
831
  const qrRes = await api.getLoginQr(platform);
398
- if (qrRes.code !== 0 || !qrRes.qr_image) {
399
- return "获取二维码失败,请稍后重试";
832
+ if (!qrRes || qrRes.code !== 0 || !qrRes.qr_image) {
833
+ const errorMsg = qrRes?.msg || qrRes?.message || "获取二维码失败,请稍后重试";
834
+ logger.error(`获取${platform}登录二维码失败:`, errorMsg);
835
+ return `获取二维码失败: ${errorMsg}`;
400
836
  }
401
837
  const frameworkToken = qrRes.token || qrRes.frameworkToken;
402
838
  if (!frameworkToken) {
403
839
  return "获取登录凭证失败,请稍后重试";
404
840
  }
405
841
  let qrImage = qrRes.qr_image;
406
- if (platform !== "wechat" && qrImage.startsWith("data:image/png;base64,")) {
407
- qrImage = qrImage.replace(/^data:image\/png;base64,/, "");
842
+ if (platform === "wechat") {
843
+ if (!qrImage.startsWith("http")) {
844
+ if (qrImage.startsWith("data:image/png;base64,")) {
845
+ qrImage = qrImage.replace(/^data:image\/png;base64,/, "");
846
+ }
847
+ }
848
+ } else {
849
+ if (qrImage.startsWith("data:image/png;base64,")) {
850
+ qrImage = qrImage.replace(/^data:image\/png;base64,/, "");
851
+ }
408
852
  }
409
853
  let platformName;
410
854
  switch (platform) {
@@ -426,11 +870,17 @@ function registerLoginCommands(ctx, config, api) {
426
870
  default:
427
871
  platformName = platform.toUpperCase();
428
872
  }
873
+ let imageElement;
874
+ if (qrImage.startsWith("http")) {
875
+ imageElement = (0, import_koishi.h)("image", { url: qrImage });
876
+ } else {
877
+ imageElement = (0, import_koishi.h)("image", { url: `data:image/png;base64,${qrImage}` });
878
+ }
429
879
  await session.send((0, import_koishi.h)("message", [
430
880
  (0, import_koishi.h)("text", `请使用【${platformName}】扫描二维码登录
431
881
  有效期约2分钟
432
882
  `),
433
- (0, import_koishi.h)("image", { url: `data:image/png;base64,${qrImage}` })
883
+ imageElement
434
884
  ]));
435
885
  const startTime = Date.now();
436
886
  const timeout = 18e4;
@@ -947,17 +1397,30 @@ __name(parseAndGetName, "parseAndGetName");
947
1397
  init_database();
948
1398
  function registerRecordCommands(ctx, api, dataManager) {
949
1399
  const logger = ctx.logger("delta-force");
950
- ctx.command("df.record [类型:string] [页码:number]", "查看战绩").action(async ({ session }, type = "sol", page = 1) => {
1400
+ ctx.command("df.record [...args:string]", "查看战绩").alias("战绩").action(async ({ session }, ...args) => {
951
1401
  const userId = session.userId;
952
1402
  const platform = session.platform;
1403
+ let mode = "sol";
1404
+ let page = 1;
1405
+ let modeName = "烽火地带";
1406
+ for (const arg of args) {
1407
+ if (["全面", "全面战场", "战场", "mp"].includes(arg)) {
1408
+ mode = "mp";
1409
+ modeName = "全面战场";
1410
+ } else if (["烽火", "烽火地带", "sol", "摸金"].includes(arg)) {
1411
+ mode = "sol";
1412
+ modeName = "烽火地带";
1413
+ } else if (!isNaN(parseInt(arg))) {
1414
+ page = parseInt(arg) > 0 ? parseInt(arg) : 1;
1415
+ }
1416
+ }
953
1417
  const token = await getActiveToken(ctx, userId, platform);
954
1418
  if (!token) {
955
1419
  return "您尚未登录,请先使用 df.login 登录";
956
1420
  }
957
- const modeName = type === "sol" ? "烽火地带" : "全面战场";
958
1421
  await session.send(`正在查询 ${modeName} 的战绩 (第${page}页),请稍候...`);
959
1422
  try {
960
- const res = await api.getRecordList(token, type, page);
1423
+ const res = await api.getRecordList(token, mode, page);
961
1424
  if (await handleApiError(res, session)) return;
962
1425
  if (!res.data || !Array.isArray(res.data) || res.data.length === 0) {
963
1426
  return `您在 ${modeName} (第${page}页) 没有更多战绩记录`;
@@ -966,7 +1429,7 @@ function registerRecordCommands(ctx, api, dataManager) {
966
1429
  let message = `【${modeName}战绩 - 第${page}页】
967
1430
 
968
1431
  `;
969
- if (type === "sol") {
1432
+ if (mode === "sol") {
970
1433
  message += formatSolRecords(records, page, dataManager);
971
1434
  } else {
972
1435
  message += formatMpRecords(records, page, dataManager);
@@ -1042,9 +1505,44 @@ __name(formatMpRecords, "formatMpRecords");
1042
1505
  init_database();
1043
1506
  function registerAccountCommands(ctx, config, api) {
1044
1507
  const logger = ctx.logger("delta-force");
1508
+ const isPrivateSession = /* @__PURE__ */ __name((session) => {
1509
+ return !!session.isDirect || session.channel?.id === "private";
1510
+ }, "isPrivateSession");
1511
+ const formatToken = /* @__PURE__ */ __name((token, isPrivate) => {
1512
+ if (isPrivate) {
1513
+ return token;
1514
+ }
1515
+ return `${token.substring(0, 4)}****${token.slice(-4)}`;
1516
+ }, "formatToken");
1517
+ const groupAccounts = /* @__PURE__ */ __name((accounts) => {
1518
+ const grouped = {
1519
+ qq_wechat: [],
1520
+ wegame: [],
1521
+ qqsafe: []
1522
+ };
1523
+ accounts.forEach((acc) => {
1524
+ const type = acc.tokenType?.toLowerCase();
1525
+ if (type === "qq" || type === "wechat") {
1526
+ grouped.qq_wechat.push(acc);
1527
+ } else if (type === "wegame" || type === "wegame/wechat") {
1528
+ grouped.wegame.push(acc);
1529
+ } else if (type === "qqsafe") {
1530
+ grouped.qqsafe.push(acc);
1531
+ }
1532
+ });
1533
+ return grouped;
1534
+ }, "groupAccounts");
1535
+ const buildOrderedAccountList = /* @__PURE__ */ __name((grouped) => {
1536
+ return [
1537
+ ...grouped.qq_wechat,
1538
+ ...grouped.wegame,
1539
+ ...grouped.qqsafe
1540
+ ];
1541
+ }, "buildOrderedAccountList");
1045
1542
  ctx.command("df.account", "账号管理").action(async ({ session }) => {
1046
1543
  const userId = session.userId;
1047
1544
  const platform = session.platform;
1545
+ const isPrivate = isPrivateSession(session);
1048
1546
  try {
1049
1547
  const listRes = await api.getUserList(userId, config.clientID);
1050
1548
  if (!listRes || listRes.code !== 0) {
@@ -1059,26 +1557,7 @@ function registerAccountCommands(ctx, config, api) {
1059
1557
  wegame: await getGroupActiveToken(ctx, userId, platform, "wegame"),
1060
1558
  qqsafe: await getGroupActiveToken(ctx, userId, platform, "qqsafe")
1061
1559
  };
1062
- const grouped = {
1063
- qq_wechat: [],
1064
- wegame: [],
1065
- qqsafe: []
1066
- };
1067
- accounts.forEach((acc) => {
1068
- const type = acc.tokenType?.toLowerCase();
1069
- if (type === "qq" || type === "wechat") {
1070
- grouped.qq_wechat.push(acc);
1071
- } else if (type === "wegame" || type === "wegame/wechat") {
1072
- grouped.wegame.push(acc);
1073
- } else if (type === "qqsafe") {
1074
- grouped.qqsafe.push(acc);
1075
- }
1076
- });
1077
- const allInOrder = [
1078
- ...grouped.qq_wechat,
1079
- ...grouped.wegame,
1080
- ...grouped.qqsafe
1081
- ];
1560
+ const grouped = groupAccounts(accounts);
1082
1561
  let message = "【账号列表】\n\n";
1083
1562
  let overallIndex = 1;
1084
1563
  const groupNames = {
@@ -1094,10 +1573,10 @@ function registerAccountCommands(ctx, config, api) {
1094
1573
  const groupActiveToken = activeTokens[groupKey];
1095
1574
  groupTokens.forEach((token) => {
1096
1575
  const isActive = token.frameworkToken === groupActiveToken ? "✅ " : "";
1097
- const maskedToken = `${token.frameworkToken.substring(0, 4)}****${token.frameworkToken.slice(-4)}`;
1576
+ const tokenDisplay = formatToken(token.frameworkToken, isPrivate);
1098
1577
  const status = token.isValid ? "有效" : "失效";
1099
1578
  const qqDisplay = token.qqNumber ? ` (${token.qqNumber.slice(0, 4)}****)` : "";
1100
- message += `${overallIndex++}. ${isActive}[${token.tokenType.toUpperCase()}]${qqDisplay} ${maskedToken} (${status})
1579
+ message += `${overallIndex++}. ${isActive}[${token.tokenType.toUpperCase()}]${qqDisplay} ${tokenDisplay} (${status})
1101
1580
  `;
1102
1581
  });
1103
1582
  message += "\n";
@@ -1114,32 +1593,15 @@ function registerAccountCommands(ctx, config, api) {
1114
1593
  ctx.command("df.switch <序号:number>", "切换账号").action(async ({ session }, index) => {
1115
1594
  const userId = session.userId;
1116
1595
  const platform = session.platform;
1596
+ const isPrivate = isPrivateSession(session);
1117
1597
  try {
1118
1598
  const listRes = await api.getUserList(userId, config.clientID);
1119
1599
  if (!listRes || listRes.code !== 0 || !listRes.data) {
1120
1600
  return `查询账号列表失败: ${listRes?.msg || listRes?.message || "未知错误"}`;
1121
1601
  }
1122
1602
  const accounts = listRes.data;
1123
- const grouped = {
1124
- qq_wechat: [],
1125
- wegame: [],
1126
- qqsafe: []
1127
- };
1128
- accounts.forEach((acc) => {
1129
- const type = acc.tokenType?.toLowerCase();
1130
- if (type === "qq" || type === "wechat") {
1131
- grouped.qq_wechat.push(acc);
1132
- } else if (type === "wegame" || type === "wegame/wechat") {
1133
- grouped.wegame.push(acc);
1134
- } else if (type === "qqsafe") {
1135
- grouped.qqsafe.push(acc);
1136
- }
1137
- });
1138
- const allInOrder = [
1139
- ...grouped.qq_wechat,
1140
- ...grouped.wegame,
1141
- ...grouped.qqsafe
1142
- ];
1603
+ const grouped = groupAccounts(accounts);
1604
+ const allInOrder = buildOrderedAccountList(grouped);
1143
1605
  if (index < 1 || index > allInOrder.length) {
1144
1606
  return "序号无效,请使用 df.account 查看账号列表";
1145
1607
  }
@@ -1155,10 +1617,10 @@ function registerAccountCommands(ctx, config, api) {
1155
1617
  qqsafe: "QQ安全中心",
1156
1618
  other: "其他"
1157
1619
  };
1158
- const maskedToken = `${targetToken.frameworkToken.substring(0, 4)}****${targetToken.frameworkToken.slice(-4)}`;
1620
+ const tokenDisplay = formatToken(targetToken.frameworkToken, isPrivate);
1159
1621
  const qqDisplay = targetToken.qqNumber ? ` (${targetToken.qqNumber.slice(0, 4)}****)` : "";
1160
1622
  return `账号切换成功!
1161
- 当前${groupNames[targetGroup] || targetGroup}分组使用:${qqDisplay} ${maskedToken}`;
1623
+ 当前${groupNames[targetGroup] || targetGroup}分组使用:${qqDisplay} ${tokenDisplay}`;
1162
1624
  } catch (error) {
1163
1625
  logger.error("切换账号失败:", error);
1164
1626
  return `切换失败: ${error.message}`;
@@ -1173,26 +1635,8 @@ function registerAccountCommands(ctx, config, api) {
1173
1635
  return `查询账号列表失败: ${listRes?.msg || listRes?.message || "未知错误"}`;
1174
1636
  }
1175
1637
  const accounts = listRes.data;
1176
- const grouped = {
1177
- qq_wechat: [],
1178
- wegame: [],
1179
- qqsafe: []
1180
- };
1181
- accounts.forEach((acc) => {
1182
- const type = acc.tokenType?.toLowerCase();
1183
- if (type === "qq" || type === "wechat") {
1184
- grouped.qq_wechat.push(acc);
1185
- } else if (type === "wegame" || type === "wegame/wechat") {
1186
- grouped.wegame.push(acc);
1187
- } else if (type === "qqsafe") {
1188
- grouped.qqsafe.push(acc);
1189
- }
1190
- });
1191
- const allInOrder = [
1192
- ...grouped.qq_wechat,
1193
- ...grouped.wegame,
1194
- ...grouped.qqsafe
1195
- ];
1638
+ const grouped = groupAccounts(accounts);
1639
+ const allInOrder = buildOrderedAccountList(grouped);
1196
1640
  if (index < 1 || index > allInOrder.length) {
1197
1641
  return "序号无效,请使用 df.account 查看账号列表";
1198
1642
  }
@@ -1267,7 +1711,9 @@ function apply(ctx, config) {
1267
1711
  extendDatabase(ctx);
1268
1712
  const api = new ApiService(ctx, config);
1269
1713
  const dataManager = new DataManager(ctx, api);
1270
- dataManager.init().catch((err) => {
1714
+ Promise.all([
1715
+ dataManager.init()
1716
+ ]).catch((err) => {
1271
1717
  logger.warn("数据管理器初始化失败:", err);
1272
1718
  });
1273
1719
  ctx.command("df", "三角洲行动").alias("三角洲");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-delta-force",
3
3
  "description": "三角洲行动游戏数据查询插件",
4
- "version": "1.0.0-alpha.0",
4
+ "version": "1.0.0-beta.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [