@karinjs/adapter-qqbot 1.0.1

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,134 @@
1
+ /** 机器人发送模式
2
+ * - 0: 直接发送
3
+ * - 1: 原生 Markdown
4
+ * - 3: 旧图文模板 Markdown
5
+ * - 4: 纯文模板 Markdown
6
+ * - 5: 自定义处理
7
+ */
8
+ export type SendMode = 0 | 1 | 3 | 4 | 5;
9
+ /**
10
+ * 全局配置类型定义
11
+ */
12
+ export interface GlobalCfgType {
13
+ /** 获取调用凭证的 API 地址 */
14
+ accessTokenApi: string;
15
+ /** 沙盒环境 API 地址 */
16
+ sandBoxApi: string;
17
+ /** 正式环境 API 地址 */
18
+ qqBotApi: string;
19
+ /** 是否开启沙盒环境 */
20
+ sandBox: boolean;
21
+ /** 机器人发送模式
22
+ * - 0: 直接发送
23
+ * - 1: 原生 Markdown
24
+ * - 3: 旧图文模板 Markdown
25
+ * - 4: 纯文模板 Markdown
26
+ * - 5: 自定义处理
27
+ */
28
+ sendMode: SendMode;
29
+ /** 是否开启频道消息 */
30
+ guild: boolean;
31
+ /** 频道机器人模式 0-公域机器人 1-私域机器人 */
32
+ guildMode: 0 | 1;
33
+ /** 机器人 Markdown 模板 ID,仅在 sendMode 为 3 或 4 时有效 */
34
+ templateId: string;
35
+ /** 机器人旧图文模板 Markdown 配置 */
36
+ oldTemplate: {
37
+ /** 开头文字的键 */
38
+ textStartKey: string;
39
+ /** 图片描述的键 */
40
+ imgDescKey: string;
41
+ /** 图片地址的键 */
42
+ imgUrlKey: string;
43
+ /** 结尾文字的键 */
44
+ textEndKey: string;
45
+ };
46
+ /** 机器人纯文模板 Markdown 配置,10个文本键 */
47
+ textTemplate: string[];
48
+ /** 文本中的 URL 转二维码白名单,配置后将不转换这些 URL 为二维码 */
49
+ exclude: string[];
50
+ /** 接受到消息后对文本进行表达式处理,优先级高于全局配置 */
51
+ regex: Array<{
52
+ /** 匹配的正则表达式 */
53
+ reg: string;
54
+ /** 替换为的内容 */
55
+ rep: string;
56
+ }>;
57
+ }
58
+ /**
59
+ * 账号配置类型定义
60
+ */
61
+ export interface AccountCfgType extends GlobalCfgType {
62
+ /** 机器人 AppID */
63
+ appId: string;
64
+ /** 机器人 AppSecret */
65
+ secret: string;
66
+ }
67
+ /**
68
+ * 配置类型定义
69
+ */
70
+ export interface ConfigType {
71
+ /**
72
+ * 全局默认配置
73
+ */
74
+ default: GlobalCfgType;
75
+ /** 账号配置列表 */
76
+ accounts: Record<string, AccountCfgType>;
77
+ }
78
+ declare class Cfg {
79
+ /** 配置文件跟路径 */
80
+ dir: string;
81
+ /** 默认配置文件根路径 */
82
+ defdir: string;
83
+ /** 缓存 不经常用的不建议缓存 */
84
+ change: Map<string, any>;
85
+ /** 监听文件 */
86
+ watcher: Map<string, any>;
87
+ constructor();
88
+ /** 初始化配置 */
89
+ initCfg(): Promise<void>;
90
+ /**
91
+ * 更新yaml文件
92
+ * @param filePath - 文件路径
93
+ * @param settings - 设置项
94
+ */
95
+ updateYaml(filePath: string, settings: {
96
+ /** 键路径 */
97
+ key: string;
98
+ /** 要写入的 */
99
+ val: any;
100
+ /** 需要写入的注释 */
101
+ comment: string;
102
+ /** 是否添加到顶部 否则添加到同一行 */
103
+ type: boolean;
104
+ }[]): void;
105
+ /**
106
+ * 基本配置
107
+ */
108
+ get Config(): ConfigType;
109
+ /**
110
+ * 获取指定Bot配置
111
+ * @param {string} appID - Bot的AppID
112
+ */
113
+ getBotConfig(appID: string): AccountCfgType | null;
114
+ /**
115
+ * package
116
+ */
117
+ get package(): any;
118
+ /**
119
+ * 获取配置yaml
120
+ */
121
+ getYaml(type: 'defSet' | 'config', name: string, isWatch?: boolean): any;
122
+ /**
123
+ * 监听配置文件
124
+ * @param {'defSet'|'config'} type 类型
125
+ * @param {string} name 文件名称 不带后缀
126
+ * @param {string} file 文件路径
127
+ */
128
+ watch(type: 'defSet' | 'config', name: string, file: string): Promise<true | undefined>;
129
+ }
130
+ /**
131
+ * 配置文件
132
+ */
133
+ export declare const config: Cfg;
134
+ export {};
@@ -0,0 +1,176 @@
1
+ import fs from 'fs';
2
+ import Yaml from 'yaml';
3
+ import chokidar from 'node-karin/chokidar';
4
+ import { dirPath, basename } from '../utils/index.js';
5
+ import { logger, YamlEditor } from 'node-karin';
6
+ class Cfg {
7
+ /** 配置文件跟路径 */
8
+ dir;
9
+ /** 默认配置文件根路径 */
10
+ defdir;
11
+ /** 缓存 不经常用的不建议缓存 */
12
+ change;
13
+ /** 监听文件 */
14
+ watcher;
15
+ constructor() {
16
+ this.dir = `./config/plugin/${basename}`;
17
+ this.defdir = `${dirPath}/config`;
18
+ this.change = new Map();
19
+ this.watcher = new Map();
20
+ this.initCfg();
21
+ }
22
+ /** 初始化配置 */
23
+ async initCfg() {
24
+ /** 读取默认配置的所有yaml */
25
+ const files = fs.readdirSync(this.defdir).filter(file => file.endsWith('.yaml'));
26
+ for (const file of files) {
27
+ const dirPath = `${this.dir}/${file}`;
28
+ const defPath = `${this.defdir}/${file}`;
29
+ if (!fs.existsSync(dirPath))
30
+ fs.copyFileSync(defPath, dirPath);
31
+ }
32
+ // this.updateYaml(`${this.dir}/config.yaml`, [
33
+ // { key: 'a', val: 'value', comment: '实例配置1', type: true },
34
+ // { key: 'b.c', val: 'Value', comment: '实例配置2', type: true },
35
+ // ])
36
+ }
37
+ /**
38
+ * 更新yaml文件
39
+ * @param filePath - 文件路径
40
+ * @param settings - 设置项
41
+ */
42
+ updateYaml(filePath, settings) {
43
+ let yaml = new YamlEditor(filePath);
44
+ /** 先添加内容 */
45
+ settings.forEach(({ key, val }) => {
46
+ try {
47
+ if (!yaml.has(key))
48
+ yaml.set(key, val);
49
+ }
50
+ catch (error) {
51
+ logger.error(`[common] 更新yaml文件时出错:${error.stack || error.message || error}`);
52
+ }
53
+ });
54
+ /** 先保存 */
55
+ yaml.save();
56
+ /** 重新解析 再次写入注释 直接写入注释会报错 写入的不是node节点模式 */
57
+ yaml = new YamlEditor(filePath);
58
+ settings.forEach(({ key, comment, type }) => {
59
+ try {
60
+ yaml.comment(key, comment, type);
61
+ }
62
+ catch (error) {
63
+ logger.error(`[common] 更新yaml文件时出错:${error.stack || error.message || error}`);
64
+ }
65
+ });
66
+ yaml.save();
67
+ }
68
+ /**
69
+ * 基本配置
70
+ */
71
+ get Config() {
72
+ const key = 'change.config';
73
+ const res = this.change.get(key);
74
+ /** 取缓存 */
75
+ if (res)
76
+ return res;
77
+ /** 取配置 */
78
+ const config = this.getYaml('config', 'config', true);
79
+ const defSet = this.getYaml('defSet', 'config', false);
80
+ const data = {
81
+ ...defSet,
82
+ ...config,
83
+ default: { ...defSet?.default, ...config?.default },
84
+ };
85
+ /** 缓存 */
86
+ this.change.set(key, data);
87
+ return data;
88
+ }
89
+ /**
90
+ * 获取指定Bot配置
91
+ * @param {string} appID - Bot的AppID
92
+ */
93
+ getBotConfig(appID) {
94
+ if (!appID)
95
+ throw new Error('appID不能为空');
96
+ const key = `change.config.${appID}`;
97
+ const res = this.change.get(key);
98
+ /** 取缓存 */
99
+ if (res)
100
+ return res;
101
+ /** 所有配置 */
102
+ const allCfg = this.Config;
103
+ /** 取不到 */
104
+ if (!allCfg?.accounts?.[appID])
105
+ return null;
106
+ /** 单个账号配置 */
107
+ const botCfg = allCfg.accounts[appID];
108
+ /** 全局默认配置 */
109
+ const defCfg = allCfg.default;
110
+ return {
111
+ ...defCfg,
112
+ ...botCfg,
113
+ sendMode: Number(botCfg.sendMode) || defCfg.sendMode,
114
+ regex: Array.isArray(botCfg.regex) ? botCfg.regex : defCfg.regex,
115
+ };
116
+ }
117
+ /**
118
+ * package
119
+ */
120
+ get package() {
121
+ const data = fs.readFileSync(dirPath + '/package.json', 'utf8');
122
+ const pkg = JSON.parse(data);
123
+ return pkg;
124
+ }
125
+ /**
126
+ * 获取配置yaml
127
+ */
128
+ getYaml(type, name, isWatch = false) {
129
+ /** 文件路径 */
130
+ const file = type === 'defSet' ? `${this.defdir}/${name}.yaml` : `${this.dir}/${name}.yaml`;
131
+ /** 读取文件 */
132
+ const data = Yaml.parse(fs.readFileSync(file, 'utf8'));
133
+ /** 监听文件 */
134
+ if (isWatch)
135
+ this.watch(type, name, file);
136
+ return data;
137
+ }
138
+ /**
139
+ * 监听配置文件
140
+ * @param {'defSet'|'config'} type 类型
141
+ * @param {string} name 文件名称 不带后缀
142
+ * @param {string} file 文件路径
143
+ */
144
+ async watch(type, name, file) {
145
+ const key = `change.${name}`;
146
+ /** 已经监听过了 */
147
+ const res = this.change.get(key);
148
+ if (res)
149
+ return true;
150
+ /** 监听文件 */
151
+ const watcher = chokidar.watch(file);
152
+ /** 监听文件变化 */
153
+ watcher.on('change', () => {
154
+ this.change.delete(key);
155
+ logger.mark(`[修改配置文件][${type}][${name}]`);
156
+ /** 文件修改后调用对应的方法 请自行使用 */
157
+ // switch (`change_${name}`) {
158
+ // case 'change_App':
159
+ // this.change_App()
160
+ // break
161
+ // case 'change_config':
162
+ // this.change_config()
163
+ // break
164
+ // case 'change_group':
165
+ // this.change_group()
166
+ // break
167
+ // }
168
+ });
169
+ /** 缓存 防止重复监听 */
170
+ this.watcher.set(key, watcher);
171
+ }
172
+ }
173
+ /**
174
+ * 配置文件
175
+ */
176
+ export const config = new Cfg();
@@ -0,0 +1,5 @@
1
+ /** 插件包绝对路径 */
2
+ declare const dirPath: string;
3
+ /** 插件包的名称 */
4
+ declare const basename: string;
5
+ export { dirPath, basename };
@@ -0,0 +1,9 @@
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
3
+ /** 当前文件的绝对路径 */
4
+ const filePath = fileURLToPath(import.meta.url).replace(/\\/g, '/');
5
+ /** 插件包绝对路径 */
6
+ const dirPath = path.resolve(filePath, '../../../');
7
+ /** 插件包的名称 */
8
+ const basename = path.basename(dirPath);
9
+ export { dirPath, basename };
@@ -0,0 +1,3 @@
1
+ export * from './dir.js';
2
+ export * from './common.js';
3
+ export * from './config.js';
@@ -0,0 +1,3 @@
1
+ export * from './dir.js';
2
+ export * from './common.js';
3
+ export * from './config.js';
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@karinjs/adapter-qqbot",
3
+ "version": "1.0.1",
4
+ "author": "shijin",
5
+ "type": "module",
6
+ "description": "karin plugin template",
7
+ "homepage": "https://github.com/KarinJS/karin-plugin-adapter-qqbot",
8
+ "bugs": {
9
+ "url": "https://github.com/KarinJS/karin-plugin-adapter-qqbot/issues"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/KarinJS/karin-plugin-adapter-qqbot.git"
14
+ },
15
+ "main": "lib/index.js",
16
+ "types": "lib/index.d.ts",
17
+ "scripts": {
18
+ "build": "tsc --project tsconfig.json && tsc-alias -p tsconfig.json",
19
+ "pub": "npm publish --access public"
20
+ },
21
+ "dependencies": {
22
+ "@karinjs/geturls": "^1.0.2",
23
+ "got": "^14.4.1",
24
+ "jimp": "^0.22.12",
25
+ "qrcode": "^1.5.3",
26
+ "silk-wasm": "^3.6.1"
27
+ },
28
+ "karin": {
29
+ "apps": [],
30
+ "outDir": "lib",
31
+ "rootDir": "src"
32
+ },
33
+ "files": [
34
+ "/lib/**/*.js",
35
+ "/lib/**/*.d.ts",
36
+ "/config/*.yaml",
37
+ "LICENSE",
38
+ "package.json",
39
+ "README.md"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public",
43
+ "registry": "https://registry.npmjs.org"
44
+ }
45
+ }