@karinjs/plugin-basic 1.2.0 → 1.3.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.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 shijin
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 shijin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,31 +1,31 @@
1
- ## 安装插件
2
-
3
- ```bash
4
- pnpm add @karinjs/plugin-basic -w
5
- ```
6
-
7
- ## 在 webui 安装
8
-
9
- 插件市场 -> `@karinjs/plugin-basic` -> 安装
10
-
11
- ## 基本指令
12
-
13
- ```
14
- # 关机
15
- ```
16
-
17
- ```
18
- # 重启
19
- ```
20
-
21
- ```
22
- # 状态
23
- ```
24
-
25
- ```
26
- # 插件列表
27
- ```
28
-
29
- ```
30
- #web登录
31
- ```
1
+ ## 安装插件
2
+
3
+ ```bash
4
+ pnpm add @karinjs/plugin-basic -w
5
+ ```
6
+
7
+ ## 在 webui 安装
8
+
9
+ 插件市场 -> `@karinjs/plugin-basic` -> 安装
10
+
11
+ ## 基本指令
12
+
13
+ ```
14
+ # 关机
15
+ ```
16
+
17
+ ```
18
+ # 重启
19
+ ```
20
+
21
+ ```
22
+ # 状态
23
+ ```
24
+
25
+ ```
26
+ # 插件列表
27
+ ```
28
+
29
+ ```
30
+ #web登录
31
+ ```
@@ -0,0 +1,6 @@
1
+ import * as node_karin from 'node-karin';
2
+
3
+ declare const logViewer: node_karin.Command<keyof node_karin.MessageEventMap>;
4
+ declare const errorLogViewer: node_karin.Command<keyof node_karin.MessageEventMap>;
5
+
6
+ export { errorLogViewer, logViewer };
@@ -0,0 +1,229 @@
1
+ import {
2
+ render
3
+ } from "../chunk-QUWYQJAF.js";
4
+
5
+ // src/apps/logger.ts
6
+ import fs from "fs";
7
+ import path from "path";
8
+ import { karin, logger } from "node-karin";
9
+ var ansiToHtml = (text) => {
10
+ if (!text) return "";
11
+ const ESC = "\x1B";
12
+ const ansiRegex = new RegExp(`${ESC}\\[([0-9;]+)m`, "g");
13
+ const escapeHtml = (str) => str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
14
+ let result = "";
15
+ let lastIndex = 0;
16
+ let openSpan = "";
17
+ const colorMap = {
18
+ 30: "#020617",
19
+ 31: "#ef4444",
20
+ 32: "#22c55e",
21
+ 33: "#eab308",
22
+ 34: "#3b82f6",
23
+ 35: "#ec4899",
24
+ 36: "#06b6d4",
25
+ 37: "#e5e7eb",
26
+ 90: "#6b7280",
27
+ 91: "#f97373",
28
+ 92: "#4ade80",
29
+ 93: "#fde047",
30
+ 94: "#60a5fa",
31
+ 95: "#a855f7",
32
+ 96: "#38bdf8",
33
+ 97: "#f9fafb"
34
+ };
35
+ text.replace(ansiRegex, (match, codesStr, offset) => {
36
+ const chunk = text.slice(lastIndex, offset);
37
+ if (chunk) {
38
+ result += escapeHtml(chunk);
39
+ }
40
+ lastIndex = offset + match.length;
41
+ const codes = codesStr.split(";").map((n) => Number(n) || 0);
42
+ if (openSpan) {
43
+ result += "</span>";
44
+ openSpan = "";
45
+ }
46
+ if (codes.includes(0) || codes.includes(39)) {
47
+ return "";
48
+ }
49
+ if (codes[0] === 38 && codes[1] === 2 && codes.length >= 5) {
50
+ const r = codes[2];
51
+ const g = codes[3];
52
+ const b = codes[4];
53
+ openSpan = `color: rgb(${r}, ${g}, ${b})`;
54
+ result += `<span style="${openSpan}">`;
55
+ return "";
56
+ }
57
+ const colorCode = codes.find((c) => colorMap[c]);
58
+ if (colorCode !== void 0) {
59
+ const color = colorMap[colorCode];
60
+ openSpan = `color: ${color}`;
61
+ result += `<span style="${openSpan}">`;
62
+ return "";
63
+ }
64
+ return "";
65
+ });
66
+ const tail = text.slice(lastIndex);
67
+ if (tail) {
68
+ result += escapeHtml(tail);
69
+ }
70
+ if (openSpan) {
71
+ result += "</span>";
72
+ }
73
+ return result;
74
+ };
75
+ var trimEmptyLines = (text) => {
76
+ const lines = text.split("\n");
77
+ while (lines.length && !lines[0].trim()) lines.shift();
78
+ while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
79
+ return lines.join("\n");
80
+ };
81
+ var groupLogLines = (lines) => {
82
+ const groups = [];
83
+ let current = [];
84
+ const isNewEntry = (line) => {
85
+ const trimmed = line.trim();
86
+ if (!trimmed) return false;
87
+ return /^\[\d{2}:\d{2}:\d{2}\.\d{3}\]\[[A-Z]+]/.test(trimmed);
88
+ };
89
+ for (const line of lines) {
90
+ if (isNewEntry(line)) {
91
+ if (current.length) groups.push(current);
92
+ current = [line];
93
+ } else {
94
+ if (current.length) {
95
+ current.push(line);
96
+ } else {
97
+ current = [line];
98
+ }
99
+ }
100
+ }
101
+ if (current.length) groups.push(current);
102
+ return groups.map((item) => item.join("\n"));
103
+ };
104
+ var getTodayLogs = async (limit = 50) => {
105
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
106
+ const logDir = path.join(process.cwd(), "@karinjs", "logs");
107
+ const logFile = path.join(logDir, `logger.${today}.log`);
108
+ try {
109
+ if (!fs.existsSync(logFile)) {
110
+ const files = fs.readdirSync(logDir).filter((f) => f.startsWith("logger.") && f.endsWith(".log") && !f.includes("error")).sort().reverse();
111
+ if (files.length === 0) {
112
+ return ["\u6682\u65E0\u65E5\u5FD7\u8BB0\u5F55"];
113
+ }
114
+ const latestLog = path.join(logDir, files[0]);
115
+ const content2 = fs.readFileSync(latestLog, "utf-8");
116
+ const lines2 = content2.split("\n").filter((line) => line.trim());
117
+ const groups2 = groupLogLines(lines2);
118
+ return groups2.slice(-limit).reverse();
119
+ }
120
+ const content = fs.readFileSync(logFile, "utf-8");
121
+ const lines = content.split("\n").filter((line) => line.trim());
122
+ const groups = groupLogLines(lines);
123
+ return groups.slice(-limit).reverse();
124
+ } catch (error) {
125
+ logger.error("\u8BFB\u53D6\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:", error);
126
+ return ["\u8BFB\u53D6\u65E5\u5FD7\u5931\u8D25"];
127
+ }
128
+ };
129
+ var getErrorLogs = async (limit = 50) => {
130
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
131
+ const errorDir = path.join(process.cwd(), "@karinjs", "logs", "error");
132
+ if (!fs.existsSync(errorDir)) {
133
+ return [];
134
+ }
135
+ let logFile = null;
136
+ try {
137
+ const todayLoggerError = path.join(errorDir, `logger.error.${today}.log`);
138
+ const todayError = path.join(errorDir, `error.${today}.log`);
139
+ if (fs.existsSync(todayLoggerError)) {
140
+ logFile = todayLoggerError;
141
+ } else if (fs.existsSync(todayError)) {
142
+ logFile = todayError;
143
+ } else {
144
+ const files = fs.readdirSync(errorDir).filter((f) => f.endsWith(".log")).sort().reverse();
145
+ if (files.length) {
146
+ logFile = path.join(errorDir, files[0]);
147
+ }
148
+ }
149
+ if (!logFile) return [];
150
+ const content = fs.readFileSync(logFile, "utf-8");
151
+ const lines = content.split("\n").filter((line) => line.trim());
152
+ const groups = groupLogLines(lines);
153
+ return groups.slice(-limit).reverse();
154
+ } catch (error) {
155
+ logger.error("\u8BFB\u53D6\u9519\u8BEF\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:", error);
156
+ return [];
157
+ }
158
+ };
159
+ var parseLogLine = (line) => {
160
+ const [firstLine, ...rest] = line.split("\n");
161
+ let time = "";
162
+ let levelRaw = "INFO";
163
+ const timeMatch = firstLine.match(/^\[(\d{2}:\d{2}:\d{2}\.\d{3})]/);
164
+ const levelMatch = firstLine.match(/\[([A-Z]+)]/);
165
+ if (timeMatch) time = timeMatch[1];
166
+ if (levelMatch) levelRaw = levelMatch[1];
167
+ const levelKey = levelRaw.toLowerCase();
168
+ const level = levelKey === "erro" ? "error" : levelKey;
169
+ const messageHead = firstLine.replace(/^\[\d{2}:\d{2}:\d{2}\.\d{3}]\[[A-Z]+]\s*/, "");
170
+ const messageTail = rest.length ? "\n" + rest.join("\n") : "";
171
+ const fullMessage = trimEmptyLines(`${messageHead}${messageTail}`);
172
+ const plainMessage = fullMessage.replace(/\u001b\[[0-9;]+m/g, "");
173
+ return {
174
+ time,
175
+ level,
176
+ message: plainMessage,
177
+ messageHtml: ansiToHtml(fullMessage)
178
+ };
179
+ };
180
+ var logViewer = karin.command(/^#日志\s*(\d+)?$/, async (e) => {
181
+ const match = e.msg.match(/^#日志\s*(\d+)?$/);
182
+ let limit = match && match[1] ? Number(match[1]) : 50;
183
+ if (!Number.isFinite(limit) || limit <= 0) limit = 50;
184
+ if (limit > 200) limit = 200;
185
+ const logs = await getTodayLogs(limit);
186
+ const parsedLogs = logs.map(parseLogLine);
187
+ try {
188
+ const img = await render("logger/index", {
189
+ logs: parsedLogs,
190
+ total: parsedLogs.length,
191
+ date: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN")
192
+ });
193
+ await e.reply(img);
194
+ return true;
195
+ } catch (error) {
196
+ logger.error("\u6E32\u67D3\u65E5\u5FD7\u5931\u8D25:", error);
197
+ await e.reply("\u65E5\u5FD7\u6E32\u67D3\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u9519\u8BEF\u4FE1\u606F");
198
+ return false;
199
+ }
200
+ }, { name: "\u65E5\u5FD7\u67E5\u770B\u5668", perm: "admin" });
201
+ var errorLogViewer = karin.command(/^#错误日志\s*(\d+)?$/, async (e) => {
202
+ const match = e.msg.match(/^#错误日志\s*(\d+)?$/);
203
+ let limit = match && match[1] ? Number(match[1]) : 50;
204
+ if (!Number.isFinite(limit) || limit <= 0) limit = 50;
205
+ if (limit > 200) limit = 200;
206
+ const logs = await getErrorLogs(limit);
207
+ if (!logs.length) {
208
+ await e.reply("\u6682\u65E0\u9519\u8BEF\u65E5\u5FD7");
209
+ return true;
210
+ }
211
+ const parsedLogs = logs.map(parseLogLine);
212
+ try {
213
+ const img = await render("logger/index", {
214
+ logs: parsedLogs,
215
+ total: parsedLogs.length,
216
+ date: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN")
217
+ });
218
+ await e.reply(img);
219
+ return true;
220
+ } catch (error) {
221
+ logger.error("\u6E32\u67D3\u9519\u8BEF\u65E5\u5FD7\u5931\u8D25:", error);
222
+ await e.reply("\u9519\u8BEF\u65E5\u5FD7\u6E32\u67D3\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u9519\u8BEF\u4FE1\u606F");
223
+ return false;
224
+ }
225
+ }, { name: "\u9519\u8BEF\u65E5\u5FD7\u67E5\u770B\u5668", perm: "admin" });
226
+ export {
227
+ errorLogViewer,
228
+ logViewer
229
+ };
@@ -1,15 +1,16 @@
1
1
  import {
2
- config
3
- } from "../chunk-BJBUGOWQ.js";
2
+ cfg
3
+ } from "../chunk-PHDIUMOH.js";
4
+ import "../chunk-QUWYQJAF.js";
4
5
 
5
6
  // src/apps/login.ts
6
7
  import karin, { common, contactFriend, logger, segment } from "node-karin";
7
8
  import axios from "node-karin/axios";
8
- import os from "node:os";
9
+ import os from "os";
9
10
  var url = { IPv4: ["https://4.ipw.cn"], IPv6: ["https://6.ipw.cn"] };
10
11
  var login = karin.command(/#?(面板|web)登录$/i, async (e) => {
11
12
  const net = os.networkInterfaces();
12
- const cfg = config();
13
+ const config = cfg.get();
13
14
  const IP = { lan: { ipv4: null, ipv6: null }, net: { ipv4: null, ipv6: null } };
14
15
  for (const i in net) {
15
16
  for (const iface of net[i]) {
@@ -32,7 +33,7 @@ var login = karin.command(/#?(面板|web)登录$/i, async (e) => {
32
33
  const port = process.env.HTTP_PORT;
33
34
  const token = process.env.HTTP_AUTH_KEY;
34
35
  const msg = [segment.text("\u9762\u677F\u767B\u5F55\u5730\u5740\uFF1A")];
35
- if (cfg.domain) msg.push(segment.text(`- \u81EA\u5B9A\u4E49\u57DF\u540D: ${cfg.domain}/web/login?token=${token}`));
36
+ if (config.domain) msg.push(segment.text(`- \u81EA\u5B9A\u4E49\u57DF\u540D: ${config.domain}/web/login?token=${token}`));
36
37
  msg.push(segment.text(`- \u5185\u7F51\u5730\u5740: ${IP.lan.ipv4 ? `http://${IP.lan.ipv4}:${port}/web/login?token=${token}` : `http://${IP.lan.ipv4}:${port}/web/login?token=${token}`}`));
37
38
  if (IP.net.ipv4) msg.push(segment.text(`- \u5916\u7F51IPv4\u5730\u5740: http://${IP.net.ipv4}:${port}/web/login?token=${token}`));
38
39
  if (IP.net.ipv6) msg.push(segment.text(`- \u5916\u7F51IPv6\u5730\u5740: http://${IP.net.ipv6}:${port}/web/login?token=${token}`));
@@ -3,5 +3,7 @@ import * as node_karin from 'node-karin';
3
3
  declare const Master: node_karin.Command<keyof node_karin.MessageEventMap>;
4
4
  declare const addMaster: node_karin.Command<keyof node_karin.MessageEventMap>;
5
5
  declare const delMaster: node_karin.Command<keyof node_karin.MessageEventMap>;
6
+ declare const listMaster: node_karin.Command<keyof node_karin.MessageEventMap>;
7
+ declare const setMasterCaptcha: node_karin.Command<keyof node_karin.MessageEventMap>;
6
8
 
7
- export { Master, addMaster, delMaster };
9
+ export { Master, addMaster, delMaster, listMaster, setMasterCaptcha };
@@ -1,7 +1,8 @@
1
1
  // src/apps/master.ts
2
2
  import crypto from "crypto";
3
- import { karin, logger, config } from "node-karin";
4
- var Master = karin.command(/^#设置主人/, async (e) => {
3
+ import { karin, logger, config, segment } from "node-karin";
4
+ var CAPTCHA = /* @__PURE__ */ new Map();
5
+ var Master = karin.command(/^#设置主人$/, async (e) => {
5
6
  if (e.isMaster) {
6
7
  await e.reply(`
7
8
  [${e.userId}] \u5DF2\u7ECF\u662F\u4E3B\u4EBA`, { at: true });
@@ -9,6 +10,7 @@ var Master = karin.command(/^#设置主人/, async (e) => {
9
10
  }
10
11
  const sign = crypto.randomUUID();
11
12
  logger.mark(`\u8BBE\u7F6E\u4E3B\u4EBA\u9A8C\u8BC1\u7801\uFF1A${logger.green(sign)}`);
13
+ CAPTCHA.set(e.userId, sign);
12
14
  await e.reply("\n\u8BF7\u8F93\u5165\u63A7\u5236\u53F0\u9A8C\u8BC1\u7801", { at: true });
13
15
  const event = await karin.ctx(e);
14
16
  if (sign !== event.msg.trim()) {
@@ -62,8 +64,24 @@ var delMaster = karin.command(/^#删除主人/, async (e) => {
62
64
  \u5220\u9664\u4E3B\u4EBA: ${userId}`, { at: true });
63
65
  return true;
64
66
  }, { name: "\u5220\u9664\u4E3B\u4EBA", priority: -1, permission: "master" });
67
+ var listMaster = karin.command(/^#主人列表$/, async (e) => {
68
+ const masters = config.master();
69
+ await e.reply(`\u4E3B\u4EBA\u5217\u8868:
70
+ ${masters.map((v) => `- ${v}`).join("\n")}`, { reply: true });
71
+ return true;
72
+ }, { name: "\u4E3B\u4EBA\u5217\u8868", priority: -1, permission: "master" });
73
+ var setMasterCaptcha = karin.command(/^#设置主人验证码$/, async (e) => {
74
+ const msg = [];
75
+ CAPTCHA.forEach((v, k) => {
76
+ msg.push(segment.text(`- \u7528\u6237: ${k} \u9A8C\u8BC1\u7801: ${v}`));
77
+ });
78
+ if (msg.length === 0) return e.reply("\u6682\u65E0\u9A8C\u8BC1\u7801", { reply: true });
79
+ await e.reply(["\u4E3B\u4EBA\u9A8C\u8BC1\u7801\u5217\u8868:\n", ...msg], { reply: true });
80
+ }, { name: "\u8BBE\u7F6E\u4E3B\u4EBA\u9A8C\u8BC1\u7801", priority: -1, permission: "master" });
65
81
  export {
66
82
  Master,
67
83
  addMaster,
68
- delMaster
84
+ delMaster,
85
+ listMaster,
86
+ setMasterCaptcha
69
87
  };
@@ -1,13 +1,14 @@
1
1
  import {
2
- config
3
- } from "../chunk-BJBUGOWQ.js";
2
+ cfg
3
+ } from "../chunk-PHDIUMOH.js";
4
+ import "../chunk-QUWYQJAF.js";
4
5
 
5
6
  // src/apps/restart.ts
6
7
  import { common, karin, logger, restart } from "node-karin";
7
8
  var restarts = karin.command(/^#重启$/, async (e) => {
8
9
  try {
9
10
  await e.reply(`\u5F00\u59CB\u91CD\u542F \u672C\u6B21\u8FD0\u884C\u65F6\u95F4: ${common.uptime()}`, { at: true });
10
- const { status, data } = await restart(e.selfId, e.contact, e.messageId, config().restartMode);
11
+ const { status, data } = await restart(e.selfId, e.contact, e.messageId, cfg.get().restartMode);
11
12
  if (status === "failed") throw data;
12
13
  return true;
13
14
  } catch (error) {
@@ -6,12 +6,12 @@ import {
6
6
  uptime
7
7
  } from "../chunk-ODFXVVIE.js";
8
8
  import {
9
- config,
10
- info
11
- } from "../chunk-BJBUGOWQ.js";
9
+ cfg
10
+ } from "../chunk-PHDIUMOH.js";
11
+ import "../chunk-QUWYQJAF.js";
12
12
 
13
13
  // src/apps/status.ts
14
- import { karin, logger } from "node-karin";
14
+ import { karin } from "node-karin";
15
15
  var status = karin.command(/^#状态$/, async (e) => {
16
16
  const { send, recv, event } = await getTodayStat();
17
17
  const { send: sendMonth, recv: recvMonth, event: eventMonth } = await getMonthStat();
@@ -31,8 +31,7 @@ var status = karin.command(/^#状态$/, async (e) => {
31
31
  ].join("\n"));
32
32
  return true;
33
33
  }, { name: "\u72B6\u6001\u7EDF\u8BA1" });
34
- if (config().status) initStat();
35
- logger.info(`${logger.violet(`[\u63D2\u4EF6:${info.version}]`)} ${logger.green(info.pkg.name)} \u521D\u59CB\u5316\u5B8C\u6210~`);
34
+ if (cfg.get().status) initStat();
36
35
  export {
37
36
  status
38
37
  };
@@ -2,13 +2,12 @@ import * as node_karin from 'node-karin';
2
2
 
3
3
  /** 插件列表 */
4
4
  declare const plugins: node_karin.Command<keyof node_karin.MessageEventMap>;
5
+ /** 更新插件 */
6
+ declare const updatePlugin: node_karin.Command<keyof node_karin.MessageEventMap>;
5
7
  /** 检查更新 */
6
8
  declare const check: node_karin.Command<keyof node_karin.MessageEventMap>;
7
- /** 更新插件 */
8
- declare const update: node_karin.Command<keyof node_karin.MessageEventMap>;
9
9
  /** 更新日志 */
10
10
  declare const log: node_karin.Command<keyof node_karin.MessageEventMap>;
11
- /** 全部更新 */
12
- declare const updateAll: node_karin.Command<keyof node_karin.MessageEventMap>;
11
+ declare const TaskUpdate: node_karin.Task;
13
12
 
14
- export { check, log, plugins, update, updateAll };
13
+ export { TaskUpdate, check, log, plugins, updatePlugin };