koishi-plugin-noah 1.0.19 → 1.1.2

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.
@@ -0,0 +1,2 @@
1
+ import { AssetConfig } from '../types/config';
2
+ export declare const assetConfig: AssetConfig;
@@ -0,0 +1,5 @@
1
+ import { AppConfig } from "../types/config";
2
+ import { Context, Logger } from "koishi";
3
+ export declare const name = "Noah-Asset";
4
+ export declare const logger: Logger;
5
+ export declare function apply(ctx: Context, config: AppConfig): void;
@@ -0,0 +1,42 @@
1
+ import { Context } from 'koishi';
2
+ import { AssetConfig } from '../types/config';
3
+ export declare class AssetService {
4
+ private ctx;
5
+ private logger;
6
+ private config;
7
+ private updateTimer;
8
+ private basePath;
9
+ constructor(ctx: Context, config: AssetConfig);
10
+ /**
11
+ * Initialize the asset service
12
+ */
13
+ initialize(): Promise<void>;
14
+ /**
15
+ * Stop the asset service
16
+ */
17
+ dispose(): void;
18
+ /**
19
+ * Get the latest release information from GitHub
20
+ */
21
+ private getLatestRelease;
22
+ /**
23
+ * Check for asset updates and download if available
24
+ */
25
+ checkForUpdates(): Promise<boolean>;
26
+ /**
27
+ * Force an immediate update check
28
+ */
29
+ forceUpdate(): Promise<boolean>;
30
+ /**
31
+ * Download an asset by its ID
32
+ */
33
+ private downloadAsset;
34
+ /**
35
+ * Extract the assets from the downloaded zip file
36
+ */
37
+ private extractAssets;
38
+ /**
39
+ * Ensure a directory exists
40
+ */
41
+ private ensureDirectoryExists;
42
+ }
@@ -0,0 +1,13 @@
1
+ import { Context } from 'koishi';
2
+ /**
3
+ * Initialize global constants with application context
4
+ * @param ctx Koishi Context
5
+ */
6
+ export declare function initConstants(ctx: Context): void;
7
+ /**
8
+ * Get the full asset path combining baseDir and asset data path
9
+ * @param ctx Koishi Context
10
+ * @param assetPath Relative path within the asset directory
11
+ * @returns Full resolved path to the asset
12
+ */
13
+ export declare function getAssetPath(ctx: Context, assetPath: string): string;
@@ -0,0 +1,2 @@
1
+ import { PokeConfig } from '../../types/config';
2
+ export declare const pokeConfig: PokeConfig;
@@ -0,0 +1,4 @@
1
+ import { Context } from "koishi";
2
+ import { AppConfig } from "../../types/config";
3
+ export declare const name = "Noah-Poke";
4
+ export declare function apply(ctx: Context, config: AppConfig): void;
@@ -0,0 +1,12 @@
1
+ declare module "koishi" {
2
+ interface Events {
3
+ notice(session: Session): void;
4
+ }
5
+ interface Session {
6
+ targetId: string;
7
+ }
8
+ }
9
+ export interface MessageReply {
10
+ content: string;
11
+ weight: number;
12
+ }
package/lib/index.js CHANGED
@@ -6,8 +6,8 @@ var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
8
  var __export = (target, all) => {
9
- for (var name11 in all)
10
- __defProp(target, name11, { get: all[name11], enumerable: true });
9
+ for (var name13 in all)
10
+ __defProp(target, name13, { get: all[name13], enumerable: true });
11
11
  };
12
12
  var __copyProps = (to, from, except, desc) => {
13
13
  if (from && typeof from === "object" || typeof from === "function") {
@@ -31,9 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  Config: () => Config,
34
- apply: () => apply10,
34
+ apply: () => apply12,
35
35
  inject: () => inject3,
36
- name: () => name10
36
+ name: () => name12
37
37
  });
38
38
  module.exports = __toCommonJS(src_exports);
39
39
 
@@ -48,10 +48,10 @@ __export(core_exports, {
48
48
  var import_koishi3 = require("koishi");
49
49
 
50
50
  // src/core/locales/en-US.yml
51
- var en_US_default = { _config: { $desc: "Core Module Settings", adminUsers: "**Plugin Admin** User ID (use inspect command to get)" }, commands: { timeout: "Noah didn't wait for your reply, please try again!", noah: { help: { description: "Show Noah help information", messages: { content: "<p>Help document:</p>\n<a>https://docs.logthm.com/noah</a>\n<p>If you cannot access the link above, please use the mirror site below:</p>\n<a>https://logthm.cn/noah</a>" } } }, bind: { description: "Bind card", messages: { prompt: "<p>Please enter your card number:</p>", "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", duplicate: "<p>This card has already been bound (︶^︶)</p>", name: "<p>Received! Please give this card a name, no spaces allowed:</p>", invalid_name: "<p>No spaces allowed! Please try again o(一︿一+)o</p>", success: "<p>Bound successfully, your card information is as follows:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "Manage cards", messages: { "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "invalid-select": "<p>No such option!</p>", "menu-select": "<p>[Card Management]</p>\n{card_list}\n<p>0. Add new card</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>Bound server: {defaultServerName}</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected card is the same as the old default card!</p>", "menu-2-prompt": "<p>Card number: {code}</p>\n<p>Please enter the new card number:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-2-error-invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "menu-5": "{server_list}\n<p>Please enter the serial number:</p>", "menu-5-success": "<p>Set successfully!</p>", "menu-5-error-duplicate": "<p>The selected server is the same as the old default server!</p>" } }, server: { description: "Manage servers", messages: { "invalid-select": "<p>No such option!</p>", "no-auth": "<p>Only group admins can use this feature~</p>", "admin-menu-select": "<p>[Group server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", "menu-select": "<p>[Server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>Type: {type}</p>\n<p>1. Set as default server</p>\n<p>2. View or modify url</p>\n<p>3. Delete the server</p>\n<p>4. Rename the server</p>\n<p>0. Return to server selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected server is the same as the old default server!</p>", "menu-2-prompt": "<p>The server's url: {baseUrl}</p>\n<p>Please enter the new server url:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "add-type": "<p>Please select the server type:</p>\n{server_type_list}", "add-url": "<p>Please enter the server url:</p>", "add-name": "<p>Received! Please give the server a name, no spaces allowed:</p>", "add-invalid_name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "add-success": "<p>Added successfully, the server information is as follows:</p>\n<p>[{serverName}]</p>\n<p>Type: {serverType}</p>" } } } };
51
+ var en_US_default = { _config: { $desc: "Core Module Settings", adminUsers: "**Plugin Admin** User ID (use inspect command to get)" }, commands: { timeout: "Noah didn't wait for your reply, please try again!", noah: { help: { description: "Show Noah help information", messages: { content: "<p>Guide:</p>\n<a>https://docs.logthm.cn/noah</a>" } } }, bind: { description: "Bind card", messages: { prompt: "<p>Please enter your card number:</p>", "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", duplicate: "<p>This card has already been bound (︶^︶)</p>", name: "<p>Received! Please give this card a name, no spaces allowed:</p>", invalid_name: "<p>No spaces allowed! Please try again o(一︿一+)o</p>", success: "<p>Bound successfully, your card information is as follows:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "Manage cards", messages: { "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "invalid-select": "<p>No such option!</p>", "menu-select": "<p>[Card Management]</p>\n{card_list}\n<p>0. Add new card</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>Bound server: {defaultServerName}</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected card is the same as the old default card!</p>", "menu-2-prompt": "<p>Card number: {code}</p>\n<p>Please enter the new card number:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-2-error-invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "menu-5": "{server_list}\n<p>Please enter the serial number:</p>", "menu-5-success": "<p>Set successfully!</p>", "menu-5-error-duplicate": "<p>The selected server is the same as the old default server!</p>" } }, server: { description: "Manage servers", messages: { "invalid-select": "<p>No such option!</p>", "no-auth": "<p>Only group admins can use this feature~</p>", "admin-menu-select": "<p>[Group server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", "menu-select": "<p>[Server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>Type: {type}</p>\n<p>1. Set as default server</p>\n<p>2. View or modify url</p>\n<p>3. Delete the server</p>\n<p>4. Rename the server</p>\n<p>0. Return to server selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected server is the same as the old default server!</p>", "menu-2-prompt": "<p>The server's url: {baseUrl}</p>\n<p>Please enter the new server url:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "add-type": "<p>Please select the server type:</p>\n{server_type_list}", "add-url": "<p>Please enter the server url:</p>", "add-name": "<p>Received! Please give the server a name, no spaces allowed:</p>", "add-invalid_name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "add-success": "<p>Added successfully, the server information is as follows:</p>\n<p>[{serverName}]</p>\n<p>Type: {serverType}</p>" } } } };
52
52
 
53
53
  // src/core/locales/zh-CN.yml
54
- var zh_CN_default = { _config: { $desc: "Core 模块设置", adminUsers: "**插件管理员** 的用户id (使用 inspect 指令获取)" }, commands: { timeout: "Noah 没等到你的回复,请重试!", noah: { help: { description: "显示 Noah 帮助信息", messages: { content: "<p>帮助文档:</p>\n<a>https://docs.logthm.com/noah</a>\n<p>如无法访问该链接,请使用下方的镜像站点:</p>\n<a>https://logthm.cn/noah</a>" } } }, bind: { description: "绑定卡片", messages: { prompt: "<p>请输入你的卡号:</p>", "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", duplicate: "<p>这张卡已经被绑定啦 (︶^︶)</p>", name: "<p>收到!为这张卡取一个名字吧,不要带空格哦:</p>", invalid_name: "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", success: "<p>绑好啦,你的卡片信息如下:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "管理卡片", messages: { "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", "menu-select": "<p>[卡片管理]</p>\n{card_list}\n<p>0. 添加新卡片</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>已绑定服务器:{defaultServerName}</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的卡片与旧的默认卡片相同!</p>", "menu-2-prompt": "<p>卡号:{code}</p>\n<p>请输入新的卡号:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-2-error-invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "menu-5": "<p>请选择一个服务器:</p>\n{server_list}\n<p>q. 退出</p>", "menu-5-success": "<p>设置成功!</p>", "menu-5-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>" } }, server: { description: "管理服务器", messages: { "invalid-select": "<p>没有该选项!</p>", "no-auth": "<p>只有群管理员能使用本功能哦~</p>", quit: "<p>已退出~</p>", "admin-menu-select": "<p>[群聊服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-select": "<p>[服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>类型:{type}</p>\n<p>1. 设为默认服务器</p>\n<p>2. 查看或修改 url</p>\n<p>3. 删除该服务器</p>\n<p>4. 重命名该服务器</p>\n<p>0. 返回服务器选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>", "menu-2-prompt": "<p>该服务器的 url:{baseUrl}</p>\n<p>请输入新的服务器 url:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "add-type": "<p>请选择服务器的类型:</p>\n{server_type_list}\n<p>q. 退出</p>", "add-url": "<p>请输入服务器的 url:</p>\n<p>q. 退出</p>", "add-name": "<p>收到!为服务器取一个名字吧,不要带空格哦:</p>\n<p>q. 退出</p>", "add-invalid_name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "add-success": "<p>添加成功啦,服务器信息如下:</p>\n<p>[{serverName}]</p>\n<p>类型:{serverType}</p>" } } } };
54
+ var zh_CN_default = { _config: { $desc: "Core 模块设置", adminUsers: "**插件管理员** 的用户id (使用 inspect 指令获取)" }, commands: { timeout: "Noah 没等到你的回复,请重试!", noah: { help: { description: "显示 Noah 帮助信息", messages: { content: "<p>使用文档:</p>\n<a>https://docs.logthm.cn/noah</a>" } } }, bind: { description: "绑定卡片", messages: { prompt: "<p>请输入你的卡号:</p>", "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", duplicate: "<p>这张卡已经被绑定啦 (︶^︶)</p>", name: "<p>收到!为这张卡取一个名字吧,不要带空格哦:</p>", invalid_name: "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", success: "<p>绑好啦,你的卡片信息如下:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "管理卡片", messages: { "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", "menu-select": "<p>[卡片管理]</p>\n{card_list}\n<p>0. 添加新卡片</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>已绑定服务器:{defaultServerName}</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的卡片与旧的默认卡片相同!</p>", "menu-2-prompt": "<p>卡号:{code}</p>\n<p>请输入新的卡号:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-2-error-invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "menu-5": "<p>请选择一个服务器:</p>\n{server_list}\n<p>q. 退出</p>", "menu-5-success": "<p>设置成功!</p>", "menu-5-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>" } }, server: { description: "管理服务器", messages: { "invalid-select": "<p>没有该选项!</p>", "no-auth": "<p>只有群管理员能使用本功能哦~</p>", quit: "<p>已退出~</p>", "admin-menu-select": "<p>[群聊服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-select": "<p>[服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>类型:{type}</p>\n<p>1. 设为默认服务器</p>\n<p>2. 查看或修改 url</p>\n<p>3. 删除该服务器</p>\n<p>4. 重命名该服务器</p>\n<p>0. 返回服务器选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>", "menu-2-prompt": "<p>该服务器的 url:{baseUrl}</p>\n<p>请输入新的服务器 url:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "add-type": "<p>请选择服务器的类型:</p>\n{server_type_list}\n<p>q. 退出</p>", "add-url": "<p>请输入服务器的 url:</p>\n<p>q. 退出</p>", "add-name": "<p>收到!为服务器取一个名字吧,不要带空格哦:</p>\n<p>q. 退出</p>", "add-invalid_name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "add-success": "<p>添加成功啦,服务器信息如下:</p>\n<p>[{serverName}]</p>\n<p>类型:{serverType}</p>" } } } };
55
55
 
56
56
  // src/core/database.ts
57
57
  var database_exports = {};
@@ -287,10 +287,9 @@ function classifyCardId(input) {
287
287
  if (uidRegex.test(input)) {
288
288
  try {
289
289
  toKonamiId(input);
290
+ return "uid";
290
291
  } catch (e) {
291
- return "invalid";
292
292
  }
293
- return "uid";
294
293
  }
295
294
  const ALPHABET2 = "0123456789ABCDEFGHJKLMNPRSTUWXYZ";
296
295
  const isKonami = input.split("").every((ch) => ALPHABET2.includes(ch));
@@ -380,8 +379,8 @@ var CardService = class {
380
379
  /**
381
380
  * 根据 name 获取卡片信息
382
381
  */
383
- async getCardByName(name11) {
384
- const rows = await this.ctx.database.get(this.tableName, { name: name11 });
382
+ async getCardByName(name13) {
383
+ const rows = await this.ctx.database.get(this.tableName, { name: name13 });
385
384
  if (!rows[0]) return null;
386
385
  return {
387
386
  ...rows[0],
@@ -396,10 +395,10 @@ var CardService = class {
396
395
  * @param defaultServerId 默认服务器 ID(若没有默认服务器则为 0)
397
396
  * @returns 创建成功后包含自动填充 id 等字段的完整对象
398
397
  */
399
- async createCard(uid, code, name11, defaultServerId = 0) {
398
+ async createCard(uid, code, name13, defaultServerId = 0) {
400
399
  const data = {
401
400
  code,
402
- name: name11,
401
+ name: name13,
403
402
  defaultServerId
404
403
  };
405
404
  const res = await this.ctx.database.create(this.tableName, data);
@@ -551,8 +550,8 @@ var ServerService = class {
551
550
  /**
552
551
  * 根据名称查找服务器
553
552
  */
554
- async getServerByName(name11) {
555
- const rows = await this.ctx.database.get(this.tableName, { name: name11 });
553
+ async getServerByName(name13) {
554
+ const rows = await this.ctx.database.get(this.tableName, { name: name13 });
556
555
  return rows[0] ?? null;
557
556
  }
558
557
  /**
@@ -1023,10 +1022,10 @@ __export(sdvx_exports, {
1023
1022
  var import_koishi8 = require("koishi");
1024
1023
 
1025
1024
  // src/games/sdvx/locales/en-US.yml
1026
- var en_US_default2 = { _config: { $desc: "SDVX Module Settings", default_model: "<p>Default model value (e.g. `2024110700`)</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>" } } } };
1025
+ var en_US_default2 = { _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>" } } } };
1027
1026
 
1028
1027
  // src/games/sdvx/locales/zh-CN.yml
1029
- var zh_CN_default2 = { _config: { $desc: "SDVX 模块设置", default_model: "<p>默认的 model 值(如 `2024110700`)</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>" } }, recent: { description: "查询 SDVX 最近分数", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>" } } } };
1028
+ var zh_CN_default2 = { _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>" } }, recent: { description: "查询 SDVX 最近分数", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>" } } } };
1030
1029
 
1031
1030
  // src/games/sdvx/database.ts
1032
1031
  var database_exports2 = {};
@@ -1063,12 +1062,12 @@ var import_koishi4 = require("koishi");
1063
1062
  // src/servers/utils/xml.ts
1064
1063
  var xml2js = __toESM(require("xml2js"));
1065
1064
  var xmlToJson = /* @__PURE__ */ __name((xml) => {
1066
- return new Promise((resolve2, reject) => {
1065
+ return new Promise((resolve3, reject) => {
1067
1066
  xml2js.parseString(xml, (err, result) => {
1068
1067
  if (err) {
1069
1068
  reject(new Error("Error parsing XML: " + err));
1070
1069
  } else {
1071
- resolve2(result);
1070
+ resolve3(result);
1072
1071
  }
1073
1072
  });
1074
1073
  });
@@ -1081,12 +1080,12 @@ var SDVXService = class _SDVXService {
1081
1080
  }
1082
1081
  static instance;
1083
1082
  logger;
1084
- constructor(logger3) {
1085
- this.logger = logger3;
1083
+ constructor(logger4) {
1084
+ this.logger = logger4;
1086
1085
  }
1087
- static getInstance(logger3) {
1086
+ static getInstance(logger4) {
1088
1087
  if (!_SDVXService.instance) {
1089
- _SDVXService.instance = new _SDVXService(logger3);
1088
+ _SDVXService.instance = new _SDVXService(logger4);
1090
1089
  }
1091
1090
  return _SDVXService.instance;
1092
1091
  }
@@ -1172,12 +1171,12 @@ var IIDXService = class _IIDXService {
1172
1171
  }
1173
1172
  static instance;
1174
1173
  logger;
1175
- constructor(logger3) {
1176
- this.logger = logger3;
1174
+ constructor(logger4) {
1175
+ this.logger = logger4;
1177
1176
  }
1178
- static getInstance(logger3) {
1177
+ static getInstance(logger4) {
1179
1178
  if (!_IIDXService.instance) {
1180
- _IIDXService.instance = new _IIDXService(logger3);
1179
+ _IIDXService.instance = new _IIDXService(logger4);
1181
1180
  }
1182
1181
  return _IIDXService.instance;
1183
1182
  }
@@ -1352,12 +1351,12 @@ var SDVXService2 = class _SDVXService {
1352
1351
  }
1353
1352
  static instance;
1354
1353
  logger;
1355
- constructor(logger3) {
1356
- this.logger = logger3;
1354
+ constructor(logger4) {
1355
+ this.logger = logger4;
1357
1356
  }
1358
- static getInstance(logger3) {
1357
+ static getInstance(logger4) {
1359
1358
  if (!_SDVXService.instance) {
1360
- _SDVXService.instance = new _SDVXService(logger3);
1359
+ _SDVXService.instance = new _SDVXService(logger4);
1361
1360
  }
1362
1361
  return _SDVXService.instance;
1363
1362
  }
@@ -1802,8 +1801,28 @@ var CoreDrawer = class extends BaseDrawer {
1802
1801
  };
1803
1802
 
1804
1803
  // src/drawer/sdvx/index.ts
1805
- var import_path = require("path");
1806
1804
  var fs = __toESM(require("fs"));
1805
+
1806
+ // src/constants.ts
1807
+ var import_path = require("path");
1808
+ var ASSET_DATA_PATH = "noah_assets";
1809
+ function initConstants(ctx) {
1810
+ try {
1811
+ if (ctx.config?.asset?.data_path) {
1812
+ ASSET_DATA_PATH = ctx.config.asset.data_path;
1813
+ }
1814
+ ctx.logger("Noah").info(`Asset data path configured as: ${ASSET_DATA_PATH}`);
1815
+ } catch (error) {
1816
+ ctx.logger("Noah").error(`Failed to initialize constants: ${error.message}`);
1817
+ }
1818
+ }
1819
+ __name(initConstants, "initConstants");
1820
+ function getAssetPath(ctx, assetPath) {
1821
+ return (0, import_path.resolve)(ctx.baseDir, ASSET_DATA_PATH, "assets", assetPath);
1822
+ }
1823
+ __name(getAssetPath, "getAssetPath");
1824
+
1825
+ // src/drawer/sdvx/index.ts
1807
1826
  var SDVXDrawer = class extends BaseDrawer {
1808
1827
  constructor(ctx) {
1809
1828
  super(ctx);
@@ -1824,7 +1843,7 @@ var SDVXDrawer = class extends BaseDrawer {
1824
1843
  if (!compression) {
1825
1844
  compression = { lossless: true };
1826
1845
  }
1827
- const bgImage = await loadImage((0, import_path.resolve)(__dirname, "../../assets/sdvx/vf/main_bg.png"));
1846
+ const bgImage = await loadImage(getAssetPath(this.ctx, "assets/sdvx/vf/main_bg.png"));
1828
1847
  const canvas = new Canvas(bgImage.width, bgImage.height);
1829
1848
  const ctx = canvas.getContext("2d");
1830
1849
  ctx.imageSmoothingEnabled = true;
@@ -1845,10 +1864,10 @@ var SDVXDrawer = class extends BaseDrawer {
1845
1864
  compression = { lossless: true };
1846
1865
  }
1847
1866
  try {
1848
- const notoSansPath = (0, import_path.resolve)(__dirname, "../../assets/fonts/NotoSans-VariableFont_wdth,wght.ttf");
1849
- const slantPath = (0, import_path.resolve)(__dirname, "../../assets/fonts/Slant.ttf");
1850
- const fredokaPath = (0, import_path.resolve)(__dirname, "../../assets/fonts/FredokaOne.ttf");
1851
- const notoSansJPPath = (0, import_path.resolve)(__dirname, "../../assets/fonts/NotoSansJP-VariableFont_wght.ttf");
1867
+ const notoSansPath = getAssetPath(this.ctx, "assets/fonts/NotoSans-VariableFont_wdth,wght.ttf");
1868
+ const slantPath = getAssetPath(this.ctx, "assets/fonts/Slant.ttf");
1869
+ const fredokaPath = getAssetPath(this.ctx, "assets/fonts/FredokaOne.ttf");
1870
+ const notoSansJPPath = getAssetPath(this.ctx, "assets/fonts/NotoSansJP-VariableFont_wght.ttf");
1852
1871
  if (fs.existsSync(notoSansPath)) {
1853
1872
  FontLibrary.use("Noto Sans", notoSansPath);
1854
1873
  this.ctx.logger("SDVX-Drawer").debug("Loaded Noto Sans font successfully");
@@ -1876,7 +1895,7 @@ var SDVXDrawer = class extends BaseDrawer {
1876
1895
  } catch (error) {
1877
1896
  this.ctx.logger("SDVX-Drawer").warn(`Error loading fonts: ${error.message}`);
1878
1897
  }
1879
- const bgImage = await loadImage((0, import_path.resolve)(__dirname, "../../assets/sdvx/vf/main_bg.png"));
1898
+ const bgImage = await loadImage(getAssetPath(this.ctx, "assets/sdvx/vf/main_bg.png"));
1880
1899
  const canvas = new Canvas(bgImage.width, bgImage.height);
1881
1900
  const ctx = canvas.getContext("2d");
1882
1901
  ctx.imageSmoothingEnabled = true;
@@ -1890,7 +1909,7 @@ var SDVXDrawer = class extends BaseDrawer {
1890
1909
  ctx.font = '300 128px "Noto Sans"';
1891
1910
  ctx.fillText(options.playerName, 1451, 187);
1892
1911
  ctx.fillText(averageVF.toFixed(3), 3849, 187);
1893
- const cardBgImage = await loadImage((0, import_path.resolve)(__dirname, "../../assets/sdvx/vf/card_bg.png"));
1912
+ const cardBgImage = await loadImage(getAssetPath(this.ctx, "assets/sdvx/vf/card_bg.png"));
1894
1913
  const sortedScores = [...options.scores].sort((a, b) => b.extra.volforce - a.extra.volforce).slice(0, 50);
1895
1914
  await this.drawScoreCards(ctx, sortedScores, cardBgImage, loadImage, options.config);
1896
1915
  return this.compressImage(canvas, compression);
@@ -1916,7 +1935,7 @@ var SDVXDrawer = class extends BaseDrawer {
1916
1935
  const grades = ["D", "C", "B", "A", "A+", "AA", "AA+", "AAA", "AAA+", "S"];
1917
1936
  for (const grade of grades) {
1918
1937
  try {
1919
- const gradePath = (0, import_path.resolve)(__dirname, `../../assets/sdvx/vf/grade/Type=${grade}.png`);
1938
+ const gradePath = getAssetPath(this.ctx, `assets/sdvx/vf/grade/Type=${grade}.png`);
1920
1939
  gradeImages[grade] = await loadImage(gradePath);
1921
1940
  } catch (error) {
1922
1941
  this.ctx.logger("SDVX-Drawer").warn(`Failed to load grade image for ${grade}: ${error.message}`);
@@ -1924,7 +1943,7 @@ var SDVXDrawer = class extends BaseDrawer {
1924
1943
  }
1925
1944
  for (let i = 1; i <= 10; i++) {
1926
1945
  try {
1927
- const circlePath = (0, import_path.resolve)(__dirname, `../../assets/sdvx/vf/circle/Class=${i}.png`);
1946
+ const circlePath = getAssetPath(this.ctx, `assets/sdvx/vf/circle/Class=${i}.png`);
1928
1947
  circleImages[i] = await loadImage(circlePath);
1929
1948
  } catch (error) {
1930
1949
  this.ctx.logger("SDVX-Drawer").warn(`Failed to load circle image for class ${i}: ${error.message}`);
@@ -1932,7 +1951,7 @@ var SDVXDrawer = class extends BaseDrawer {
1932
1951
  }
1933
1952
  for (let i = 1; i <= 10; i++) {
1934
1953
  try {
1935
- const badgePath = (0, import_path.resolve)(__dirname, `../../assets/sdvx/vf/badge/Class=${i}.png`);
1954
+ const badgePath = getAssetPath(this.ctx, `assets/sdvx/vf/badge/Class=${i}.png`);
1936
1955
  vfBadges[i] = await loadImage(badgePath);
1937
1956
  } catch (error) {
1938
1957
  this.ctx.logger("SDVX-Drawer").warn(`Failed to load badge image for class ${i}: ${error.message}`);
@@ -2474,22 +2493,433 @@ async function apply9(ctx, config) {
2474
2493
  ctx.plugin(database_exports2, config.sdvx);
2475
2494
  ctx.plugin(command_exports2, config.sdvx);
2476
2495
  ctx.plugin(event_exports, config.sdvx);
2477
- const serverManager = ServerManager.getInstance();
2478
- const sdvxService = serverManager.getGameService("mao", "sdvx");
2479
- const musicService = MusicService.getInstance(config.sdvx);
2480
- const music = await musicService.getMusic(ctx, [1438, 1259]);
2481
2496
  }
2482
2497
  __name(apply9, "apply");
2483
2498
 
2499
+ // src/fun/poke/index.ts
2500
+ var poke_exports = {};
2501
+ __export(poke_exports, {
2502
+ apply: () => apply10,
2503
+ name: () => name10
2504
+ });
2505
+ var import_koishi9 = require("koishi");
2506
+ var fs2 = __toESM(require("fs"));
2507
+ var path = __toESM(require("path"));
2508
+
2509
+ // src/fun/poke/locales/zh-CN.yml
2510
+ var zh_CN_default3 = { _config: { $desc: "Poke 模块设置", interval: "最小触发间隔(毫秒)", warning: "频繁触发是否发送警告", prompt: { $desc: "警告内容", content: "消息", weight: "权重" }, messages: { $desc: "消息内容", content: "消息", weight: "权重" } }, commands: { poke: { description: "戳一戳" } } };
2511
+
2512
+ // src/fun/poke/locales/en-US.yml
2513
+ var en_US_default3 = { _config: { $desc: "Poke Module Settings", interval: "最小触发间隔(毫秒)", warning: "频繁触发是否发送警告", prompt: "警告内容", messages: { $desc: "消息内容", content: "消息内容", weight: "权重" } }, commands: { poke: { description: "poke" } } };
2514
+
2515
+ // src/fun/poke/index.ts
2516
+ var name10 = "Noah-Poke";
2517
+ function apply10(ctx, config) {
2518
+ [["en-US", en_US_default3], ["zh-CN", zh_CN_default3]].forEach(([lang, file]) => ctx.i18n.define(lang, file));
2519
+ const cache = /* @__PURE__ */ new Map();
2520
+ const pokeConfig2 = config.poke;
2521
+ const IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".webp"];
2522
+ function isImageFile(filename) {
2523
+ const ext = path.extname(filename).toLowerCase();
2524
+ return IMAGE_EXTENSIONS.includes(ext);
2525
+ }
2526
+ __name(isImageFile, "isImageFile");
2527
+ function getMimeType(filename) {
2528
+ const ext = path.extname(filename).toLowerCase();
2529
+ switch (ext) {
2530
+ case ".png":
2531
+ return "image/png";
2532
+ case ".jpg":
2533
+ case ".jpeg":
2534
+ return "image/jpeg";
2535
+ case ".gif":
2536
+ return "image/gif";
2537
+ case ".webp":
2538
+ return "image/webp";
2539
+ default:
2540
+ return "image/png";
2541
+ }
2542
+ }
2543
+ __name(getMimeType, "getMimeType");
2544
+ async function sendRandomNoahStamp(ctx2) {
2545
+ try {
2546
+ const stampsPath = getAssetPath(ctx2, "stamps/noah_stamp");
2547
+ const stampDirs = fs2.readdirSync(stampsPath).filter((dir) => dir.startsWith("stamp_"));
2548
+ if (stampDirs.length === 0) {
2549
+ return "No stamps found!";
2550
+ }
2551
+ const allStamps = [];
2552
+ for (const dir of stampDirs) {
2553
+ const stampDirPath = path.join(stampsPath, dir);
2554
+ const stampFiles = fs2.readdirSync(stampDirPath).filter((file) => file.startsWith(dir) && isImageFile(file));
2555
+ stampFiles.forEach((file) => {
2556
+ allStamps.push({
2557
+ path: path.join(stampDirPath, file),
2558
+ dirName: dir
2559
+ });
2560
+ });
2561
+ }
2562
+ if (allStamps.length === 0) {
2563
+ return "No stamps found in any directory!";
2564
+ }
2565
+ const randomStamp = allStamps[Math.floor(Math.random() * allStamps.length)];
2566
+ ctx2.logger("Noah-Poke").debug(`Selected stamp from ${randomStamp.dirName}`);
2567
+ if (!fs2.existsSync(randomStamp.path)) {
2568
+ return "Selected stamp not found!";
2569
+ }
2570
+ const imageBuffer = fs2.readFileSync(randomStamp.path);
2571
+ return import_koishi9.h.image(imageBuffer, getMimeType(randomStamp.path));
2572
+ } catch (error) {
2573
+ ctx2.logger("Noah-Poke").error(`Error sending noah stamp: ${error.message}`);
2574
+ return "Failed to send noah stamp.";
2575
+ }
2576
+ }
2577
+ __name(sendRandomNoahStamp, "sendRandomNoahStamp");
2578
+ async function sendRandomChatStamp(ctx2) {
2579
+ try {
2580
+ const stampsPath = getAssetPath(ctx2, "stamps/chat_stamp");
2581
+ const stampFiles = fs2.readdirSync(stampsPath).filter((file) => isImageFile(file));
2582
+ if (stampFiles.length === 0) {
2583
+ return "No chat stamps found!";
2584
+ }
2585
+ const randomStamp = stampFiles[Math.floor(Math.random() * stampFiles.length)];
2586
+ const stampPath = path.join(stampsPath, randomStamp);
2587
+ if (!fs2.existsSync(stampPath)) {
2588
+ return "Selected stamp not found!";
2589
+ }
2590
+ const imageBuffer = fs2.readFileSync(stampPath);
2591
+ return import_koishi9.h.image(imageBuffer, getMimeType(stampPath));
2592
+ } catch (error) {
2593
+ ctx2.logger("Noah-Poke").error(`Error sending chat stamp: ${error.message}`);
2594
+ return "Failed to send chat stamp.";
2595
+ }
2596
+ }
2597
+ __name(sendRandomChatStamp, "sendRandomChatStamp");
2598
+ ctx.command("stamp").option("type", "-t [type]").action(async ({ session, options }) => {
2599
+ if (options.type == "noah") {
2600
+ return sendRandomNoahStamp(ctx);
2601
+ } else if (options.type == "chat") {
2602
+ return sendRandomChatStamp(ctx);
2603
+ } else {
2604
+ return sendRandomChatStamp(ctx);
2605
+ }
2606
+ });
2607
+ ctx.platform("onebot").command("poke [target:user]").action(async ({ session }, target) => {
2608
+ if (!session.onebot) {
2609
+ return;
2610
+ }
2611
+ const params = { user_id: session.userId };
2612
+ if (target) {
2613
+ const [platform, id] = parsePlatform(target);
2614
+ if (platform != "onebot") {
2615
+ return;
2616
+ }
2617
+ params.user_id = id;
2618
+ }
2619
+ if (session.isDirect) {
2620
+ await session.onebot._request("friend_poke", params);
2621
+ } else {
2622
+ params["group_id"] = session.guildId;
2623
+ await session.onebot._request("group_poke", params);
2624
+ }
2625
+ });
2626
+ ctx.platform("onebot").on("notice", async (session) => {
2627
+ if (session.subtype != "poke") {
2628
+ return;
2629
+ }
2630
+ if (session.targetId != session.selfId) {
2631
+ return;
2632
+ }
2633
+ if (pokeConfig2.interval > 0 && cache.has(session.userId)) {
2634
+ const ts = cache.get(session.userId);
2635
+ if (session.timestamp - ts < pokeConfig2.interval) {
2636
+ if (pokeConfig2.warning) {
2637
+ const msg = randomMessage(pokeConfig2.prompt);
2638
+ const content = import_koishi9.h.parse(msg, session);
2639
+ session.sendQueued(content);
2640
+ }
2641
+ return;
2642
+ }
2643
+ }
2644
+ cache.set(session.userId, session.timestamp);
2645
+ if (pokeConfig2.messages.length > 0) {
2646
+ const msg = randomMessage(pokeConfig2.messages);
2647
+ const content = import_koishi9.h.parse(msg, session);
2648
+ await session.sendQueued(content);
2649
+ }
2650
+ });
2651
+ }
2652
+ __name(apply10, "apply");
2653
+ function randomMessage(messages) {
2654
+ const totalWeight = messages.reduce((sum2, cur) => sum2 + cur.weight, 0);
2655
+ const random = Math.random() * totalWeight;
2656
+ let sum = 0;
2657
+ for (const message of messages) {
2658
+ sum += message.weight;
2659
+ if (random < sum) return message.content;
2660
+ }
2661
+ }
2662
+ __name(randomMessage, "randomMessage");
2663
+ function parsePlatform(target) {
2664
+ const index = target.indexOf(":");
2665
+ const platform = target.slice(0, index);
2666
+ const id = target.slice(index + 1);
2667
+ return [platform, id];
2668
+ }
2669
+ __name(parsePlatform, "parsePlatform");
2670
+
2671
+ // src/asset/index.ts
2672
+ var asset_exports = {};
2673
+ __export(asset_exports, {
2674
+ apply: () => apply11,
2675
+ logger: () => logger3,
2676
+ name: () => name11
2677
+ });
2678
+
2679
+ // src/asset/locales/zh-CN.yml
2680
+ var zh_CN_default4 = { _config: { $desc: "Asset 模块设置", data_path: "Noah 的资源文件路径", auto_update: "是否自动检查资源更新", update_url: "资源更新的基础URL", update_interval: "检查更新的时间间隔(毫秒)", github_token: "GitHub 访问令牌,用于访问私有仓库" }, commands: { update: { messages: { success: "资源更新成功!", already_up_to_date: "资源已是最新版本,无需更新。", failed: "资源更新失败,请查看日志获取详细信息。" } } } };
2681
+
2682
+ // src/asset/locales/en-US.yml
2683
+ var en_US_default4 = { _config: { $desc: "Asset Module Settings", data_path: "Path to Noah resource files", auto_update: "Whether to automatically check for asset updates", update_url: "Base URL for asset updates", update_interval: "Time interval in milliseconds to check for updates", github_token: "GitHub access token for private repository access" }, commands: { update: { messages: { success: "Asset update successful!", already_up_to_date: "Asset is already up to date.", failed: "Asset update failed, please check the logs for more details." } } } };
2684
+
2685
+ // src/asset/index.ts
2686
+ var import_koishi10 = require("koishi");
2687
+
2688
+ // src/asset/service.ts
2689
+ var import_fs = __toESM(require("fs"));
2690
+ var import_path2 = __toESM(require("path"));
2691
+ var import_path3 = require("path");
2692
+ var import_promises = require("fs/promises");
2693
+ var import_adm_zip = __toESM(require("adm-zip"));
2694
+ var AssetService = class {
2695
+ constructor(ctx, config) {
2696
+ this.ctx = ctx;
2697
+ this.logger = ctx.logger("Noah-Asset-Service");
2698
+ this.config = config;
2699
+ this.basePath = import_path2.default.resolve(this.ctx.baseDir, this.config.data_path);
2700
+ }
2701
+ static {
2702
+ __name(this, "AssetService");
2703
+ }
2704
+ logger;
2705
+ config;
2706
+ updateTimer = null;
2707
+ basePath;
2708
+ /**
2709
+ * Initialize the asset service
2710
+ */
2711
+ async initialize() {
2712
+ this.logger.info("Initializing asset service");
2713
+ this.ensureDirectoryExists(this.basePath);
2714
+ if (this.config.auto_update) {
2715
+ await this.checkForUpdates();
2716
+ if (this.config.update_interval) {
2717
+ this.updateTimer = setInterval(() => {
2718
+ this.checkForUpdates().catch((err) => {
2719
+ this.logger.error(`Scheduled update check failed: ${err.message}`);
2720
+ });
2721
+ }, this.config.update_interval);
2722
+ }
2723
+ }
2724
+ }
2725
+ /**
2726
+ * Stop the asset service
2727
+ */
2728
+ dispose() {
2729
+ if (this.updateTimer) {
2730
+ clearInterval(this.updateTimer);
2731
+ this.updateTimer = null;
2732
+ }
2733
+ }
2734
+ /**
2735
+ * Get the latest release information from GitHub
2736
+ */
2737
+ async getLatestRelease() {
2738
+ try {
2739
+ const repoUrl = this.config.update_url.match(/github\.com\/([^/]+\/[^/]+)/);
2740
+ if (!repoUrl?.[1]) {
2741
+ throw new Error("Invalid GitHub repository URL");
2742
+ }
2743
+ const options = {
2744
+ headers: {
2745
+ "Accept": "application/vnd.github+json",
2746
+ "User-Agent": "Noah-Asset-Service"
2747
+ }
2748
+ };
2749
+ if (this.config.github_token) {
2750
+ options.headers["Authorization"] = `token ${this.config.github_token}`;
2751
+ }
2752
+ const response = await this.ctx.http.get(
2753
+ `https://api.github.com/repos/${repoUrl[1]}/releases/latest`,
2754
+ options
2755
+ );
2756
+ return response;
2757
+ } catch (error) {
2758
+ this.logger.error(`Failed to get latest release info: ${error.message}`);
2759
+ return null;
2760
+ }
2761
+ }
2762
+ /**
2763
+ * Check for asset updates and download if available
2764
+ */
2765
+ async checkForUpdates() {
2766
+ if (!this.config.update_url) {
2767
+ this.logger.warn("Update URL not configured, skipping update check");
2768
+ return false;
2769
+ }
2770
+ try {
2771
+ this.logger.info("Checking for asset updates...");
2772
+ const release = await this.getLatestRelease();
2773
+ if (!release) {
2774
+ throw new Error("Could not fetch release information");
2775
+ }
2776
+ const assetFile = release.assets.find((asset) => asset.name.startsWith("noah_assets_") && asset.name.endsWith(".zip"));
2777
+ if (!assetFile) {
2778
+ throw new Error("No asset file found in release");
2779
+ }
2780
+ const downloadPath = import_path2.default.join(this.basePath, "downloads");
2781
+ this.ensureDirectoryExists(downloadPath);
2782
+ const localPath = import_path2.default.join(downloadPath, assetFile.name);
2783
+ let shouldDownload = true;
2784
+ if (import_fs.default.existsSync(localPath)) {
2785
+ const currentTag = release.tag_name;
2786
+ const localTag = import_path2.default.basename(localPath, ".zip").replace("noah_assets_", "assets-");
2787
+ if (currentTag === localTag) {
2788
+ this.logger.info("Assets are up to date, no update needed");
2789
+ shouldDownload = false;
2790
+ }
2791
+ }
2792
+ if (shouldDownload) {
2793
+ this.logger.info(`Downloading asset ${assetFile.id} from release`);
2794
+ await this.downloadAsset(assetFile.id, localPath);
2795
+ await this.extractAssets(localPath);
2796
+ return true;
2797
+ }
2798
+ return false;
2799
+ } catch (error) {
2800
+ this.logger.error(`Failed to check for updates: ${error.message}`);
2801
+ return false;
2802
+ }
2803
+ }
2804
+ /**
2805
+ * Force an immediate update check
2806
+ */
2807
+ async forceUpdate() {
2808
+ this.logger.info("Forcing asset update");
2809
+ return this.checkForUpdates();
2810
+ }
2811
+ /**
2812
+ * Download an asset by its ID
2813
+ */
2814
+ async downloadAsset(assetId, destination) {
2815
+ this.logger.info(`Downloading asset ${assetId} to ${destination}`);
2816
+ try {
2817
+ const repoUrl = this.config.update_url.match(/github\.com\/([^/]+\/[^/]+)/);
2818
+ if (!repoUrl?.[1]) {
2819
+ throw new Error("Invalid GitHub repository URL");
2820
+ }
2821
+ const assetUrl = `https://api.github.com/repos/${repoUrl[1]}/releases/assets/${assetId}`;
2822
+ const options = {
2823
+ headers: {
2824
+ "User-Agent": "Noah-Asset-Service",
2825
+ "Accept": "application/octet-stream",
2826
+ "X-GitHub-Api-Version": "2022-11-28"
2827
+ },
2828
+ responseType: "arraybuffer",
2829
+ maxRedirects: 0
2830
+ // Don't auto-follow redirects
2831
+ };
2832
+ if (this.config.github_token) {
2833
+ options.headers["Authorization"] = `token ${this.config.github_token}`;
2834
+ }
2835
+ try {
2836
+ const response = await this.ctx.http.get(assetUrl, options);
2837
+ import_fs.default.writeFileSync(destination, Buffer.from(response));
2838
+ this.logger.info(`Download complete: ${destination}`);
2839
+ } catch (error) {
2840
+ if (error.response?.status === 302) {
2841
+ const redirectUrl = error.response.headers.location;
2842
+ this.logger.info(`Following redirect to ${redirectUrl}`);
2843
+ const redirectResponse = await this.ctx.http.get(redirectUrl, {
2844
+ ...options,
2845
+ maxRedirects: 5
2846
+ // Allow some redirects for the actual download
2847
+ });
2848
+ import_fs.default.writeFileSync(destination, Buffer.from(redirectResponse.data));
2849
+ this.logger.info(`Download complete: ${destination}`);
2850
+ } else {
2851
+ throw error;
2852
+ }
2853
+ }
2854
+ } catch (error) {
2855
+ this.logger.error(`Download failed: ${error.message}`);
2856
+ if (error.response) {
2857
+ this.logger.error(`Response status: ${error.response.status}`);
2858
+ this.logger.error(`Response headers: ${JSON.stringify(error.response.headers, null, 2)}`);
2859
+ }
2860
+ throw error;
2861
+ }
2862
+ }
2863
+ /**
2864
+ * Extract the assets from the downloaded zip file
2865
+ */
2866
+ async extractAssets(archivePath) {
2867
+ const extractPath = (0, import_path3.resolve)(this.basePath, "assets");
2868
+ await (0, import_promises.mkdir)(extractPath, { recursive: true });
2869
+ this.logger.info(`Extracting assets to ${extractPath}`);
2870
+ const zip = new import_adm_zip.default(archivePath);
2871
+ zip.extractAllTo(extractPath, true);
2872
+ }
2873
+ /**
2874
+ * Ensure a directory exists
2875
+ */
2876
+ ensureDirectoryExists(dir) {
2877
+ if (!import_fs.default.existsSync(dir)) {
2878
+ this.logger.info(`Creating directory: ${dir}`);
2879
+ import_fs.default.mkdirSync(dir, { recursive: true });
2880
+ }
2881
+ }
2882
+ };
2883
+
2884
+ // src/asset/index.ts
2885
+ var name11 = "Noah-Asset";
2886
+ var logger3 = new import_koishi10.Logger("Noah-Asset");
2887
+ function apply11(ctx, config) {
2888
+ [["en-US", en_US_default4], ["zh-CN", zh_CN_default4]].forEach(([lang, file]) => ctx.i18n.define(lang, file));
2889
+ const assetConfig2 = config.asset;
2890
+ logger3.info(`Asset path: ${assetConfig2.data_path}`);
2891
+ const assetService = new AssetService(ctx, assetConfig2);
2892
+ assetService.initialize().catch((err) => {
2893
+ logger3.error(`Failed to initialize asset service: ${err.message}`);
2894
+ });
2895
+ ctx.command("update").action(async ({ session }) => {
2896
+ try {
2897
+ const updated = await assetService.forceUpdate();
2898
+ if (updated) {
2899
+ return session.text(".success");
2900
+ } else {
2901
+ return session.text(".already_up_to_date");
2902
+ }
2903
+ } catch (error) {
2904
+ logger3.error(`Update command failed: ${error.message}`);
2905
+ return session.text(".failed");
2906
+ }
2907
+ });
2908
+ ctx.on("dispose", () => {
2909
+ assetService.dispose();
2910
+ });
2911
+ }
2912
+ __name(apply11, "apply");
2913
+
2484
2914
  // src/config.ts
2485
- var import_koishi11 = require("koishi");
2915
+ var import_koishi15 = require("koishi");
2486
2916
 
2487
2917
  // src/core/config.ts
2488
- var import_koishi9 = require("koishi");
2489
- var coreConfig = import_koishi9.Schema.object({
2490
- adminUsers: import_koishi9.Schema.union([
2491
- import_koishi9.Schema.array(String),
2492
- import_koishi9.Schema.transform(String, (adminUsers) => [adminUsers])
2918
+ var import_koishi11 = require("koishi");
2919
+ var coreConfig = import_koishi11.Schema.object({
2920
+ adminUsers: import_koishi11.Schema.union([
2921
+ import_koishi11.Schema.array(String),
2922
+ import_koishi11.Schema.transform(String, (adminUsers) => [adminUsers])
2493
2923
  ])
2494
2924
  }).i18n({
2495
2925
  "en-US": en_US_default._config,
@@ -2497,31 +2927,72 @@ var coreConfig = import_koishi9.Schema.object({
2497
2927
  });
2498
2928
 
2499
2929
  // src/games/sdvx/config.ts
2500
- var import_koishi10 = require("koishi");
2501
- var sdvxConfig = import_koishi10.Schema.object({
2502
- default_model: import_koishi10.Schema.string().default("2024110700"),
2503
- sdvx_data_url: import_koishi10.Schema.string().required()
2930
+ var import_koishi12 = require("koishi");
2931
+ var sdvxConfig = import_koishi12.Schema.object({
2932
+ default_model: import_koishi12.Schema.string().default("2024110700"),
2933
+ sdvx_data_url: import_koishi12.Schema.string().required()
2504
2934
  }).i18n({
2505
2935
  "en-US": en_US_default2._config,
2506
2936
  "zh-CN": zh_CN_default2._config
2507
2937
  });
2508
2938
 
2939
+ // src/fun/poke/config.ts
2940
+ var import_koishi13 = require("koishi");
2941
+ var pokeConfig = import_koishi13.Schema.object({
2942
+ interval: import_koishi13.Schema.number().default(1e3).step(100),
2943
+ warning: import_koishi13.Schema.boolean().default(false),
2944
+ prompt: import_koishi13.Schema.array(
2945
+ import_koishi13.Schema.object({
2946
+ content: import_koishi13.Schema.string().required(),
2947
+ weight: import_koishi13.Schema.number().min(0).max(100).default(50)
2948
+ })
2949
+ ).role("table"),
2950
+ messages: import_koishi13.Schema.array(
2951
+ import_koishi13.Schema.object({
2952
+ content: import_koishi13.Schema.string().required(),
2953
+ weight: import_koishi13.Schema.number().min(0).max(100).default(50)
2954
+ })
2955
+ ).role("table")
2956
+ }).i18n({
2957
+ "en-US": en_US_default3._config,
2958
+ "zh-CN": zh_CN_default3._config
2959
+ });
2960
+
2961
+ // src/asset/config.ts
2962
+ var import_koishi14 = require("koishi");
2963
+ var assetConfig = import_koishi14.Schema.object({
2964
+ data_path: import_koishi14.Schema.string().default("noah_assets"),
2965
+ auto_update: import_koishi14.Schema.boolean().default(true),
2966
+ update_url: import_koishi14.Schema.string().default("https://github.com/logthm/noah/releases/latest/download/"),
2967
+ update_interval: import_koishi14.Schema.number().default(24 * 60 * 60 * 1e3),
2968
+ // 24 hours in milliseconds
2969
+ github_token: import_koishi14.Schema.string().description("GitHub token for accessing private repositories").role("secret")
2970
+ }).i18n({
2971
+ "en-US": en_US_default4._config,
2972
+ "zh-CN": zh_CN_default4._config
2973
+ });
2974
+
2509
2975
  // src/config.ts
2510
- var Config = import_koishi11.Schema.object({
2976
+ var Config = import_koishi15.Schema.object({
2511
2977
  core: coreConfig,
2512
- sdvx: sdvxConfig
2978
+ sdvx: sdvxConfig,
2979
+ poke: pokeConfig,
2980
+ asset: assetConfig
2513
2981
  });
2514
2982
 
2515
2983
  // src/index.ts
2516
- var name10 = "noah";
2984
+ var name12 = "noah";
2517
2985
  var inject3 = ["database", "skia"];
2518
- function apply10(ctx, config) {
2986
+ function apply12(ctx, config) {
2987
+ initConstants(ctx);
2519
2988
  ctx.plugin(core_exports, config);
2520
2989
  ctx.plugin(sdvx_exports, config);
2521
2990
  ctx.plugin(servers_exports, config);
2522
2991
  ctx.plugin(drawer_exports, config);
2992
+ ctx.plugin(poke_exports, config);
2993
+ ctx.plugin(asset_exports, config);
2523
2994
  }
2524
- __name(apply10, "apply");
2995
+ __name(apply12, "apply");
2525
2996
  // Annotate the CommonJS export names for ESM import in node:
2526
2997
  0 && (module.exports = {
2527
2998
  Config,
@@ -1,3 +1,4 @@
1
+ import { MessageReply } from "../fun/poke/types";
1
2
  export interface BaseConfig {
2
3
  }
3
4
  export interface CoreConfig extends BaseConfig {
@@ -7,7 +8,22 @@ export interface SDVXConfig extends BaseConfig {
7
8
  default_model: string;
8
9
  sdvx_data_url: string;
9
10
  }
11
+ export interface PokeConfig extends BaseConfig {
12
+ interval?: number;
13
+ warning?: boolean;
14
+ prompt?: MessageReply[];
15
+ messages?: MessageReply[];
16
+ }
17
+ export interface AssetConfig extends BaseConfig {
18
+ data_path: string;
19
+ auto_update?: boolean;
20
+ update_url?: string;
21
+ update_interval?: number;
22
+ github_token?: string;
23
+ }
10
24
  export interface AppConfig {
11
25
  core: CoreConfig;
12
26
  sdvx: SDVXConfig;
27
+ poke: PokeConfig;
28
+ asset: AssetConfig;
13
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-noah",
3
- "version": "1.0.19",
3
+ "version": "1.1.2",
4
4
  "contributors": [
5
5
  "Logthm <logthm@outlook.com>"
6
6
  ],
@@ -21,6 +21,8 @@
21
21
  "koishi": "^4.18.7"
22
22
  },
23
23
  "dependencies": {
24
+ "adm-zip": "^0.5.16",
25
+ "koishi-plugin-adapter-onebot": "^6.8.0",
24
26
  "sharp": "^0.33.5",
25
27
  "xml2js": "^0.6.2"
26
28
  },
@@ -42,6 +44,7 @@
42
44
  },
43
45
  "devDependencies": {
44
46
  "@ltxhhz/koishi-plugin-skia-canvas": "^0.0.8",
47
+ "@types/adm-zip": "^0",
45
48
  "@types/xml2js": "^0"
46
49
  }
47
50
  }
File without changes