@kotori-bot/core
Advanced tools
Comparing version 1.5.0 to 1.5.1
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -41,4 +41,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/components/config.ts | ||
var config_exports = {}; | ||
@@ -51,35 +49,6 @@ __export(config_exports, { | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_node_path = require("node:path"); | ||
var import_tools = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko.default.Object({ | ||
var import_global = require("../global"); | ||
const packageInfoSchema = import_tsukiko.default.Object({ | ||
name: import_tsukiko.default.String(), | ||
@@ -92,6 +61,6 @@ version: import_tsukiko.default.String(), | ||
}); | ||
var Config = class { | ||
class Config { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
constructor(config = import_global.DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
@@ -112,3 +81,3 @@ const info = (0, import_tools.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
} | ||
}; | ||
} | ||
var config_default = Config; | ||
@@ -115,0 +84,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -32,3 +32,2 @@ | ||
}; | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
@@ -43,4 +42,2 @@ // If the importer is in node compatibility mode or this is not an ESM | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/components/core.ts | ||
var core_exports = {}; | ||
@@ -52,792 +49,25 @@ __export(core_exports, { | ||
module.exports = __toCommonJS(core_exports); | ||
var import_tools8 = require("@kotori-bot/tools"); | ||
var import_i18n2 = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro2 = require("fluoro"); | ||
// src/components/config.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_tools = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko.default.Object({ | ||
name: import_tsukiko.default.String(), | ||
version: import_tsukiko.default.String(), | ||
description: import_tsukiko.default.String(), | ||
main: import_tsukiko.default.String(), | ||
license: import_tsukiko.default.Literal("GPL-3.0"), | ||
author: import_tsukiko.default.String() | ||
}); | ||
var Config = class { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
const info = (0, import_tools.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
if (!info || Object.values(info).length === 0) { | ||
process.stderr.write(`Cannot find kotori-bot package.json | ||
`); | ||
process.exit(); | ||
} | ||
const result = packageInfoSchema.parseSafe(info); | ||
if (!result.value) { | ||
process.stderr.write(`File package.json format error: ${result.error.message} | ||
`); | ||
process.exit(); | ||
} | ||
this.pkg = result.data; | ||
} | ||
}; | ||
var config_default = Config; | ||
// src/components/message.ts | ||
var import_tools7 = require("@kotori-bot/tools"); | ||
var import_cron = require("cron"); | ||
// src/utils/factory.ts | ||
var import_tools6 = require("@kotori-bot/tools"); | ||
// src/types/message.ts | ||
var import_tsukiko2 = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko2.default.Union([ | ||
import_tsukiko2.default.Union([import_tsukiko2.default.Literal("string"), import_tsukiko2.default.Literal("number")]), | ||
import_tsukiko2.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko2.default.Union([import_tsukiko2.default.Number(), import_tsukiko2.default.String()]); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Cache: () => Cache, | ||
Command: () => Command, | ||
CommandAccess: () => CommandAccess, | ||
CommandError: () => CommandError, | ||
Container: () => Container, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
DevError: () => DevError, | ||
Elements: () => Elements, | ||
KotoriError: () => KotoriError, | ||
MessageScope: () => MessageScope, | ||
ModuleError: () => ModuleError, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols, | ||
cancelFactory: () => cancelFactory, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
confirmFactory: () => confirmFactory, | ||
disposeFactory: () => disposeFactory, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema, | ||
formatFactory: () => formatFactory, | ||
promptFactory: () => promptFactory, | ||
quickFactory: () => quickFactory, | ||
sendMessageFactory: () => sendMessageFactory | ||
}); | ||
__reExport(src_exports, require("fluoro")); | ||
// src/service/elements.ts | ||
var import_tools2 = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
default(...args) { | ||
(0, import_tools2.none)(this, args); | ||
return ""; | ||
} | ||
at(target, ...extra) { | ||
return this.default(target, extra); | ||
} | ||
image(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
voice(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
video(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
face(id, ...extra) { | ||
return this.default(id, extra); | ||
} | ||
file(data, ...extra) { | ||
return this.default(data, extra); | ||
} | ||
supports() { | ||
const supports = []; | ||
const keys = ["at", "image", "voice", "video", "face", "file"]; | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
var elements_default = Elements; | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
var commandError_default = CommandError; | ||
// src/service/adapter.ts | ||
function setProxy(api, ctx) { | ||
const proxy = Object.create(api); | ||
proxy.sendPrivateMsg = new Proxy(api.sendPrivateMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendPrivateMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
proxy.sendGroupMsg = new Proxy(api.sendGroupMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendGroupMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
return proxy; | ||
} | ||
function error(type, data) { | ||
return new commandError_default(Object.assign(data ?? {}, { type })); | ||
} | ||
var Adapter = class { | ||
constructor(ctx, config, identity, Api2, el = new elements_default()) { | ||
this.ctx = ctx; | ||
this.config = config; | ||
this.identity = identity; | ||
this.platform = config.extends; | ||
this.api = setProxy(new Api2(this), this.ctx); | ||
this.elements = el; | ||
if (!this.ctx[Symbols.bot].get(this.platform)) this.ctx[Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[Symbols.bot].get(this.platform).add(this.api); | ||
} | ||
online() { | ||
if (this.status.value !== "offline") return; | ||
this.status.value = "online"; | ||
this.ctx.emit("status", { adapter: this, status: "online" }); | ||
} | ||
offline() { | ||
if (this.status.value !== "online") return; | ||
this.status.value = "offline"; | ||
this.status.offlineTimes += 1; | ||
this.ctx.emit("status", { adapter: this, status: "offline" }); | ||
} | ||
session(type, data) { | ||
const i18n = this.ctx.i18n.extends(this.config.lang); | ||
const send = sendMessageFactory(this, type, data); | ||
const format = formatFactory(i18n); | ||
const quick = quickFactory(send, i18n); | ||
const prompt = promptFactory(quick, this, data); | ||
const confirm = confirmFactory(quick, this, data); | ||
const { api, elements: el } = this; | ||
this.ctx.emit( | ||
type, | ||
...[{ ...data, api, el, send, i18n, format, quick, prompt, confirm, error }] | ||
); | ||
} | ||
ctx; | ||
config; | ||
identity; | ||
platform; | ||
api; | ||
elements; | ||
status = { | ||
value: "offline", | ||
createTime: /* @__PURE__ */ new Date(), | ||
lastMsgTime: null, | ||
receivedMsg: 0, | ||
sentMsg: 0, | ||
offlineTimes: 0 | ||
}; | ||
selfId = -1; | ||
}; | ||
// src/service/api.ts | ||
var import_tools3 = require("@kotori-bot/tools"); | ||
var Api = class { | ||
adapter; | ||
constructor(adapter) { | ||
this.adapter = adapter; | ||
} | ||
sendPrivateMsg(message, userId, ...extra) { | ||
(0, import_tools3.none)(this, message, userId, extra); | ||
} | ||
sendGroupMsg(message, groupId, ...extra) { | ||
(0, import_tools3.none)(this, message, groupId, extra, extra); | ||
} | ||
deleteMsg(messageId, ...extra) { | ||
(0, import_tools3.none)(this, messageId, extra); | ||
} | ||
setGroupName(groupId, groupName, ...extra) { | ||
(0, import_tools3.none)(this, groupId, groupName, extra); | ||
} | ||
setGroupAvatar(groupId, image, ...extra) { | ||
(0, import_tools3.none)(this, groupId, image, extra); | ||
} | ||
setGroupAdmin(groupId, userId, enable, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, enable, extra); | ||
} | ||
setGroupCard(groupId, userId, card, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, card, extra); | ||
} | ||
setGroupBan(groupId, userId, time, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, time, extra); | ||
} | ||
sendGroupNotice(groupId, content, image, ...extra) { | ||
(0, import_tools3.none)(this, groupId, content, image, extra); | ||
} | ||
setGroupKick(groupId, userId, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, extra); | ||
} | ||
setGroupLeave(groupId, ...extra) { | ||
(0, import_tools3.none)(this, groupId, groupId, extra); | ||
} | ||
}; | ||
// src/service/cache.ts | ||
var import_i18n = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro = require("fluoro"); | ||
var Cache = class extends import_fluoro.Service { | ||
cache; | ||
constructor(ctx) { | ||
super(ctx, {}, "cache"); | ||
} | ||
start() { | ||
if (this.cache) return; | ||
this.cache = /* @__PURE__ */ new Map(); | ||
} | ||
stop() { | ||
this.cache?.forEach((el) => el.clear()); | ||
this.cache?.clear(); | ||
delete this.cache; | ||
} | ||
getContainer() { | ||
const key = this.ctx.identity ?? "root"; | ||
if (!this.cache.has(key)) this.cache.set(key, /* @__PURE__ */ new Map()); | ||
return this.cache.get(key); | ||
} | ||
get(prop) { | ||
return this.getContainer().get(prop); | ||
} | ||
set(prop, value) { | ||
this.getContainer().set(prop, value); | ||
} | ||
}; | ||
// src/utils/command.ts | ||
var import_tools4 = require("@kotori-bot/tools"); | ||
var import_minimist = __toESM(require("minimist")); | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
if (type === "boolean") return value !== "false" && !!value; | ||
if (type === "number") { | ||
if (typeof value === "number") return value; | ||
if (value === true) return 1; | ||
if (value === false) return 0; | ||
const float = parseFloat(value); | ||
const int = parseInt(value, 10); | ||
return float === int ? int : float; | ||
} | ||
return value.toString(); | ||
} | ||
var Command = class { | ||
static run(input, data) { | ||
let starts = ""; | ||
[data.root, ...data.alias].forEach((el) => { | ||
if (starts) return; | ||
if (input.startsWith(`${el} `) || input === el) starts = el; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
const opts = { | ||
string: [], | ||
boolean: [], | ||
alias: {} | ||
}; | ||
data.options.forEach((option) => { | ||
if (option.type === "string") { | ||
opts.string.push(option.realname); | ||
} else if (option.type === "boolean") { | ||
opts.boolean.push(option.realname); | ||
} | ||
opts.alias[option.realname] = option.name; | ||
}); | ||
const arr = (0, import_tools4.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
const args = result._; | ||
const count = { | ||
expected: data.args.filter((el) => !el.optional).length, | ||
reality: args.length | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
let error2; | ||
data.args.forEach((val, index) => { | ||
if (error2 || index > 0 && !args[index - 1]) return; | ||
if (!args[index] && val.default) { | ||
args[index] = val.default; | ||
return; | ||
} | ||
if (val.rest || !args[index]) return; | ||
args[index] = handleDefaultValue(args[index], val.type); | ||
if (!Number.isNaN(args[index])) return; | ||
error2 = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
if (error2) return error2; | ||
const options = {}; | ||
data.options.forEach((val) => { | ||
if (!(val.realname in result)) return; | ||
options[val.realname] = Array.isArray(result[val.realname]) ? result[val.realname][0] : result[val.realname]; | ||
options[val.realname] = handleDefaultValue(options[val.realname], val.type); | ||
if (Number.isNaN(options[val.realname])) | ||
error2 = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
if (error2) return error2; | ||
return { | ||
args: data.args.length > 0 && data.args[data.args.length - 1].rest ? args : args.slice(0, data.args.length), | ||
options | ||
}; | ||
} | ||
template; | ||
meta = { | ||
root: "", | ||
alias: [], | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
args: [], | ||
options: [] | ||
}; | ||
constructor(template, config) { | ||
this.template = template; | ||
this.meta = Object.assign(this.meta, config); | ||
this.parse(); | ||
} | ||
parse() { | ||
const [str, description] = this.template.trim().split(" - "); | ||
this.meta.description = description; | ||
const requiredIndex = str.indexOf(" <"); | ||
const optionalIndex = str.indexOf(" ["); | ||
if (requiredIndex === -1 && optionalIndex === -1) { | ||
this.meta.root = str.trim(); | ||
return; | ||
} | ||
if (requiredIndex !== -1 && (optionalIndex === -1 || requiredIndex < optionalIndex)) { | ||
this.meta.root = str.substring(0, requiredIndex).trim(); | ||
} else { | ||
this.meta.root = str.substring(0, optionalIndex).trim(); | ||
} | ||
const args = (0, import_minimist.default)(str.split(" "))._; | ||
args.forEach((arg) => { | ||
const current = this.meta.args[this.meta.args.length - 1]; | ||
if (current && current.rest) return; | ||
let result = optionalParamMatch.exec(arg); | ||
if (result) { | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type, | ||
rest: !!result[1], | ||
optional: true, | ||
default: result[6] ? handleDefaultValue(result[6], type) : void 0 | ||
}); | ||
} | ||
result = requiredParamMatch.exec(arg); | ||
if (!result || !result[2]) return; | ||
if (!result[6] && current && current.optional) return; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
optional: false | ||
}); | ||
}); | ||
} | ||
alias(alias) { | ||
if (typeof alias === "string") this.meta.alias.push(alias); | ||
else this.meta.alias.push(...alias); | ||
return this; | ||
} | ||
scope(scope) { | ||
this.meta.scope = scope; | ||
return this; | ||
} | ||
access(access) { | ||
this.meta.access = access; | ||
return this; | ||
} | ||
option(name, template) { | ||
const [str, description] = template.trim().split(" "); | ||
const [realname, type] = str.split(":"); | ||
this.meta.options.push({ | ||
realname, | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
}); | ||
return this; | ||
} | ||
action(callback) { | ||
this.meta.action = callback; | ||
return this; | ||
} | ||
help(text) { | ||
this.meta.help = text; | ||
return this; | ||
} | ||
}; | ||
// src/utils/container.ts | ||
var import_tools5 = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
constructor() { | ||
(0, import_tools5.none)(); | ||
} | ||
static instance = {}; | ||
static setInstance(ctx) { | ||
this.instance = ctx; | ||
} | ||
static getInstance() { | ||
return this.instance; | ||
} | ||
static getMixin() { | ||
return Object.assign( | ||
_Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("@kotori-bot/tools")); | ||
__reExport(src_exports, require("@kotori-bot/i18n")); | ||
__reExport(src_exports, require("tsukiko")); | ||
// src/utils/factory.ts | ||
function disposeFactory(ctx, dispose) { | ||
ctx.once("dispose_module", (data) => { | ||
if ((typeof data.instance === "object" ? data.instance.name : data.instance) !== ctx.identity) { | ||
disposeFactory(ctx, dispose); | ||
return; | ||
} | ||
dispose(); | ||
}); | ||
} | ||
function cancelFactory() { | ||
return { | ||
get() { | ||
return () => this.fn(); | ||
}, | ||
fn() { | ||
this.value = true; | ||
}, | ||
value: false | ||
}; | ||
} | ||
function formatFactory(i18n) { | ||
return (template, data) => { | ||
const params = data; | ||
if (Array.isArray(params)) { | ||
let str = i18n.locale(template); | ||
params.forEach((value, index) => { | ||
str = str.replaceAll(`{${index}}`, i18n.locale(typeof value === "string" ? value : String(value))); | ||
}); | ||
return str; | ||
} | ||
Object.keys(params).forEach((key) => { | ||
if (typeof params[key] !== "string") params[key] = String(params[key]); | ||
params[key] = i18n.locale(params[key]); | ||
}); | ||
return (0, import_tools6.stringTemp)(i18n.locale(template), params); | ||
}; | ||
} | ||
function sendMessageFactory(adapter, type, data) { | ||
if ((data.type === 1 /* GROUP */ || type.includes("group")) && "groupId" in data) { | ||
return (message) => { | ||
adapter.api.sendGroupMsg(message, data.groupId, data.extra); | ||
}; | ||
} | ||
return (message) => { | ||
adapter.api.sendPrivateMsg(message, data.userId, data.extra); | ||
}; | ||
} | ||
function quickFactory(send, i18n) { | ||
return async (message) => { | ||
const msg = await message; | ||
if (!msg || msg instanceof CommandError) return; | ||
if (typeof msg === "string") { | ||
send(i18n.locale(msg)); | ||
return; | ||
} | ||
send(formatFactory(i18n)(...msg)); | ||
}; | ||
} | ||
function isSameSender(adapter, data, session) { | ||
return session.api.adapter.identity === adapter.identity && session.api.adapter.platform === adapter.platform && session.type === data.type && session.groupId === data.groupId && session.userId === data.userId && "messageId" in data && session.messageId !== data.messageId; | ||
} | ||
function promptFactory(quick, adapter, data) { | ||
return (message) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(message ?? "corei18n.template.prompt").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
function confirmFactory(quick, adapter, data) { | ||
return (options) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(options?.message ?? "corei18n.template.confirm").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
// src/components/message.ts | ||
var Message = class { | ||
[Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[Symbols.command] = /* @__PURE__ */ new Set(); | ||
[Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
handleMidware(session) { | ||
const { api } = session; | ||
let isPass = true; | ||
let midwares = []; | ||
api.adapter.status.receivedMsg += 1; | ||
this[Symbols.midware].forEach((val) => midwares.push(val)); | ||
midwares = midwares.sort((first, second) => first.priority - second.priority); | ||
let lastMidwareNum = -1; | ||
while (midwares.length > 0) { | ||
if (lastMidwareNum === midwares.length) { | ||
isPass = false; | ||
break; | ||
} | ||
lastMidwareNum = midwares.length; | ||
session.quick(midwares[0].callback(() => midwares.shift(), session)); | ||
} | ||
this.ctx.emit("midwares", { isPass, session }); | ||
} | ||
async handleRegexp(data) { | ||
const { session } = data; | ||
if (!data.isPass) return; | ||
this[Symbols.regexp].forEach((data2) => { | ||
const result = session.message.match(data2.match); | ||
if (!result) return; | ||
session.quick(data2.callback(result, session)); | ||
this.ctx.emit("regexp", { result, session, regexp: data2.match, raw: session.message }); | ||
}); | ||
} | ||
handleCommand(data) { | ||
const { session } = data; | ||
const prefix = session.api.adapter.config["command-prefix"] ?? this.ctx.config.global["command-prefix"]; | ||
if (!session.message.startsWith(prefix)) return; | ||
const params = { | ||
session, | ||
raw: (0, import_tools7.stringRightSplit)(session.message, prefix) | ||
}; | ||
this.ctx.emit("before_parse", params); | ||
const cancel = cancelFactory(); | ||
this.ctx.emit("before_command", { cancel: cancel.get(), ...params }); | ||
if (cancel.value) return; | ||
let matched; | ||
this[Symbols.command].forEach(async (cmd) => { | ||
if (matched || !cmd.meta.action) return; | ||
const result = Command.run(params.raw, cmd.meta); | ||
if (result instanceof commandError_default && result.value.type === "unknown") return; | ||
matched = cmd; | ||
this.ctx.emit("parse", { command: cmd, result, ...params, cancel: cancel.get() }); | ||
if (cancel.value || result instanceof commandError_default) return; | ||
try { | ||
const executed = await cmd.meta.action({ args: result.args, options: result.options }, session); | ||
if (executed instanceof commandError_default) { | ||
this.ctx.emit("command", { command: cmd, result: executed, ...params }); | ||
return; | ||
} | ||
if (executed !== void 0) session.quick(executed); | ||
this.ctx.emit("command", { | ||
command: cmd, | ||
result: executed instanceof commandError_default ? result : executed, | ||
...params | ||
}); | ||
} catch (error2) { | ||
this.ctx.emit("command", { | ||
command: matched, | ||
result: new commandError_default({ type: "error", error: error2 }), | ||
...params | ||
}); | ||
} | ||
}); | ||
if (matched) return; | ||
this.ctx.emit("parse", { | ||
command: new Command(""), | ||
result: new commandError_default({ type: "unknown", input: params.raw }), | ||
...params, | ||
cancel: cancel.get() | ||
}); | ||
} | ||
ctx; | ||
constructor(ctx) { | ||
this.ctx = ctx; | ||
this.ctx.on("on_message", (session) => this.handleMidware(session)); | ||
this.ctx.on("midwares", (data) => this.handleCommand(data)); | ||
this.ctx.on("midwares", (data) => this.handleRegexp(data)); | ||
this.ctx.on("before_send", (data) => { | ||
const { api } = data; | ||
api.adapter.status.sentMsg += 1; | ||
}); | ||
} | ||
midware(callback, priority = 100) { | ||
const data = { callback, priority }; | ||
this[Symbols.midware].add(data); | ||
const dispose = () => this[Symbols.midware].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
command(template, config) { | ||
const command = new Command(template, config); | ||
this[Symbols.command].add(command); | ||
const dispose = () => this[Symbols.command].delete(command); | ||
disposeFactory(this.ctx, dispose); | ||
return command; | ||
} | ||
regexp(match, callback) { | ||
const data = { match, callback }; | ||
this[Symbols.regexp].add(data); | ||
const dispose = () => this[Symbols.regexp].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
// boardcast(type: MessageScope, message: MessageRaw) { | ||
// const send = | ||
// type === 'private' | ||
// ? (api: Api) => api.send_on_message(message, 1) | ||
// : (api: Api) => api.send_on_message(message, 1); | ||
// /* this need support of database... */ | ||
// Object.values(this.botStack).forEach((apis) => { | ||
// apis.forEach((api) => send(api)); | ||
// }); | ||
// } | ||
notify(message) { | ||
const mainAdapterIdentity = Object.keys(this.ctx.config.adapter)[0]; | ||
this.ctx[Symbols.bot].forEach( | ||
(apis) => apis.forEach((api) => { | ||
if (api.adapter.identity !== mainAdapterIdentity) return; | ||
quickFactory( | ||
sendMessageFactory(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
this.ctx.i18n.extends(api.adapter.config.lang) | ||
)(message); | ||
}) | ||
); | ||
} | ||
task(options, callback) { | ||
const [cron, extraOptions] = typeof options === "string" ? [options, {}] : [options.cron, options]; | ||
return new import_cron.CronJob(cron, () => callback(this.ctx), null, extraOptions.start ?? true, extraOptions.timeZone); | ||
} | ||
}; | ||
var message_default = Message; | ||
// src/components/core.ts | ||
var Core = class extends import_fluoro2.Context { | ||
[Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[Symbols.bot] = /* @__PURE__ */ new Map(); | ||
var import_config = __toESM(require("./config")); | ||
var import_message = __toESM(require("./message")); | ||
var import_service = require("../service"); | ||
var import_global = require("../global"); | ||
class Core extends import_fluoro.Context { | ||
[import_global.Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[import_global.Symbols.bot] = /* @__PURE__ */ new Map(); | ||
constructor(config) { | ||
super(); | ||
this.provide("config", new config_default(config)); | ||
this.provide("config", new import_config.default(config)); | ||
this.mixin("config", ["config", "pkg"]); | ||
this.provide("message", new message_default(this)); | ||
this.provide("message", new import_message.default(this)); | ||
this.mixin("message", ["midware", "command", "regexp", "notify", "task"]); | ||
this.provide("http", new import_tools8.Http({ validateStatus: () => true })); | ||
this.provide("http", new import_tools.Http({ validateStatus: () => true })); | ||
this.inject("http"); | ||
this.provide("i18n", new import_i18n2.default({ lang: this.config.global.lang })); | ||
this.provide("i18n", new import_i18n.default({ lang: this.config.global.lang })); | ||
this.inject("i18n"); | ||
this.service("cache", new Cache(this.extends())); | ||
this.service("cache", new import_service.Cache(this.extends())); | ||
} | ||
}; | ||
} | ||
var core_default = Core; | ||
@@ -844,0 +74,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,16 +9,10 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
"use strict"; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
@@ -33,829 +27,11 @@ if (from && typeof from === "object" || typeof from === "function") { | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
// If the importer is in node compatibility mode or this is not an ESM | ||
// file that has been converted to a CommonJS file using a Babel- | ||
// compatible transform (i.e. "__esModule" has not been set), then set | ||
// "default" to the CommonJS "module.exports" for node compatibility. | ||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
mod | ||
)); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/components/index.ts | ||
var components_exports = {}; | ||
__export(components_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols | ||
}); | ||
module.exports = __toCommonJS(components_exports); | ||
// src/components/core.ts | ||
var import_tools8 = require("@kotori-bot/tools"); | ||
var import_i18n2 = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro2 = require("fluoro"); | ||
// src/components/config.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_tools = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko.default.Object({ | ||
name: import_tsukiko.default.String(), | ||
version: import_tsukiko.default.String(), | ||
description: import_tsukiko.default.String(), | ||
main: import_tsukiko.default.String(), | ||
license: import_tsukiko.default.Literal("GPL-3.0"), | ||
author: import_tsukiko.default.String() | ||
}); | ||
var Config = class { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
const info = (0, import_tools.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
if (!info || Object.values(info).length === 0) { | ||
process.stderr.write(`Cannot find kotori-bot package.json | ||
`); | ||
process.exit(); | ||
} | ||
const result = packageInfoSchema.parseSafe(info); | ||
if (!result.value) { | ||
process.stderr.write(`File package.json format error: ${result.error.message} | ||
`); | ||
process.exit(); | ||
} | ||
this.pkg = result.data; | ||
} | ||
}; | ||
var config_default = Config; | ||
// src/components/message.ts | ||
var import_tools7 = require("@kotori-bot/tools"); | ||
var import_cron = require("cron"); | ||
// src/utils/factory.ts | ||
var import_tools6 = require("@kotori-bot/tools"); | ||
// src/types/message.ts | ||
var import_tsukiko2 = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko2.default.Union([ | ||
import_tsukiko2.default.Union([import_tsukiko2.default.Literal("string"), import_tsukiko2.default.Literal("number")]), | ||
import_tsukiko2.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko2.default.Union([import_tsukiko2.default.Number(), import_tsukiko2.default.String()]); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Cache: () => Cache, | ||
Command: () => Command, | ||
CommandAccess: () => CommandAccess, | ||
CommandError: () => CommandError, | ||
Container: () => Container, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
DevError: () => DevError, | ||
Elements: () => Elements, | ||
KotoriError: () => KotoriError, | ||
MessageScope: () => MessageScope, | ||
ModuleError: () => ModuleError, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols, | ||
cancelFactory: () => cancelFactory, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
confirmFactory: () => confirmFactory, | ||
disposeFactory: () => disposeFactory, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema, | ||
formatFactory: () => formatFactory, | ||
promptFactory: () => promptFactory, | ||
quickFactory: () => quickFactory, | ||
sendMessageFactory: () => sendMessageFactory | ||
}); | ||
__reExport(src_exports, require("fluoro")); | ||
// src/service/elements.ts | ||
var import_tools2 = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
default(...args) { | ||
(0, import_tools2.none)(this, args); | ||
return ""; | ||
} | ||
at(target, ...extra) { | ||
return this.default(target, extra); | ||
} | ||
image(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
voice(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
video(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
face(id, ...extra) { | ||
return this.default(id, extra); | ||
} | ||
file(data, ...extra) { | ||
return this.default(data, extra); | ||
} | ||
supports() { | ||
const supports = []; | ||
const keys = ["at", "image", "voice", "video", "face", "file"]; | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
var elements_default = Elements; | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
var commandError_default = CommandError; | ||
// src/service/adapter.ts | ||
function setProxy(api, ctx) { | ||
const proxy = Object.create(api); | ||
proxy.sendPrivateMsg = new Proxy(api.sendPrivateMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendPrivateMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
proxy.sendGroupMsg = new Proxy(api.sendGroupMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendGroupMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
return proxy; | ||
} | ||
function error(type, data) { | ||
return new commandError_default(Object.assign(data ?? {}, { type })); | ||
} | ||
var Adapter = class { | ||
constructor(ctx, config, identity, Api2, el = new elements_default()) { | ||
this.ctx = ctx; | ||
this.config = config; | ||
this.identity = identity; | ||
this.platform = config.extends; | ||
this.api = setProxy(new Api2(this), this.ctx); | ||
this.elements = el; | ||
if (!this.ctx[Symbols.bot].get(this.platform)) this.ctx[Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[Symbols.bot].get(this.platform).add(this.api); | ||
} | ||
online() { | ||
if (this.status.value !== "offline") return; | ||
this.status.value = "online"; | ||
this.ctx.emit("status", { adapter: this, status: "online" }); | ||
} | ||
offline() { | ||
if (this.status.value !== "online") return; | ||
this.status.value = "offline"; | ||
this.status.offlineTimes += 1; | ||
this.ctx.emit("status", { adapter: this, status: "offline" }); | ||
} | ||
session(type, data) { | ||
const i18n = this.ctx.i18n.extends(this.config.lang); | ||
const send = sendMessageFactory(this, type, data); | ||
const format = formatFactory(i18n); | ||
const quick = quickFactory(send, i18n); | ||
const prompt = promptFactory(quick, this, data); | ||
const confirm = confirmFactory(quick, this, data); | ||
const { api, elements: el } = this; | ||
this.ctx.emit( | ||
type, | ||
...[{ ...data, api, el, send, i18n, format, quick, prompt, confirm, error }] | ||
); | ||
} | ||
ctx; | ||
config; | ||
identity; | ||
platform; | ||
api; | ||
elements; | ||
status = { | ||
value: "offline", | ||
createTime: /* @__PURE__ */ new Date(), | ||
lastMsgTime: null, | ||
receivedMsg: 0, | ||
sentMsg: 0, | ||
offlineTimes: 0 | ||
}; | ||
selfId = -1; | ||
}; | ||
// src/service/api.ts | ||
var import_tools3 = require("@kotori-bot/tools"); | ||
var Api = class { | ||
adapter; | ||
constructor(adapter) { | ||
this.adapter = adapter; | ||
} | ||
sendPrivateMsg(message, userId, ...extra) { | ||
(0, import_tools3.none)(this, message, userId, extra); | ||
} | ||
sendGroupMsg(message, groupId, ...extra) { | ||
(0, import_tools3.none)(this, message, groupId, extra, extra); | ||
} | ||
deleteMsg(messageId, ...extra) { | ||
(0, import_tools3.none)(this, messageId, extra); | ||
} | ||
setGroupName(groupId, groupName, ...extra) { | ||
(0, import_tools3.none)(this, groupId, groupName, extra); | ||
} | ||
setGroupAvatar(groupId, image, ...extra) { | ||
(0, import_tools3.none)(this, groupId, image, extra); | ||
} | ||
setGroupAdmin(groupId, userId, enable, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, enable, extra); | ||
} | ||
setGroupCard(groupId, userId, card, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, card, extra); | ||
} | ||
setGroupBan(groupId, userId, time, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, time, extra); | ||
} | ||
sendGroupNotice(groupId, content, image, ...extra) { | ||
(0, import_tools3.none)(this, groupId, content, image, extra); | ||
} | ||
setGroupKick(groupId, userId, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, extra); | ||
} | ||
setGroupLeave(groupId, ...extra) { | ||
(0, import_tools3.none)(this, groupId, groupId, extra); | ||
} | ||
}; | ||
// src/service/cache.ts | ||
var import_fluoro = require("fluoro"); | ||
var Cache = class extends import_fluoro.Service { | ||
cache; | ||
constructor(ctx) { | ||
super(ctx, {}, "cache"); | ||
} | ||
start() { | ||
if (this.cache) return; | ||
this.cache = /* @__PURE__ */ new Map(); | ||
} | ||
stop() { | ||
this.cache?.forEach((el) => el.clear()); | ||
this.cache?.clear(); | ||
delete this.cache; | ||
} | ||
getContainer() { | ||
const key = this.ctx.identity ?? "root"; | ||
if (!this.cache.has(key)) this.cache.set(key, /* @__PURE__ */ new Map()); | ||
return this.cache.get(key); | ||
} | ||
get(prop) { | ||
return this.getContainer().get(prop); | ||
} | ||
set(prop, value) { | ||
this.getContainer().set(prop, value); | ||
} | ||
}; | ||
// src/utils/command.ts | ||
var import_tools4 = require("@kotori-bot/tools"); | ||
var import_minimist = __toESM(require("minimist")); | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
if (type === "boolean") return value !== "false" && !!value; | ||
if (type === "number") { | ||
if (typeof value === "number") return value; | ||
if (value === true) return 1; | ||
if (value === false) return 0; | ||
const float = parseFloat(value); | ||
const int = parseInt(value, 10); | ||
return float === int ? int : float; | ||
} | ||
return value.toString(); | ||
} | ||
var Command = class { | ||
static run(input, data) { | ||
let starts = ""; | ||
[data.root, ...data.alias].forEach((el) => { | ||
if (starts) return; | ||
if (input.startsWith(`${el} `) || input === el) starts = el; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
const opts = { | ||
string: [], | ||
boolean: [], | ||
alias: {} | ||
}; | ||
data.options.forEach((option) => { | ||
if (option.type === "string") { | ||
opts.string.push(option.realname); | ||
} else if (option.type === "boolean") { | ||
opts.boolean.push(option.realname); | ||
} | ||
opts.alias[option.realname] = option.name; | ||
}); | ||
const arr = (0, import_tools4.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
const args = result._; | ||
const count = { | ||
expected: data.args.filter((el) => !el.optional).length, | ||
reality: args.length | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
let error2; | ||
data.args.forEach((val, index) => { | ||
if (error2 || index > 0 && !args[index - 1]) return; | ||
if (!args[index] && val.default) { | ||
args[index] = val.default; | ||
return; | ||
} | ||
if (val.rest || !args[index]) return; | ||
args[index] = handleDefaultValue(args[index], val.type); | ||
if (!Number.isNaN(args[index])) return; | ||
error2 = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
if (error2) return error2; | ||
const options = {}; | ||
data.options.forEach((val) => { | ||
if (!(val.realname in result)) return; | ||
options[val.realname] = Array.isArray(result[val.realname]) ? result[val.realname][0] : result[val.realname]; | ||
options[val.realname] = handleDefaultValue(options[val.realname], val.type); | ||
if (Number.isNaN(options[val.realname])) | ||
error2 = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
if (error2) return error2; | ||
return { | ||
args: data.args.length > 0 && data.args[data.args.length - 1].rest ? args : args.slice(0, data.args.length), | ||
options | ||
}; | ||
} | ||
template; | ||
meta = { | ||
root: "", | ||
alias: [], | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
args: [], | ||
options: [] | ||
}; | ||
constructor(template, config) { | ||
this.template = template; | ||
this.meta = Object.assign(this.meta, config); | ||
this.parse(); | ||
} | ||
parse() { | ||
const [str, description] = this.template.trim().split(" - "); | ||
this.meta.description = description; | ||
const requiredIndex = str.indexOf(" <"); | ||
const optionalIndex = str.indexOf(" ["); | ||
if (requiredIndex === -1 && optionalIndex === -1) { | ||
this.meta.root = str.trim(); | ||
return; | ||
} | ||
if (requiredIndex !== -1 && (optionalIndex === -1 || requiredIndex < optionalIndex)) { | ||
this.meta.root = str.substring(0, requiredIndex).trim(); | ||
} else { | ||
this.meta.root = str.substring(0, optionalIndex).trim(); | ||
} | ||
const args = (0, import_minimist.default)(str.split(" "))._; | ||
args.forEach((arg) => { | ||
const current = this.meta.args[this.meta.args.length - 1]; | ||
if (current && current.rest) return; | ||
let result = optionalParamMatch.exec(arg); | ||
if (result) { | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type, | ||
rest: !!result[1], | ||
optional: true, | ||
default: result[6] ? handleDefaultValue(result[6], type) : void 0 | ||
}); | ||
} | ||
result = requiredParamMatch.exec(arg); | ||
if (!result || !result[2]) return; | ||
if (!result[6] && current && current.optional) return; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
optional: false | ||
}); | ||
}); | ||
} | ||
alias(alias) { | ||
if (typeof alias === "string") this.meta.alias.push(alias); | ||
else this.meta.alias.push(...alias); | ||
return this; | ||
} | ||
scope(scope) { | ||
this.meta.scope = scope; | ||
return this; | ||
} | ||
access(access) { | ||
this.meta.access = access; | ||
return this; | ||
} | ||
option(name, template) { | ||
const [str, description] = template.trim().split(" "); | ||
const [realname, type] = str.split(":"); | ||
this.meta.options.push({ | ||
realname, | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
}); | ||
return this; | ||
} | ||
action(callback) { | ||
this.meta.action = callback; | ||
return this; | ||
} | ||
help(text) { | ||
this.meta.help = text; | ||
return this; | ||
} | ||
}; | ||
// src/utils/container.ts | ||
var import_tools5 = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
constructor() { | ||
(0, import_tools5.none)(); | ||
} | ||
static instance = {}; | ||
static setInstance(ctx) { | ||
this.instance = ctx; | ||
} | ||
static getInstance() { | ||
return this.instance; | ||
} | ||
static getMixin() { | ||
return Object.assign( | ||
_Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("@kotori-bot/tools")); | ||
__reExport(src_exports, require("@kotori-bot/i18n")); | ||
__reExport(src_exports, require("tsukiko")); | ||
// src/utils/factory.ts | ||
function disposeFactory(ctx, dispose) { | ||
ctx.once("dispose_module", (data) => { | ||
if ((typeof data.instance === "object" ? data.instance.name : data.instance) !== ctx.identity) { | ||
disposeFactory(ctx, dispose); | ||
return; | ||
} | ||
dispose(); | ||
}); | ||
} | ||
function cancelFactory() { | ||
return { | ||
get() { | ||
return () => this.fn(); | ||
}, | ||
fn() { | ||
this.value = true; | ||
}, | ||
value: false | ||
}; | ||
} | ||
function formatFactory(i18n) { | ||
return (template, data) => { | ||
const params = data; | ||
if (Array.isArray(params)) { | ||
let str = i18n.locale(template); | ||
params.forEach((value, index) => { | ||
str = str.replaceAll(`{${index}}`, i18n.locale(typeof value === "string" ? value : String(value))); | ||
}); | ||
return str; | ||
} | ||
Object.keys(params).forEach((key) => { | ||
if (typeof params[key] !== "string") params[key] = String(params[key]); | ||
params[key] = i18n.locale(params[key]); | ||
}); | ||
return (0, import_tools6.stringTemp)(i18n.locale(template), params); | ||
}; | ||
} | ||
function sendMessageFactory(adapter, type, data) { | ||
if ((data.type === 1 /* GROUP */ || type.includes("group")) && "groupId" in data) { | ||
return (message) => { | ||
adapter.api.sendGroupMsg(message, data.groupId, data.extra); | ||
}; | ||
} | ||
return (message) => { | ||
adapter.api.sendPrivateMsg(message, data.userId, data.extra); | ||
}; | ||
} | ||
function quickFactory(send, i18n) { | ||
return async (message) => { | ||
const msg = await message; | ||
if (!msg || msg instanceof CommandError) return; | ||
if (typeof msg === "string") { | ||
send(i18n.locale(msg)); | ||
return; | ||
} | ||
send(formatFactory(i18n)(...msg)); | ||
}; | ||
} | ||
function isSameSender(adapter, data, session) { | ||
return session.api.adapter.identity === adapter.identity && session.api.adapter.platform === adapter.platform && session.type === data.type && session.groupId === data.groupId && session.userId === data.userId && "messageId" in data && session.messageId !== data.messageId; | ||
} | ||
function promptFactory(quick, adapter, data) { | ||
return (message) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(message ?? "corei18n.template.prompt").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
function confirmFactory(quick, adapter, data) { | ||
return (options) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(options?.message ?? "corei18n.template.confirm").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
// src/components/message.ts | ||
var Message = class { | ||
[Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[Symbols.command] = /* @__PURE__ */ new Set(); | ||
[Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
handleMidware(session) { | ||
const { api } = session; | ||
let isPass = true; | ||
let midwares = []; | ||
api.adapter.status.receivedMsg += 1; | ||
this[Symbols.midware].forEach((val) => midwares.push(val)); | ||
midwares = midwares.sort((first, second) => first.priority - second.priority); | ||
let lastMidwareNum = -1; | ||
while (midwares.length > 0) { | ||
if (lastMidwareNum === midwares.length) { | ||
isPass = false; | ||
break; | ||
} | ||
lastMidwareNum = midwares.length; | ||
session.quick(midwares[0].callback(() => midwares.shift(), session)); | ||
} | ||
this.ctx.emit("midwares", { isPass, session }); | ||
} | ||
async handleRegexp(data) { | ||
const { session } = data; | ||
if (!data.isPass) return; | ||
this[Symbols.regexp].forEach((data2) => { | ||
const result = session.message.match(data2.match); | ||
if (!result) return; | ||
session.quick(data2.callback(result, session)); | ||
this.ctx.emit("regexp", { result, session, regexp: data2.match, raw: session.message }); | ||
}); | ||
} | ||
handleCommand(data) { | ||
const { session } = data; | ||
const prefix = session.api.adapter.config["command-prefix"] ?? this.ctx.config.global["command-prefix"]; | ||
if (!session.message.startsWith(prefix)) return; | ||
const params = { | ||
session, | ||
raw: (0, import_tools7.stringRightSplit)(session.message, prefix) | ||
}; | ||
this.ctx.emit("before_parse", params); | ||
const cancel = cancelFactory(); | ||
this.ctx.emit("before_command", { cancel: cancel.get(), ...params }); | ||
if (cancel.value) return; | ||
let matched; | ||
this[Symbols.command].forEach(async (cmd) => { | ||
if (matched || !cmd.meta.action) return; | ||
const result = Command.run(params.raw, cmd.meta); | ||
if (result instanceof commandError_default && result.value.type === "unknown") return; | ||
matched = cmd; | ||
this.ctx.emit("parse", { command: cmd, result, ...params, cancel: cancel.get() }); | ||
if (cancel.value || result instanceof commandError_default) return; | ||
try { | ||
const executed = await cmd.meta.action({ args: result.args, options: result.options }, session); | ||
if (executed instanceof commandError_default) { | ||
this.ctx.emit("command", { command: cmd, result: executed, ...params }); | ||
return; | ||
} | ||
if (executed !== void 0) session.quick(executed); | ||
this.ctx.emit("command", { | ||
command: cmd, | ||
result: executed instanceof commandError_default ? result : executed, | ||
...params | ||
}); | ||
} catch (error2) { | ||
this.ctx.emit("command", { | ||
command: matched, | ||
result: new commandError_default({ type: "error", error: error2 }), | ||
...params | ||
}); | ||
} | ||
}); | ||
if (matched) return; | ||
this.ctx.emit("parse", { | ||
command: new Command(""), | ||
result: new commandError_default({ type: "unknown", input: params.raw }), | ||
...params, | ||
cancel: cancel.get() | ||
}); | ||
} | ||
ctx; | ||
constructor(ctx) { | ||
this.ctx = ctx; | ||
this.ctx.on("on_message", (session) => this.handleMidware(session)); | ||
this.ctx.on("midwares", (data) => this.handleCommand(data)); | ||
this.ctx.on("midwares", (data) => this.handleRegexp(data)); | ||
this.ctx.on("before_send", (data) => { | ||
const { api } = data; | ||
api.adapter.status.sentMsg += 1; | ||
}); | ||
} | ||
midware(callback, priority = 100) { | ||
const data = { callback, priority }; | ||
this[Symbols.midware].add(data); | ||
const dispose = () => this[Symbols.midware].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
command(template, config) { | ||
const command = new Command(template, config); | ||
this[Symbols.command].add(command); | ||
const dispose = () => this[Symbols.command].delete(command); | ||
disposeFactory(this.ctx, dispose); | ||
return command; | ||
} | ||
regexp(match, callback) { | ||
const data = { match, callback }; | ||
this[Symbols.regexp].add(data); | ||
const dispose = () => this[Symbols.regexp].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
// boardcast(type: MessageScope, message: MessageRaw) { | ||
// const send = | ||
// type === 'private' | ||
// ? (api: Api) => api.send_on_message(message, 1) | ||
// : (api: Api) => api.send_on_message(message, 1); | ||
// /* this need support of database... */ | ||
// Object.values(this.botStack).forEach((apis) => { | ||
// apis.forEach((api) => send(api)); | ||
// }); | ||
// } | ||
notify(message) { | ||
const mainAdapterIdentity = Object.keys(this.ctx.config.adapter)[0]; | ||
this.ctx[Symbols.bot].forEach( | ||
(apis) => apis.forEach((api) => { | ||
if (api.adapter.identity !== mainAdapterIdentity) return; | ||
quickFactory( | ||
sendMessageFactory(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
this.ctx.i18n.extends(api.adapter.config.lang) | ||
)(message); | ||
}) | ||
); | ||
} | ||
task(options, callback) { | ||
const [cron, extraOptions] = typeof options === "string" ? [options, {}] : [options.cron, options]; | ||
return new import_cron.CronJob(cron, () => callback(this.ctx), null, extraOptions.start ?? true, extraOptions.timeZone); | ||
} | ||
}; | ||
var message_default = Message; | ||
// src/components/core.ts | ||
var Core = class extends import_fluoro2.Context { | ||
[Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[Symbols.bot] = /* @__PURE__ */ new Map(); | ||
constructor(config) { | ||
super(); | ||
this.provide("config", new config_default(config)); | ||
this.mixin("config", ["config", "pkg"]); | ||
this.provide("message", new message_default(this)); | ||
this.mixin("message", ["midware", "command", "regexp", "notify", "task"]); | ||
this.provide("http", new import_tools8.Http({ validateStatus: () => true })); | ||
this.inject("http"); | ||
this.provide("i18n", new import_i18n2.default({ lang: this.config.global.lang })); | ||
this.inject("i18n"); | ||
this.service("cache", new Cache(this.extends())); | ||
} | ||
}; | ||
__reExport(components_exports, require("./core"), module.exports); | ||
__reExport(components_exports, require("../global"), module.exports); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
ADAPTER_PREFIX, | ||
CUSTOM_PREFIX, | ||
Core, | ||
DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT, | ||
OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX, | ||
Symbols | ||
...require("./core"), | ||
...require("../global") | ||
}); |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -32,3 +32,2 @@ | ||
}; | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
@@ -43,4 +42,2 @@ // If the importer is in node compatibility mode or this is not an ESM | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/components/message.ts | ||
var message_exports = {}; | ||
@@ -52,656 +49,12 @@ __export(message_exports, { | ||
module.exports = __toCommonJS(message_exports); | ||
var import_tools8 = require("@kotori-bot/tools"); | ||
var import_tools = require("@kotori-bot/tools"); | ||
var import_cron = require("cron"); | ||
// src/utils/factory.ts | ||
var import_tools7 = require("@kotori-bot/tools"); | ||
// src/types/message.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
import_tsukiko.default.Union([import_tsukiko.default.Literal("string"), import_tsukiko.default.Literal("number")]), | ||
import_tsukiko.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Cache: () => Cache, | ||
Command: () => Command, | ||
CommandAccess: () => CommandAccess, | ||
CommandError: () => CommandError, | ||
Container: () => Container, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
DevError: () => DevError, | ||
Elements: () => Elements, | ||
KotoriError: () => KotoriError, | ||
MessageScope: () => MessageScope, | ||
ModuleError: () => ModuleError, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols, | ||
cancelFactory: () => cancelFactory, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
confirmFactory: () => confirmFactory, | ||
disposeFactory: () => disposeFactory, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema, | ||
formatFactory: () => formatFactory, | ||
promptFactory: () => promptFactory, | ||
quickFactory: () => quickFactory, | ||
sendMessageFactory: () => sendMessageFactory | ||
}); | ||
__reExport(src_exports, require("fluoro")); | ||
// src/components/core.ts | ||
var import_tools4 = require("@kotori-bot/tools"); | ||
var import_i18n2 = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro2 = require("fluoro"); | ||
// src/components/config.ts | ||
var import_tsukiko2 = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_tools = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko2.default.Object({ | ||
name: import_tsukiko2.default.String(), | ||
version: import_tsukiko2.default.String(), | ||
description: import_tsukiko2.default.String(), | ||
main: import_tsukiko2.default.String(), | ||
license: import_tsukiko2.default.Literal("GPL-3.0"), | ||
author: import_tsukiko2.default.String() | ||
}); | ||
var Config = class { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
const info = (0, import_tools.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
if (!info || Object.values(info).length === 0) { | ||
process.stderr.write(`Cannot find kotori-bot package.json | ||
`); | ||
process.exit(); | ||
} | ||
const result = packageInfoSchema.parseSafe(info); | ||
if (!result.value) { | ||
process.stderr.write(`File package.json format error: ${result.error.message} | ||
`); | ||
process.exit(); | ||
} | ||
this.pkg = result.data; | ||
} | ||
}; | ||
var config_default = Config; | ||
// src/service/elements.ts | ||
var import_tools2 = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
default(...args) { | ||
(0, import_tools2.none)(this, args); | ||
return ""; | ||
} | ||
at(target, ...extra) { | ||
return this.default(target, extra); | ||
} | ||
image(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
voice(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
video(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
face(id, ...extra) { | ||
return this.default(id, extra); | ||
} | ||
file(data, ...extra) { | ||
return this.default(data, extra); | ||
} | ||
supports() { | ||
const supports = []; | ||
const keys = ["at", "image", "voice", "video", "face", "file"]; | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
var elements_default = Elements; | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
var commandError_default = CommandError; | ||
// src/service/adapter.ts | ||
function setProxy(api, ctx) { | ||
const proxy = Object.create(api); | ||
proxy.sendPrivateMsg = new Proxy(api.sendPrivateMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendPrivateMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
proxy.sendGroupMsg = new Proxy(api.sendGroupMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendGroupMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
return proxy; | ||
} | ||
function error(type, data) { | ||
return new commandError_default(Object.assign(data ?? {}, { type })); | ||
} | ||
var Adapter = class { | ||
constructor(ctx, config, identity, Api2, el = new elements_default()) { | ||
this.ctx = ctx; | ||
this.config = config; | ||
this.identity = identity; | ||
this.platform = config.extends; | ||
this.api = setProxy(new Api2(this), this.ctx); | ||
this.elements = el; | ||
if (!this.ctx[Symbols.bot].get(this.platform)) this.ctx[Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[Symbols.bot].get(this.platform).add(this.api); | ||
} | ||
online() { | ||
if (this.status.value !== "offline") return; | ||
this.status.value = "online"; | ||
this.ctx.emit("status", { adapter: this, status: "online" }); | ||
} | ||
offline() { | ||
if (this.status.value !== "online") return; | ||
this.status.value = "offline"; | ||
this.status.offlineTimes += 1; | ||
this.ctx.emit("status", { adapter: this, status: "offline" }); | ||
} | ||
session(type, data) { | ||
const i18n = this.ctx.i18n.extends(this.config.lang); | ||
const send = sendMessageFactory(this, type, data); | ||
const format = formatFactory(i18n); | ||
const quick = quickFactory(send, i18n); | ||
const prompt = promptFactory(quick, this, data); | ||
const confirm = confirmFactory(quick, this, data); | ||
const { api, elements: el } = this; | ||
this.ctx.emit( | ||
type, | ||
...[{ ...data, api, el, send, i18n, format, quick, prompt, confirm, error }] | ||
); | ||
} | ||
ctx; | ||
config; | ||
identity; | ||
platform; | ||
api; | ||
elements; | ||
status = { | ||
value: "offline", | ||
createTime: /* @__PURE__ */ new Date(), | ||
lastMsgTime: null, | ||
receivedMsg: 0, | ||
sentMsg: 0, | ||
offlineTimes: 0 | ||
}; | ||
selfId = -1; | ||
}; | ||
// src/service/api.ts | ||
var import_tools3 = require("@kotori-bot/tools"); | ||
var Api = class { | ||
adapter; | ||
constructor(adapter) { | ||
this.adapter = adapter; | ||
} | ||
sendPrivateMsg(message, userId, ...extra) { | ||
(0, import_tools3.none)(this, message, userId, extra); | ||
} | ||
sendGroupMsg(message, groupId, ...extra) { | ||
(0, import_tools3.none)(this, message, groupId, extra, extra); | ||
} | ||
deleteMsg(messageId, ...extra) { | ||
(0, import_tools3.none)(this, messageId, extra); | ||
} | ||
setGroupName(groupId, groupName, ...extra) { | ||
(0, import_tools3.none)(this, groupId, groupName, extra); | ||
} | ||
setGroupAvatar(groupId, image, ...extra) { | ||
(0, import_tools3.none)(this, groupId, image, extra); | ||
} | ||
setGroupAdmin(groupId, userId, enable, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, enable, extra); | ||
} | ||
setGroupCard(groupId, userId, card, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, card, extra); | ||
} | ||
setGroupBan(groupId, userId, time, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, time, extra); | ||
} | ||
sendGroupNotice(groupId, content, image, ...extra) { | ||
(0, import_tools3.none)(this, groupId, content, image, extra); | ||
} | ||
setGroupKick(groupId, userId, ...extra) { | ||
(0, import_tools3.none)(this, groupId, userId, extra); | ||
} | ||
setGroupLeave(groupId, ...extra) { | ||
(0, import_tools3.none)(this, groupId, groupId, extra); | ||
} | ||
}; | ||
// src/service/cache.ts | ||
var import_fluoro = require("fluoro"); | ||
var Cache = class extends import_fluoro.Service { | ||
cache; | ||
constructor(ctx) { | ||
super(ctx, {}, "cache"); | ||
} | ||
start() { | ||
if (this.cache) return; | ||
this.cache = /* @__PURE__ */ new Map(); | ||
} | ||
stop() { | ||
this.cache?.forEach((el) => el.clear()); | ||
this.cache?.clear(); | ||
delete this.cache; | ||
} | ||
getContainer() { | ||
const key = this.ctx.identity ?? "root"; | ||
if (!this.cache.has(key)) this.cache.set(key, /* @__PURE__ */ new Map()); | ||
return this.cache.get(key); | ||
} | ||
get(prop) { | ||
return this.getContainer().get(prop); | ||
} | ||
set(prop, value) { | ||
this.getContainer().set(prop, value); | ||
} | ||
}; | ||
// src/components/core.ts | ||
var Core = class extends import_fluoro2.Context { | ||
[Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[Symbols.bot] = /* @__PURE__ */ new Map(); | ||
constructor(config) { | ||
super(); | ||
this.provide("config", new config_default(config)); | ||
this.mixin("config", ["config", "pkg"]); | ||
this.provide("message", new message_default(this)); | ||
this.mixin("message", ["midware", "command", "regexp", "notify", "task"]); | ||
this.provide("http", new import_tools4.Http({ validateStatus: () => true })); | ||
this.inject("http"); | ||
this.provide("i18n", new import_i18n2.default({ lang: this.config.global.lang })); | ||
this.inject("i18n"); | ||
this.service("cache", new Cache(this.extends())); | ||
} | ||
}; | ||
// src/utils/command.ts | ||
var import_tools5 = require("@kotori-bot/tools"); | ||
var import_minimist = __toESM(require("minimist")); | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
if (type === "boolean") return value !== "false" && !!value; | ||
if (type === "number") { | ||
if (typeof value === "number") return value; | ||
if (value === true) return 1; | ||
if (value === false) return 0; | ||
const float = parseFloat(value); | ||
const int = parseInt(value, 10); | ||
return float === int ? int : float; | ||
} | ||
return value.toString(); | ||
} | ||
var Command = class { | ||
static run(input, data) { | ||
let starts = ""; | ||
[data.root, ...data.alias].forEach((el) => { | ||
if (starts) return; | ||
if (input.startsWith(`${el} `) || input === el) starts = el; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
const opts = { | ||
string: [], | ||
boolean: [], | ||
alias: {} | ||
}; | ||
data.options.forEach((option) => { | ||
if (option.type === "string") { | ||
opts.string.push(option.realname); | ||
} else if (option.type === "boolean") { | ||
opts.boolean.push(option.realname); | ||
} | ||
opts.alias[option.realname] = option.name; | ||
}); | ||
const arr = (0, import_tools5.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
const args = result._; | ||
const count = { | ||
expected: data.args.filter((el) => !el.optional).length, | ||
reality: args.length | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
let error2; | ||
data.args.forEach((val, index) => { | ||
if (error2 || index > 0 && !args[index - 1]) return; | ||
if (!args[index] && val.default) { | ||
args[index] = val.default; | ||
return; | ||
} | ||
if (val.rest || !args[index]) return; | ||
args[index] = handleDefaultValue(args[index], val.type); | ||
if (!Number.isNaN(args[index])) return; | ||
error2 = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
if (error2) return error2; | ||
const options = {}; | ||
data.options.forEach((val) => { | ||
if (!(val.realname in result)) return; | ||
options[val.realname] = Array.isArray(result[val.realname]) ? result[val.realname][0] : result[val.realname]; | ||
options[val.realname] = handleDefaultValue(options[val.realname], val.type); | ||
if (Number.isNaN(options[val.realname])) | ||
error2 = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
if (error2) return error2; | ||
return { | ||
args: data.args.length > 0 && data.args[data.args.length - 1].rest ? args : args.slice(0, data.args.length), | ||
options | ||
}; | ||
} | ||
template; | ||
meta = { | ||
root: "", | ||
alias: [], | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
args: [], | ||
options: [] | ||
}; | ||
constructor(template, config) { | ||
this.template = template; | ||
this.meta = Object.assign(this.meta, config); | ||
this.parse(); | ||
} | ||
parse() { | ||
const [str, description] = this.template.trim().split(" - "); | ||
this.meta.description = description; | ||
const requiredIndex = str.indexOf(" <"); | ||
const optionalIndex = str.indexOf(" ["); | ||
if (requiredIndex === -1 && optionalIndex === -1) { | ||
this.meta.root = str.trim(); | ||
return; | ||
} | ||
if (requiredIndex !== -1 && (optionalIndex === -1 || requiredIndex < optionalIndex)) { | ||
this.meta.root = str.substring(0, requiredIndex).trim(); | ||
} else { | ||
this.meta.root = str.substring(0, optionalIndex).trim(); | ||
} | ||
const args = (0, import_minimist.default)(str.split(" "))._; | ||
args.forEach((arg) => { | ||
const current = this.meta.args[this.meta.args.length - 1]; | ||
if (current && current.rest) return; | ||
let result = optionalParamMatch.exec(arg); | ||
if (result) { | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type, | ||
rest: !!result[1], | ||
optional: true, | ||
default: result[6] ? handleDefaultValue(result[6], type) : void 0 | ||
}); | ||
} | ||
result = requiredParamMatch.exec(arg); | ||
if (!result || !result[2]) return; | ||
if (!result[6] && current && current.optional) return; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
optional: false | ||
}); | ||
}); | ||
} | ||
alias(alias) { | ||
if (typeof alias === "string") this.meta.alias.push(alias); | ||
else this.meta.alias.push(...alias); | ||
return this; | ||
} | ||
scope(scope) { | ||
this.meta.scope = scope; | ||
return this; | ||
} | ||
access(access) { | ||
this.meta.access = access; | ||
return this; | ||
} | ||
option(name, template) { | ||
const [str, description] = template.trim().split(" "); | ||
const [realname, type] = str.split(":"); | ||
this.meta.options.push({ | ||
realname, | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
}); | ||
return this; | ||
} | ||
action(callback) { | ||
this.meta.action = callback; | ||
return this; | ||
} | ||
help(text) { | ||
this.meta.help = text; | ||
return this; | ||
} | ||
}; | ||
// src/utils/container.ts | ||
var import_tools6 = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
constructor() { | ||
(0, import_tools6.none)(); | ||
} | ||
static instance = {}; | ||
static setInstance(ctx) { | ||
this.instance = ctx; | ||
} | ||
static getInstance() { | ||
return this.instance; | ||
} | ||
static getMixin() { | ||
return Object.assign( | ||
_Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("@kotori-bot/tools")); | ||
__reExport(src_exports, require("@kotori-bot/i18n")); | ||
__reExport(src_exports, require("tsukiko")); | ||
// src/utils/factory.ts | ||
function disposeFactory(ctx, dispose) { | ||
ctx.once("dispose_module", (data) => { | ||
if ((typeof data.instance === "object" ? data.instance.name : data.instance) !== ctx.identity) { | ||
disposeFactory(ctx, dispose); | ||
return; | ||
} | ||
dispose(); | ||
}); | ||
} | ||
function cancelFactory() { | ||
return { | ||
get() { | ||
return () => this.fn(); | ||
}, | ||
fn() { | ||
this.value = true; | ||
}, | ||
value: false | ||
}; | ||
} | ||
function formatFactory(i18n) { | ||
return (template, data) => { | ||
const params = data; | ||
if (Array.isArray(params)) { | ||
let str = i18n.locale(template); | ||
params.forEach((value, index) => { | ||
str = str.replaceAll(`{${index}}`, i18n.locale(typeof value === "string" ? value : String(value))); | ||
}); | ||
return str; | ||
} | ||
Object.keys(params).forEach((key) => { | ||
if (typeof params[key] !== "string") params[key] = String(params[key]); | ||
params[key] = i18n.locale(params[key]); | ||
}); | ||
return (0, import_tools7.stringTemp)(i18n.locale(template), params); | ||
}; | ||
} | ||
function sendMessageFactory(adapter, type, data) { | ||
if ((data.type === 1 /* GROUP */ || type.includes("group")) && "groupId" in data) { | ||
return (message) => { | ||
adapter.api.sendGroupMsg(message, data.groupId, data.extra); | ||
}; | ||
} | ||
return (message) => { | ||
adapter.api.sendPrivateMsg(message, data.userId, data.extra); | ||
}; | ||
} | ||
function quickFactory(send, i18n) { | ||
return async (message) => { | ||
const msg = await message; | ||
if (!msg || msg instanceof CommandError) return; | ||
if (typeof msg === "string") { | ||
send(i18n.locale(msg)); | ||
return; | ||
} | ||
send(formatFactory(i18n)(...msg)); | ||
}; | ||
} | ||
function isSameSender(adapter, data, session) { | ||
return session.api.adapter.identity === adapter.identity && session.api.adapter.platform === adapter.platform && session.type === data.type && session.groupId === data.groupId && session.userId === data.userId && "messageId" in data && session.messageId !== data.messageId; | ||
} | ||
function promptFactory(quick, adapter, data) { | ||
return (message) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(message ?? "corei18n.template.prompt").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
function confirmFactory(quick, adapter, data) { | ||
return (options) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(options?.message ?? "corei18n.template.confirm").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
// src/components/message.ts | ||
var Message = class { | ||
[Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[Symbols.command] = /* @__PURE__ */ new Set(); | ||
[Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
var import_factory = require("../utils/factory"); | ||
var import_command = require("../utils/command"); | ||
var import_commandError = __toESM(require("../utils/commandError")); | ||
var import_global = require("../global"); | ||
class Message { | ||
[import_global.Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[import_global.Symbols.command] = /* @__PURE__ */ new Set(); | ||
[import_global.Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
handleMidware(session) { | ||
@@ -712,3 +65,3 @@ const { api } = session; | ||
api.adapter.status.receivedMsg += 1; | ||
this[Symbols.midware].forEach((val) => midwares.push(val)); | ||
this[import_global.Symbols.midware].forEach((val) => midwares.push(val)); | ||
midwares = midwares.sort((first, second) => first.priority - second.priority); | ||
@@ -729,3 +82,3 @@ let lastMidwareNum = -1; | ||
if (!data.isPass) return; | ||
this[Symbols.regexp].forEach((data2) => { | ||
this[import_global.Symbols.regexp].forEach((data2) => { | ||
const result = session.message.match(data2.match); | ||
@@ -743,19 +96,19 @@ if (!result) return; | ||
session, | ||
raw: (0, import_tools8.stringRightSplit)(session.message, prefix) | ||
raw: (0, import_tools.stringRightSplit)(session.message, prefix) | ||
}; | ||
this.ctx.emit("before_parse", params); | ||
const cancel = cancelFactory(); | ||
const cancel = (0, import_factory.cancelFactory)(); | ||
this.ctx.emit("before_command", { cancel: cancel.get(), ...params }); | ||
if (cancel.value) return; | ||
let matched; | ||
this[Symbols.command].forEach(async (cmd) => { | ||
this[import_global.Symbols.command].forEach(async (cmd) => { | ||
if (matched || !cmd.meta.action) return; | ||
const result = Command.run(params.raw, cmd.meta); | ||
if (result instanceof commandError_default && result.value.type === "unknown") return; | ||
const result = import_command.Command.run(params.raw, cmd.meta); | ||
if (result instanceof import_commandError.default && result.value.type === "unknown") return; | ||
matched = cmd; | ||
this.ctx.emit("parse", { command: cmd, result, ...params, cancel: cancel.get() }); | ||
if (cancel.value || result instanceof commandError_default) return; | ||
if (cancel.value || result instanceof import_commandError.default) return; | ||
try { | ||
const executed = await cmd.meta.action({ args: result.args, options: result.options }, session); | ||
if (executed instanceof commandError_default) { | ||
if (executed instanceof import_commandError.default) { | ||
this.ctx.emit("command", { command: cmd, result: executed, ...params }); | ||
@@ -767,9 +120,9 @@ return; | ||
command: cmd, | ||
result: executed instanceof commandError_default ? result : executed, | ||
result: executed instanceof import_commandError.default ? result : executed, | ||
...params | ||
}); | ||
} catch (error2) { | ||
} catch (error) { | ||
this.ctx.emit("command", { | ||
command: matched, | ||
result: new commandError_default({ type: "error", error: error2 }), | ||
result: new import_commandError.default({ type: "error", error }), | ||
...params | ||
@@ -781,4 +134,4 @@ }); | ||
this.ctx.emit("parse", { | ||
command: new Command(""), | ||
result: new commandError_default({ type: "unknown", input: params.raw }), | ||
command: new import_command.Command(""), | ||
result: new import_commandError.default({ type: "unknown", input: params.raw }), | ||
...params, | ||
@@ -801,12 +154,12 @@ cancel: cancel.get() | ||
const data = { callback, priority }; | ||
this[Symbols.midware].add(data); | ||
const dispose = () => this[Symbols.midware].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
this[import_global.Symbols.midware].add(data); | ||
const dispose = () => this[import_global.Symbols.midware].delete(data); | ||
(0, import_factory.disposeFactory)(this.ctx, dispose); | ||
return dispose; | ||
} | ||
command(template, config) { | ||
const command = new Command(template, config); | ||
this[Symbols.command].add(command); | ||
const dispose = () => this[Symbols.command].delete(command); | ||
disposeFactory(this.ctx, dispose); | ||
const command = new import_command.Command(template, config); | ||
this[import_global.Symbols.command].add(command); | ||
const dispose = () => this[import_global.Symbols.command].delete(command); | ||
(0, import_factory.disposeFactory)(this.ctx, dispose); | ||
return command; | ||
@@ -816,5 +169,5 @@ } | ||
const data = { match, callback }; | ||
this[Symbols.regexp].add(data); | ||
const dispose = () => this[Symbols.regexp].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
this[import_global.Symbols.regexp].add(data); | ||
const dispose = () => this[import_global.Symbols.regexp].delete(data); | ||
(0, import_factory.disposeFactory)(this.ctx, dispose); | ||
return dispose; | ||
@@ -834,7 +187,7 @@ } | ||
const mainAdapterIdentity = Object.keys(this.ctx.config.adapter)[0]; | ||
this.ctx[Symbols.bot].forEach( | ||
this.ctx[import_global.Symbols.bot].forEach( | ||
(apis) => apis.forEach((api) => { | ||
if (api.adapter.identity !== mainAdapterIdentity) return; | ||
quickFactory( | ||
sendMessageFactory(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
(0, import_factory.quickFactory)( | ||
(0, import_factory.sendMessageFactory)(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
this.ctx.i18n.extends(api.adapter.config.lang) | ||
@@ -849,3 +202,3 @@ )(message); | ||
} | ||
}; | ||
} | ||
var message_default = Message; | ||
@@ -852,0 +205,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/global/constants.ts | ||
var constants_exports = {}; | ||
@@ -46,9 +44,9 @@ __export(constants_exports, { | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
const OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
const PLUGIN_PREFIX = "kotori-plugin-"; | ||
const DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
const ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
const CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
const DEFAULT_PORT = 720; | ||
const DEFAULT_CORE_CONFIG = { | ||
global: { | ||
@@ -55,0 +53,0 @@ lang: import_i18n.DEFAULT_LANG, |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -18,6 +18,2 @@ | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
@@ -31,56 +27,12 @@ if (from && typeof from === "object" || typeof from === "function") { | ||
}; | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/global/index.ts | ||
var global_exports = {}; | ||
__export(global_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols | ||
}); | ||
module.exports = __toCommonJS(global_exports); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
__reExport(global_exports, require("./constants"), module.exports); | ||
__reExport(global_exports, require("./symbols"), module.exports); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
ADAPTER_PREFIX, | ||
CUSTOM_PREFIX, | ||
DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT, | ||
OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX, | ||
Symbols | ||
...require("./constants"), | ||
...require("./symbols") | ||
}); |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/global/symbols.ts | ||
var symbols_exports = {}; | ||
@@ -40,3 +38,3 @@ __export(symbols_exports, { | ||
module.exports = __toCommonJS(symbols_exports); | ||
var Symbols = class { | ||
class Symbols { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
@@ -49,3 +47,3 @@ static bot = Symbol.for("kotori.core.bot"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
} | ||
var symbols_default = Symbols; | ||
@@ -52,0 +50,0 @@ // Annotate the CommonJS export names for ESM import in node: |
855
lib/index.js
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,16 +9,10 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
"use strict"; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
@@ -33,803 +27,15 @@ if (from && typeof from === "object" || typeof from === "function") { | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
// If the importer is in node compatibility mode or this is not an ESM | ||
// file that has been converted to a CommonJS file using a Babel- | ||
// compatible transform (i.e. "__esModule" has not been set), then set | ||
// "default" to the CommonJS "module.exports" for node compatibility. | ||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
mod | ||
)); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Cache: () => Cache, | ||
Command: () => Command, | ||
CommandAccess: () => CommandAccess, | ||
CommandError: () => CommandError, | ||
Container: () => Container, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
DevError: () => DevError, | ||
Elements: () => Elements, | ||
KotoriError: () => KotoriError, | ||
MessageScope: () => MessageScope, | ||
ModuleError: () => ModuleError, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols, | ||
cancelFactory: () => cancelFactory, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
confirmFactory: () => confirmFactory, | ||
disposeFactory: () => disposeFactory, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema, | ||
formatFactory: () => formatFactory, | ||
promptFactory: () => promptFactory, | ||
quickFactory: () => quickFactory, | ||
sendMessageFactory: () => sendMessageFactory | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
__reExport(src_exports, require("fluoro"), module.exports); | ||
// src/components/core.ts | ||
var import_tools7 = require("@kotori-bot/tools"); | ||
var import_i18n2 = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro2 = require("fluoro"); | ||
// src/components/config.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_tools = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko.default.Object({ | ||
name: import_tsukiko.default.String(), | ||
version: import_tsukiko.default.String(), | ||
description: import_tsukiko.default.String(), | ||
main: import_tsukiko.default.String(), | ||
license: import_tsukiko.default.Literal("GPL-3.0"), | ||
author: import_tsukiko.default.String() | ||
}); | ||
var Config = class { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
const info = (0, import_tools.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
if (!info || Object.values(info).length === 0) { | ||
process.stderr.write(`Cannot find kotori-bot package.json | ||
`); | ||
process.exit(); | ||
} | ||
const result = packageInfoSchema.parseSafe(info); | ||
if (!result.value) { | ||
process.stderr.write(`File package.json format error: ${result.error.message} | ||
`); | ||
process.exit(); | ||
} | ||
this.pkg = result.data; | ||
} | ||
}; | ||
var config_default = Config; | ||
// src/components/message.ts | ||
var import_tools4 = require("@kotori-bot/tools"); | ||
var import_cron = require("cron"); | ||
// src/utils/factory.ts | ||
var import_tools2 = require("@kotori-bot/tools"); | ||
// src/types/message.ts | ||
var import_tsukiko2 = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko2.default.Union([ | ||
import_tsukiko2.default.Union([import_tsukiko2.default.Literal("string"), import_tsukiko2.default.Literal("number")]), | ||
import_tsukiko2.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko2.default.Union([import_tsukiko2.default.Number(), import_tsukiko2.default.String()]); | ||
// src/utils/factory.ts | ||
function disposeFactory(ctx, dispose) { | ||
ctx.once("dispose_module", (data) => { | ||
if ((typeof data.instance === "object" ? data.instance.name : data.instance) !== ctx.identity) { | ||
disposeFactory(ctx, dispose); | ||
return; | ||
} | ||
dispose(); | ||
}); | ||
} | ||
function cancelFactory() { | ||
return { | ||
get() { | ||
return () => this.fn(); | ||
}, | ||
fn() { | ||
this.value = true; | ||
}, | ||
value: false | ||
}; | ||
} | ||
function formatFactory(i18n) { | ||
return (template, data) => { | ||
const params = data; | ||
if (Array.isArray(params)) { | ||
let str = i18n.locale(template); | ||
params.forEach((value, index) => { | ||
str = str.replaceAll(`{${index}}`, i18n.locale(typeof value === "string" ? value : String(value))); | ||
}); | ||
return str; | ||
} | ||
Object.keys(params).forEach((key) => { | ||
if (typeof params[key] !== "string") params[key] = String(params[key]); | ||
params[key] = i18n.locale(params[key]); | ||
}); | ||
return (0, import_tools2.stringTemp)(i18n.locale(template), params); | ||
}; | ||
} | ||
function sendMessageFactory(adapter, type, data) { | ||
if ((data.type === 1 /* GROUP */ || type.includes("group")) && "groupId" in data) { | ||
return (message) => { | ||
adapter.api.sendGroupMsg(message, data.groupId, data.extra); | ||
}; | ||
} | ||
return (message) => { | ||
adapter.api.sendPrivateMsg(message, data.userId, data.extra); | ||
}; | ||
} | ||
function quickFactory(send, i18n) { | ||
return async (message) => { | ||
const msg = await message; | ||
if (!msg || msg instanceof CommandError) return; | ||
if (typeof msg === "string") { | ||
send(i18n.locale(msg)); | ||
return; | ||
} | ||
send(formatFactory(i18n)(...msg)); | ||
}; | ||
} | ||
function isSameSender(adapter, data, session) { | ||
return session.api.adapter.identity === adapter.identity && session.api.adapter.platform === adapter.platform && session.type === data.type && session.groupId === data.groupId && session.userId === data.userId && "messageId" in data && session.messageId !== data.messageId; | ||
} | ||
function promptFactory(quick, adapter, data) { | ||
return (message) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(message ?? "corei18n.template.prompt").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
function confirmFactory(quick, adapter, data) { | ||
return (options) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(options?.message ?? "corei18n.template.confirm").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
// src/utils/command.ts | ||
var import_tools3 = require("@kotori-bot/tools"); | ||
var import_minimist = __toESM(require("minimist")); | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
var commandError_default = CommandError; | ||
// src/utils/command.ts | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
if (type === "boolean") return value !== "false" && !!value; | ||
if (type === "number") { | ||
if (typeof value === "number") return value; | ||
if (value === true) return 1; | ||
if (value === false) return 0; | ||
const float = parseFloat(value); | ||
const int = parseInt(value, 10); | ||
return float === int ? int : float; | ||
} | ||
return value.toString(); | ||
} | ||
var Command = class { | ||
static run(input, data) { | ||
let starts = ""; | ||
[data.root, ...data.alias].forEach((el) => { | ||
if (starts) return; | ||
if (input.startsWith(`${el} `) || input === el) starts = el; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
const opts = { | ||
string: [], | ||
boolean: [], | ||
alias: {} | ||
}; | ||
data.options.forEach((option) => { | ||
if (option.type === "string") { | ||
opts.string.push(option.realname); | ||
} else if (option.type === "boolean") { | ||
opts.boolean.push(option.realname); | ||
} | ||
opts.alias[option.realname] = option.name; | ||
}); | ||
const arr = (0, import_tools3.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
const args = result._; | ||
const count = { | ||
expected: data.args.filter((el) => !el.optional).length, | ||
reality: args.length | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
let error2; | ||
data.args.forEach((val, index) => { | ||
if (error2 || index > 0 && !args[index - 1]) return; | ||
if (!args[index] && val.default) { | ||
args[index] = val.default; | ||
return; | ||
} | ||
if (val.rest || !args[index]) return; | ||
args[index] = handleDefaultValue(args[index], val.type); | ||
if (!Number.isNaN(args[index])) return; | ||
error2 = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
if (error2) return error2; | ||
const options = {}; | ||
data.options.forEach((val) => { | ||
if (!(val.realname in result)) return; | ||
options[val.realname] = Array.isArray(result[val.realname]) ? result[val.realname][0] : result[val.realname]; | ||
options[val.realname] = handleDefaultValue(options[val.realname], val.type); | ||
if (Number.isNaN(options[val.realname])) | ||
error2 = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
if (error2) return error2; | ||
return { | ||
args: data.args.length > 0 && data.args[data.args.length - 1].rest ? args : args.slice(0, data.args.length), | ||
options | ||
}; | ||
} | ||
template; | ||
meta = { | ||
root: "", | ||
alias: [], | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
args: [], | ||
options: [] | ||
}; | ||
constructor(template, config) { | ||
this.template = template; | ||
this.meta = Object.assign(this.meta, config); | ||
this.parse(); | ||
} | ||
parse() { | ||
const [str, description] = this.template.trim().split(" - "); | ||
this.meta.description = description; | ||
const requiredIndex = str.indexOf(" <"); | ||
const optionalIndex = str.indexOf(" ["); | ||
if (requiredIndex === -1 && optionalIndex === -1) { | ||
this.meta.root = str.trim(); | ||
return; | ||
} | ||
if (requiredIndex !== -1 && (optionalIndex === -1 || requiredIndex < optionalIndex)) { | ||
this.meta.root = str.substring(0, requiredIndex).trim(); | ||
} else { | ||
this.meta.root = str.substring(0, optionalIndex).trim(); | ||
} | ||
const args = (0, import_minimist.default)(str.split(" "))._; | ||
args.forEach((arg) => { | ||
const current = this.meta.args[this.meta.args.length - 1]; | ||
if (current && current.rest) return; | ||
let result = optionalParamMatch.exec(arg); | ||
if (result) { | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type, | ||
rest: !!result[1], | ||
optional: true, | ||
default: result[6] ? handleDefaultValue(result[6], type) : void 0 | ||
}); | ||
} | ||
result = requiredParamMatch.exec(arg); | ||
if (!result || !result[2]) return; | ||
if (!result[6] && current && current.optional) return; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
optional: false | ||
}); | ||
}); | ||
} | ||
alias(alias) { | ||
if (typeof alias === "string") this.meta.alias.push(alias); | ||
else this.meta.alias.push(...alias); | ||
return this; | ||
} | ||
scope(scope) { | ||
this.meta.scope = scope; | ||
return this; | ||
} | ||
access(access) { | ||
this.meta.access = access; | ||
return this; | ||
} | ||
option(name, template) { | ||
const [str, description] = template.trim().split(" "); | ||
const [realname, type] = str.split(":"); | ||
this.meta.options.push({ | ||
realname, | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
}); | ||
return this; | ||
} | ||
action(callback) { | ||
this.meta.action = callback; | ||
return this; | ||
} | ||
help(text) { | ||
this.meta.help = text; | ||
return this; | ||
} | ||
}; | ||
// src/components/message.ts | ||
var Message = class { | ||
[Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[Symbols.command] = /* @__PURE__ */ new Set(); | ||
[Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
handleMidware(session) { | ||
const { api } = session; | ||
let isPass = true; | ||
let midwares = []; | ||
api.adapter.status.receivedMsg += 1; | ||
this[Symbols.midware].forEach((val) => midwares.push(val)); | ||
midwares = midwares.sort((first, second) => first.priority - second.priority); | ||
let lastMidwareNum = -1; | ||
while (midwares.length > 0) { | ||
if (lastMidwareNum === midwares.length) { | ||
isPass = false; | ||
break; | ||
} | ||
lastMidwareNum = midwares.length; | ||
session.quick(midwares[0].callback(() => midwares.shift(), session)); | ||
} | ||
this.ctx.emit("midwares", { isPass, session }); | ||
} | ||
async handleRegexp(data) { | ||
const { session } = data; | ||
if (!data.isPass) return; | ||
this[Symbols.regexp].forEach((data2) => { | ||
const result = session.message.match(data2.match); | ||
if (!result) return; | ||
session.quick(data2.callback(result, session)); | ||
this.ctx.emit("regexp", { result, session, regexp: data2.match, raw: session.message }); | ||
}); | ||
} | ||
handleCommand(data) { | ||
const { session } = data; | ||
const prefix = session.api.adapter.config["command-prefix"] ?? this.ctx.config.global["command-prefix"]; | ||
if (!session.message.startsWith(prefix)) return; | ||
const params = { | ||
session, | ||
raw: (0, import_tools4.stringRightSplit)(session.message, prefix) | ||
}; | ||
this.ctx.emit("before_parse", params); | ||
const cancel = cancelFactory(); | ||
this.ctx.emit("before_command", { cancel: cancel.get(), ...params }); | ||
if (cancel.value) return; | ||
let matched; | ||
this[Symbols.command].forEach(async (cmd) => { | ||
if (matched || !cmd.meta.action) return; | ||
const result = Command.run(params.raw, cmd.meta); | ||
if (result instanceof commandError_default && result.value.type === "unknown") return; | ||
matched = cmd; | ||
this.ctx.emit("parse", { command: cmd, result, ...params, cancel: cancel.get() }); | ||
if (cancel.value || result instanceof commandError_default) return; | ||
try { | ||
const executed = await cmd.meta.action({ args: result.args, options: result.options }, session); | ||
if (executed instanceof commandError_default) { | ||
this.ctx.emit("command", { command: cmd, result: executed, ...params }); | ||
return; | ||
} | ||
if (executed !== void 0) session.quick(executed); | ||
this.ctx.emit("command", { | ||
command: cmd, | ||
result: executed instanceof commandError_default ? result : executed, | ||
...params | ||
}); | ||
} catch (error2) { | ||
this.ctx.emit("command", { | ||
command: matched, | ||
result: new commandError_default({ type: "error", error: error2 }), | ||
...params | ||
}); | ||
} | ||
}); | ||
if (matched) return; | ||
this.ctx.emit("parse", { | ||
command: new Command(""), | ||
result: new commandError_default({ type: "unknown", input: params.raw }), | ||
...params, | ||
cancel: cancel.get() | ||
}); | ||
} | ||
ctx; | ||
constructor(ctx) { | ||
this.ctx = ctx; | ||
this.ctx.on("on_message", (session) => this.handleMidware(session)); | ||
this.ctx.on("midwares", (data) => this.handleCommand(data)); | ||
this.ctx.on("midwares", (data) => this.handleRegexp(data)); | ||
this.ctx.on("before_send", (data) => { | ||
const { api } = data; | ||
api.adapter.status.sentMsg += 1; | ||
}); | ||
} | ||
midware(callback, priority = 100) { | ||
const data = { callback, priority }; | ||
this[Symbols.midware].add(data); | ||
const dispose = () => this[Symbols.midware].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
command(template, config) { | ||
const command = new Command(template, config); | ||
this[Symbols.command].add(command); | ||
const dispose = () => this[Symbols.command].delete(command); | ||
disposeFactory(this.ctx, dispose); | ||
return command; | ||
} | ||
regexp(match, callback) { | ||
const data = { match, callback }; | ||
this[Symbols.regexp].add(data); | ||
const dispose = () => this[Symbols.regexp].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
// boardcast(type: MessageScope, message: MessageRaw) { | ||
// const send = | ||
// type === 'private' | ||
// ? (api: Api) => api.send_on_message(message, 1) | ||
// : (api: Api) => api.send_on_message(message, 1); | ||
// /* this need support of database... */ | ||
// Object.values(this.botStack).forEach((apis) => { | ||
// apis.forEach((api) => send(api)); | ||
// }); | ||
// } | ||
notify(message) { | ||
const mainAdapterIdentity = Object.keys(this.ctx.config.adapter)[0]; | ||
this.ctx[Symbols.bot].forEach( | ||
(apis) => apis.forEach((api) => { | ||
if (api.adapter.identity !== mainAdapterIdentity) return; | ||
quickFactory( | ||
sendMessageFactory(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
this.ctx.i18n.extends(api.adapter.config.lang) | ||
)(message); | ||
}) | ||
); | ||
} | ||
task(options, callback) { | ||
const [cron, extraOptions] = typeof options === "string" ? [options, {}] : [options.cron, options]; | ||
return new import_cron.CronJob(cron, () => callback(this.ctx), null, extraOptions.start ?? true, extraOptions.timeZone); | ||
} | ||
}; | ||
var message_default = Message; | ||
// src/service/elements.ts | ||
var import_tools5 = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
default(...args) { | ||
(0, import_tools5.none)(this, args); | ||
return ""; | ||
} | ||
at(target, ...extra) { | ||
return this.default(target, extra); | ||
} | ||
image(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
voice(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
video(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
face(id, ...extra) { | ||
return this.default(id, extra); | ||
} | ||
file(data, ...extra) { | ||
return this.default(data, extra); | ||
} | ||
supports() { | ||
const supports = []; | ||
const keys = ["at", "image", "voice", "video", "face", "file"]; | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
var elements_default = Elements; | ||
// src/service/adapter.ts | ||
function setProxy(api, ctx) { | ||
const proxy = Object.create(api); | ||
proxy.sendPrivateMsg = new Proxy(api.sendPrivateMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendPrivateMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
proxy.sendGroupMsg = new Proxy(api.sendGroupMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendGroupMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
return proxy; | ||
} | ||
function error(type, data) { | ||
return new commandError_default(Object.assign(data ?? {}, { type })); | ||
} | ||
var Adapter = class { | ||
constructor(ctx, config, identity, Api2, el = new elements_default()) { | ||
this.ctx = ctx; | ||
this.config = config; | ||
this.identity = identity; | ||
this.platform = config.extends; | ||
this.api = setProxy(new Api2(this), this.ctx); | ||
this.elements = el; | ||
if (!this.ctx[Symbols.bot].get(this.platform)) this.ctx[Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[Symbols.bot].get(this.platform).add(this.api); | ||
} | ||
online() { | ||
if (this.status.value !== "offline") return; | ||
this.status.value = "online"; | ||
this.ctx.emit("status", { adapter: this, status: "online" }); | ||
} | ||
offline() { | ||
if (this.status.value !== "online") return; | ||
this.status.value = "offline"; | ||
this.status.offlineTimes += 1; | ||
this.ctx.emit("status", { adapter: this, status: "offline" }); | ||
} | ||
session(type, data) { | ||
const i18n = this.ctx.i18n.extends(this.config.lang); | ||
const send = sendMessageFactory(this, type, data); | ||
const format = formatFactory(i18n); | ||
const quick = quickFactory(send, i18n); | ||
const prompt = promptFactory(quick, this, data); | ||
const confirm = confirmFactory(quick, this, data); | ||
const { api, elements: el } = this; | ||
this.ctx.emit( | ||
type, | ||
...[{ ...data, api, el, send, i18n, format, quick, prompt, confirm, error }] | ||
); | ||
} | ||
ctx; | ||
config; | ||
identity; | ||
platform; | ||
api; | ||
elements; | ||
status = { | ||
value: "offline", | ||
createTime: /* @__PURE__ */ new Date(), | ||
lastMsgTime: null, | ||
receivedMsg: 0, | ||
sentMsg: 0, | ||
offlineTimes: 0 | ||
}; | ||
selfId = -1; | ||
}; | ||
// src/service/api.ts | ||
var import_tools6 = require("@kotori-bot/tools"); | ||
var Api = class { | ||
adapter; | ||
constructor(adapter) { | ||
this.adapter = adapter; | ||
} | ||
sendPrivateMsg(message, userId, ...extra) { | ||
(0, import_tools6.none)(this, message, userId, extra); | ||
} | ||
sendGroupMsg(message, groupId, ...extra) { | ||
(0, import_tools6.none)(this, message, groupId, extra, extra); | ||
} | ||
deleteMsg(messageId, ...extra) { | ||
(0, import_tools6.none)(this, messageId, extra); | ||
} | ||
setGroupName(groupId, groupName, ...extra) { | ||
(0, import_tools6.none)(this, groupId, groupName, extra); | ||
} | ||
setGroupAvatar(groupId, image, ...extra) { | ||
(0, import_tools6.none)(this, groupId, image, extra); | ||
} | ||
setGroupAdmin(groupId, userId, enable, ...extra) { | ||
(0, import_tools6.none)(this, groupId, userId, enable, extra); | ||
} | ||
setGroupCard(groupId, userId, card, ...extra) { | ||
(0, import_tools6.none)(this, groupId, userId, card, extra); | ||
} | ||
setGroupBan(groupId, userId, time, ...extra) { | ||
(0, import_tools6.none)(this, groupId, userId, time, extra); | ||
} | ||
sendGroupNotice(groupId, content, image, ...extra) { | ||
(0, import_tools6.none)(this, groupId, content, image, extra); | ||
} | ||
setGroupKick(groupId, userId, ...extra) { | ||
(0, import_tools6.none)(this, groupId, userId, extra); | ||
} | ||
setGroupLeave(groupId, ...extra) { | ||
(0, import_tools6.none)(this, groupId, groupId, extra); | ||
} | ||
}; | ||
// src/service/cache.ts | ||
var import_fluoro = require("fluoro"); | ||
var Cache = class extends import_fluoro.Service { | ||
cache; | ||
constructor(ctx) { | ||
super(ctx, {}, "cache"); | ||
} | ||
start() { | ||
if (this.cache) return; | ||
this.cache = /* @__PURE__ */ new Map(); | ||
} | ||
stop() { | ||
this.cache?.forEach((el) => el.clear()); | ||
this.cache?.clear(); | ||
delete this.cache; | ||
} | ||
getContainer() { | ||
const key = this.ctx.identity ?? "root"; | ||
if (!this.cache.has(key)) this.cache.set(key, /* @__PURE__ */ new Map()); | ||
return this.cache.get(key); | ||
} | ||
get(prop) { | ||
return this.getContainer().get(prop); | ||
} | ||
set(prop, value) { | ||
this.getContainer().set(prop, value); | ||
} | ||
}; | ||
// src/components/core.ts | ||
var Core = class extends import_fluoro2.Context { | ||
[Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[Symbols.bot] = /* @__PURE__ */ new Map(); | ||
constructor(config) { | ||
super(); | ||
this.provide("config", new config_default(config)); | ||
this.mixin("config", ["config", "pkg"]); | ||
this.provide("message", new message_default(this)); | ||
this.mixin("message", ["midware", "command", "regexp", "notify", "task"]); | ||
this.provide("http", new import_tools7.Http({ validateStatus: () => true })); | ||
this.inject("http"); | ||
this.provide("i18n", new import_i18n2.default({ lang: this.config.global.lang })); | ||
this.inject("i18n"); | ||
this.service("cache", new Cache(this.extends())); | ||
} | ||
}; | ||
// src/utils/container.ts | ||
var import_tools8 = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
constructor() { | ||
(0, import_tools8.none)(); | ||
} | ||
static instance = {}; | ||
static setInstance(ctx) { | ||
this.instance = ctx; | ||
} | ||
static getInstance() { | ||
return this.instance; | ||
} | ||
static getMixin() { | ||
return Object.assign( | ||
_Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("./components"), module.exports); | ||
__reExport(src_exports, require("./service"), module.exports); | ||
__reExport(src_exports, require("./utils/command"), module.exports); | ||
__reExport(src_exports, require("./utils/error"), module.exports); | ||
__reExport(src_exports, require("./utils/commandError"), module.exports); | ||
__reExport(src_exports, require("./utils/container"), module.exports); | ||
__reExport(src_exports, require("./utils/factory"), module.exports); | ||
__reExport(src_exports, require("./global"), module.exports); | ||
__reExport(src_exports, require("./types"), module.exports); | ||
__reExport(src_exports, require("@kotori-bot/tools"), module.exports); | ||
@@ -840,33 +46,12 @@ __reExport(src_exports, require("@kotori-bot/i18n"), module.exports); | ||
0 && (module.exports = { | ||
ADAPTER_PREFIX, | ||
Adapter, | ||
Api, | ||
CUSTOM_PREFIX, | ||
Cache, | ||
Command, | ||
CommandAccess, | ||
CommandError, | ||
Container, | ||
Core, | ||
DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT, | ||
DevError, | ||
Elements, | ||
KotoriError, | ||
MessageScope, | ||
ModuleError, | ||
OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX, | ||
Symbols, | ||
cancelFactory, | ||
commandArgTypeSignSchema, | ||
confirmFactory, | ||
disposeFactory, | ||
eventDataTargetIdSchema, | ||
formatFactory, | ||
promptFactory, | ||
quickFactory, | ||
sendMessageFactory, | ||
...require("fluoro"), | ||
...require("./components"), | ||
...require("./service"), | ||
...require("./utils/command"), | ||
...require("./utils/error"), | ||
...require("./utils/commandError"), | ||
...require("./utils/container"), | ||
...require("./utils/factory"), | ||
...require("./global"), | ||
...require("./types"), | ||
...require("@kotori-bot/tools"), | ||
@@ -873,0 +58,0 @@ ...require("@kotori-bot/i18n"), |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -32,3 +32,2 @@ | ||
}; | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
@@ -43,4 +42,2 @@ // If the importer is in node compatibility mode or this is not an ESM | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/service/adapter.ts | ||
var adapter_exports = {}; | ||
@@ -52,720 +49,7 @@ __export(adapter_exports, { | ||
module.exports = __toCommonJS(adapter_exports); | ||
// src/types/message.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
import_tsukiko.default.Union([import_tsukiko.default.Literal("string"), import_tsukiko.default.Literal("number")]), | ||
import_tsukiko.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
// src/service/elements.ts | ||
var import_tools = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
default(...args) { | ||
(0, import_tools.none)(this, args); | ||
return ""; | ||
} | ||
at(target, ...extra) { | ||
return this.default(target, extra); | ||
} | ||
image(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
voice(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
video(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
face(id, ...extra) { | ||
return this.default(id, extra); | ||
} | ||
file(data, ...extra) { | ||
return this.default(data, extra); | ||
} | ||
supports() { | ||
const supports = []; | ||
const keys = ["at", "image", "voice", "video", "face", "file"]; | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
var elements_default = Elements; | ||
// src/utils/factory.ts | ||
var import_tools8 = require("@kotori-bot/tools"); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Cache: () => Cache, | ||
Command: () => Command, | ||
CommandAccess: () => CommandAccess, | ||
CommandError: () => CommandError, | ||
Container: () => Container, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
DevError: () => DevError, | ||
Elements: () => Elements, | ||
KotoriError: () => KotoriError, | ||
MessageScope: () => MessageScope, | ||
ModuleError: () => ModuleError, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols, | ||
cancelFactory: () => cancelFactory, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
confirmFactory: () => confirmFactory, | ||
disposeFactory: () => disposeFactory, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema, | ||
formatFactory: () => formatFactory, | ||
promptFactory: () => promptFactory, | ||
quickFactory: () => quickFactory, | ||
sendMessageFactory: () => sendMessageFactory | ||
}); | ||
__reExport(src_exports, require("fluoro")); | ||
// src/components/core.ts | ||
var import_tools6 = require("@kotori-bot/tools"); | ||
var import_i18n2 = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro2 = require("fluoro"); | ||
// src/components/config.ts | ||
var import_tsukiko2 = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_tools2 = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko2.default.Object({ | ||
name: import_tsukiko2.default.String(), | ||
version: import_tsukiko2.default.String(), | ||
description: import_tsukiko2.default.String(), | ||
main: import_tsukiko2.default.String(), | ||
license: import_tsukiko2.default.Literal("GPL-3.0"), | ||
author: import_tsukiko2.default.String() | ||
}); | ||
var Config = class { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
const info = (0, import_tools2.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
if (!info || Object.values(info).length === 0) { | ||
process.stderr.write(`Cannot find kotori-bot package.json | ||
`); | ||
process.exit(); | ||
} | ||
const result = packageInfoSchema.parseSafe(info); | ||
if (!result.value) { | ||
process.stderr.write(`File package.json format error: ${result.error.message} | ||
`); | ||
process.exit(); | ||
} | ||
this.pkg = result.data; | ||
} | ||
}; | ||
var config_default = Config; | ||
// src/components/message.ts | ||
var import_tools4 = require("@kotori-bot/tools"); | ||
var import_cron = require("cron"); | ||
// src/utils/command.ts | ||
var import_tools3 = require("@kotori-bot/tools"); | ||
var import_minimist = __toESM(require("minimist")); | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
var commandError_default = CommandError; | ||
// src/utils/command.ts | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
if (type === "boolean") return value !== "false" && !!value; | ||
if (type === "number") { | ||
if (typeof value === "number") return value; | ||
if (value === true) return 1; | ||
if (value === false) return 0; | ||
const float = parseFloat(value); | ||
const int = parseInt(value, 10); | ||
return float === int ? int : float; | ||
} | ||
return value.toString(); | ||
} | ||
var Command = class { | ||
static run(input, data) { | ||
let starts = ""; | ||
[data.root, ...data.alias].forEach((el) => { | ||
if (starts) return; | ||
if (input.startsWith(`${el} `) || input === el) starts = el; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
const opts = { | ||
string: [], | ||
boolean: [], | ||
alias: {} | ||
}; | ||
data.options.forEach((option) => { | ||
if (option.type === "string") { | ||
opts.string.push(option.realname); | ||
} else if (option.type === "boolean") { | ||
opts.boolean.push(option.realname); | ||
} | ||
opts.alias[option.realname] = option.name; | ||
}); | ||
const arr = (0, import_tools3.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
const args = result._; | ||
const count = { | ||
expected: data.args.filter((el) => !el.optional).length, | ||
reality: args.length | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
let error2; | ||
data.args.forEach((val, index) => { | ||
if (error2 || index > 0 && !args[index - 1]) return; | ||
if (!args[index] && val.default) { | ||
args[index] = val.default; | ||
return; | ||
} | ||
if (val.rest || !args[index]) return; | ||
args[index] = handleDefaultValue(args[index], val.type); | ||
if (!Number.isNaN(args[index])) return; | ||
error2 = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
if (error2) return error2; | ||
const options = {}; | ||
data.options.forEach((val) => { | ||
if (!(val.realname in result)) return; | ||
options[val.realname] = Array.isArray(result[val.realname]) ? result[val.realname][0] : result[val.realname]; | ||
options[val.realname] = handleDefaultValue(options[val.realname], val.type); | ||
if (Number.isNaN(options[val.realname])) | ||
error2 = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
if (error2) return error2; | ||
return { | ||
args: data.args.length > 0 && data.args[data.args.length - 1].rest ? args : args.slice(0, data.args.length), | ||
options | ||
}; | ||
} | ||
template; | ||
meta = { | ||
root: "", | ||
alias: [], | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
args: [], | ||
options: [] | ||
}; | ||
constructor(template, config) { | ||
this.template = template; | ||
this.meta = Object.assign(this.meta, config); | ||
this.parse(); | ||
} | ||
parse() { | ||
const [str, description] = this.template.trim().split(" - "); | ||
this.meta.description = description; | ||
const requiredIndex = str.indexOf(" <"); | ||
const optionalIndex = str.indexOf(" ["); | ||
if (requiredIndex === -1 && optionalIndex === -1) { | ||
this.meta.root = str.trim(); | ||
return; | ||
} | ||
if (requiredIndex !== -1 && (optionalIndex === -1 || requiredIndex < optionalIndex)) { | ||
this.meta.root = str.substring(0, requiredIndex).trim(); | ||
} else { | ||
this.meta.root = str.substring(0, optionalIndex).trim(); | ||
} | ||
const args = (0, import_minimist.default)(str.split(" "))._; | ||
args.forEach((arg) => { | ||
const current = this.meta.args[this.meta.args.length - 1]; | ||
if (current && current.rest) return; | ||
let result = optionalParamMatch.exec(arg); | ||
if (result) { | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type, | ||
rest: !!result[1], | ||
optional: true, | ||
default: result[6] ? handleDefaultValue(result[6], type) : void 0 | ||
}); | ||
} | ||
result = requiredParamMatch.exec(arg); | ||
if (!result || !result[2]) return; | ||
if (!result[6] && current && current.optional) return; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
optional: false | ||
}); | ||
}); | ||
} | ||
alias(alias) { | ||
if (typeof alias === "string") this.meta.alias.push(alias); | ||
else this.meta.alias.push(...alias); | ||
return this; | ||
} | ||
scope(scope) { | ||
this.meta.scope = scope; | ||
return this; | ||
} | ||
access(access) { | ||
this.meta.access = access; | ||
return this; | ||
} | ||
option(name, template) { | ||
const [str, description] = template.trim().split(" "); | ||
const [realname, type] = str.split(":"); | ||
this.meta.options.push({ | ||
realname, | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
}); | ||
return this; | ||
} | ||
action(callback) { | ||
this.meta.action = callback; | ||
return this; | ||
} | ||
help(text) { | ||
this.meta.help = text; | ||
return this; | ||
} | ||
}; | ||
// src/components/message.ts | ||
var Message = class { | ||
[Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[Symbols.command] = /* @__PURE__ */ new Set(); | ||
[Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
handleMidware(session) { | ||
const { api } = session; | ||
let isPass = true; | ||
let midwares = []; | ||
api.adapter.status.receivedMsg += 1; | ||
this[Symbols.midware].forEach((val) => midwares.push(val)); | ||
midwares = midwares.sort((first, second) => first.priority - second.priority); | ||
let lastMidwareNum = -1; | ||
while (midwares.length > 0) { | ||
if (lastMidwareNum === midwares.length) { | ||
isPass = false; | ||
break; | ||
} | ||
lastMidwareNum = midwares.length; | ||
session.quick(midwares[0].callback(() => midwares.shift(), session)); | ||
} | ||
this.ctx.emit("midwares", { isPass, session }); | ||
} | ||
async handleRegexp(data) { | ||
const { session } = data; | ||
if (!data.isPass) return; | ||
this[Symbols.regexp].forEach((data2) => { | ||
const result = session.message.match(data2.match); | ||
if (!result) return; | ||
session.quick(data2.callback(result, session)); | ||
this.ctx.emit("regexp", { result, session, regexp: data2.match, raw: session.message }); | ||
}); | ||
} | ||
handleCommand(data) { | ||
const { session } = data; | ||
const prefix = session.api.adapter.config["command-prefix"] ?? this.ctx.config.global["command-prefix"]; | ||
if (!session.message.startsWith(prefix)) return; | ||
const params = { | ||
session, | ||
raw: (0, import_tools4.stringRightSplit)(session.message, prefix) | ||
}; | ||
this.ctx.emit("before_parse", params); | ||
const cancel = cancelFactory(); | ||
this.ctx.emit("before_command", { cancel: cancel.get(), ...params }); | ||
if (cancel.value) return; | ||
let matched; | ||
this[Symbols.command].forEach(async (cmd) => { | ||
if (matched || !cmd.meta.action) return; | ||
const result = Command.run(params.raw, cmd.meta); | ||
if (result instanceof commandError_default && result.value.type === "unknown") return; | ||
matched = cmd; | ||
this.ctx.emit("parse", { command: cmd, result, ...params, cancel: cancel.get() }); | ||
if (cancel.value || result instanceof commandError_default) return; | ||
try { | ||
const executed = await cmd.meta.action({ args: result.args, options: result.options }, session); | ||
if (executed instanceof commandError_default) { | ||
this.ctx.emit("command", { command: cmd, result: executed, ...params }); | ||
return; | ||
} | ||
if (executed !== void 0) session.quick(executed); | ||
this.ctx.emit("command", { | ||
command: cmd, | ||
result: executed instanceof commandError_default ? result : executed, | ||
...params | ||
}); | ||
} catch (error2) { | ||
this.ctx.emit("command", { | ||
command: matched, | ||
result: new commandError_default({ type: "error", error: error2 }), | ||
...params | ||
}); | ||
} | ||
}); | ||
if (matched) return; | ||
this.ctx.emit("parse", { | ||
command: new Command(""), | ||
result: new commandError_default({ type: "unknown", input: params.raw }), | ||
...params, | ||
cancel: cancel.get() | ||
}); | ||
} | ||
ctx; | ||
constructor(ctx) { | ||
this.ctx = ctx; | ||
this.ctx.on("on_message", (session) => this.handleMidware(session)); | ||
this.ctx.on("midwares", (data) => this.handleCommand(data)); | ||
this.ctx.on("midwares", (data) => this.handleRegexp(data)); | ||
this.ctx.on("before_send", (data) => { | ||
const { api } = data; | ||
api.adapter.status.sentMsg += 1; | ||
}); | ||
} | ||
midware(callback, priority = 100) { | ||
const data = { callback, priority }; | ||
this[Symbols.midware].add(data); | ||
const dispose = () => this[Symbols.midware].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
command(template, config) { | ||
const command = new Command(template, config); | ||
this[Symbols.command].add(command); | ||
const dispose = () => this[Symbols.command].delete(command); | ||
disposeFactory(this.ctx, dispose); | ||
return command; | ||
} | ||
regexp(match, callback) { | ||
const data = { match, callback }; | ||
this[Symbols.regexp].add(data); | ||
const dispose = () => this[Symbols.regexp].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
// boardcast(type: MessageScope, message: MessageRaw) { | ||
// const send = | ||
// type === 'private' | ||
// ? (api: Api) => api.send_on_message(message, 1) | ||
// : (api: Api) => api.send_on_message(message, 1); | ||
// /* this need support of database... */ | ||
// Object.values(this.botStack).forEach((apis) => { | ||
// apis.forEach((api) => send(api)); | ||
// }); | ||
// } | ||
notify(message) { | ||
const mainAdapterIdentity = Object.keys(this.ctx.config.adapter)[0]; | ||
this.ctx[Symbols.bot].forEach( | ||
(apis) => apis.forEach((api) => { | ||
if (api.adapter.identity !== mainAdapterIdentity) return; | ||
quickFactory( | ||
sendMessageFactory(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
this.ctx.i18n.extends(api.adapter.config.lang) | ||
)(message); | ||
}) | ||
); | ||
} | ||
task(options, callback) { | ||
const [cron, extraOptions] = typeof options === "string" ? [options, {}] : [options.cron, options]; | ||
return new import_cron.CronJob(cron, () => callback(this.ctx), null, extraOptions.start ?? true, extraOptions.timeZone); | ||
} | ||
}; | ||
var message_default = Message; | ||
// src/service/api.ts | ||
var import_tools5 = require("@kotori-bot/tools"); | ||
var Api = class { | ||
adapter; | ||
constructor(adapter) { | ||
this.adapter = adapter; | ||
} | ||
sendPrivateMsg(message, userId, ...extra) { | ||
(0, import_tools5.none)(this, message, userId, extra); | ||
} | ||
sendGroupMsg(message, groupId, ...extra) { | ||
(0, import_tools5.none)(this, message, groupId, extra, extra); | ||
} | ||
deleteMsg(messageId, ...extra) { | ||
(0, import_tools5.none)(this, messageId, extra); | ||
} | ||
setGroupName(groupId, groupName, ...extra) { | ||
(0, import_tools5.none)(this, groupId, groupName, extra); | ||
} | ||
setGroupAvatar(groupId, image, ...extra) { | ||
(0, import_tools5.none)(this, groupId, image, extra); | ||
} | ||
setGroupAdmin(groupId, userId, enable, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, enable, extra); | ||
} | ||
setGroupCard(groupId, userId, card, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, card, extra); | ||
} | ||
setGroupBan(groupId, userId, time, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, time, extra); | ||
} | ||
sendGroupNotice(groupId, content, image, ...extra) { | ||
(0, import_tools5.none)(this, groupId, content, image, extra); | ||
} | ||
setGroupKick(groupId, userId, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, extra); | ||
} | ||
setGroupLeave(groupId, ...extra) { | ||
(0, import_tools5.none)(this, groupId, groupId, extra); | ||
} | ||
}; | ||
// src/service/cache.ts | ||
var import_fluoro = require("fluoro"); | ||
var Cache = class extends import_fluoro.Service { | ||
cache; | ||
constructor(ctx) { | ||
super(ctx, {}, "cache"); | ||
} | ||
start() { | ||
if (this.cache) return; | ||
this.cache = /* @__PURE__ */ new Map(); | ||
} | ||
stop() { | ||
this.cache?.forEach((el) => el.clear()); | ||
this.cache?.clear(); | ||
delete this.cache; | ||
} | ||
getContainer() { | ||
const key = this.ctx.identity ?? "root"; | ||
if (!this.cache.has(key)) this.cache.set(key, /* @__PURE__ */ new Map()); | ||
return this.cache.get(key); | ||
} | ||
get(prop) { | ||
return this.getContainer().get(prop); | ||
} | ||
set(prop, value) { | ||
this.getContainer().set(prop, value); | ||
} | ||
}; | ||
// src/components/core.ts | ||
var Core = class extends import_fluoro2.Context { | ||
[Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[Symbols.bot] = /* @__PURE__ */ new Map(); | ||
constructor(config) { | ||
super(); | ||
this.provide("config", new config_default(config)); | ||
this.mixin("config", ["config", "pkg"]); | ||
this.provide("message", new message_default(this)); | ||
this.mixin("message", ["midware", "command", "regexp", "notify", "task"]); | ||
this.provide("http", new import_tools6.Http({ validateStatus: () => true })); | ||
this.inject("http"); | ||
this.provide("i18n", new import_i18n2.default({ lang: this.config.global.lang })); | ||
this.inject("i18n"); | ||
this.service("cache", new Cache(this.extends())); | ||
} | ||
}; | ||
// src/utils/container.ts | ||
var import_tools7 = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
constructor() { | ||
(0, import_tools7.none)(); | ||
} | ||
static instance = {}; | ||
static setInstance(ctx) { | ||
this.instance = ctx; | ||
} | ||
static getInstance() { | ||
return this.instance; | ||
} | ||
static getMixin() { | ||
return Object.assign( | ||
_Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("@kotori-bot/tools")); | ||
__reExport(src_exports, require("@kotori-bot/i18n")); | ||
__reExport(src_exports, require("tsukiko")); | ||
// src/utils/factory.ts | ||
function disposeFactory(ctx, dispose) { | ||
ctx.once("dispose_module", (data) => { | ||
if ((typeof data.instance === "object" ? data.instance.name : data.instance) !== ctx.identity) { | ||
disposeFactory(ctx, dispose); | ||
return; | ||
} | ||
dispose(); | ||
}); | ||
} | ||
function cancelFactory() { | ||
return { | ||
get() { | ||
return () => this.fn(); | ||
}, | ||
fn() { | ||
this.value = true; | ||
}, | ||
value: false | ||
}; | ||
} | ||
function formatFactory(i18n) { | ||
return (template, data) => { | ||
const params = data; | ||
if (Array.isArray(params)) { | ||
let str = i18n.locale(template); | ||
params.forEach((value, index) => { | ||
str = str.replaceAll(`{${index}}`, i18n.locale(typeof value === "string" ? value : String(value))); | ||
}); | ||
return str; | ||
} | ||
Object.keys(params).forEach((key) => { | ||
if (typeof params[key] !== "string") params[key] = String(params[key]); | ||
params[key] = i18n.locale(params[key]); | ||
}); | ||
return (0, import_tools8.stringTemp)(i18n.locale(template), params); | ||
}; | ||
} | ||
function sendMessageFactory(adapter, type, data) { | ||
if ((data.type === 1 /* GROUP */ || type.includes("group")) && "groupId" in data) { | ||
return (message) => { | ||
adapter.api.sendGroupMsg(message, data.groupId, data.extra); | ||
}; | ||
} | ||
return (message) => { | ||
adapter.api.sendPrivateMsg(message, data.userId, data.extra); | ||
}; | ||
} | ||
function quickFactory(send, i18n) { | ||
return async (message) => { | ||
const msg = await message; | ||
if (!msg || msg instanceof CommandError) return; | ||
if (typeof msg === "string") { | ||
send(i18n.locale(msg)); | ||
return; | ||
} | ||
send(formatFactory(i18n)(...msg)); | ||
}; | ||
} | ||
function isSameSender(adapter, data, session) { | ||
return session.api.adapter.identity === adapter.identity && session.api.adapter.platform === adapter.platform && session.type === data.type && session.groupId === data.groupId && session.userId === data.userId && "messageId" in data && session.messageId !== data.messageId; | ||
} | ||
function promptFactory(quick, adapter, data) { | ||
return (message) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(message ?? "corei18n.template.prompt").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
function confirmFactory(quick, adapter, data) { | ||
return (options) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(options?.message ?? "corei18n.template.confirm").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
// src/service/adapter.ts | ||
var import_types = require("../types"); | ||
var import_elements = __toESM(require("./elements")); | ||
var import_factory = require("../utils/factory"); | ||
var import_commandError = __toESM(require("../utils/commandError")); | ||
var import_global = require("../global"); | ||
function setProxy(api, ctx) { | ||
@@ -776,4 +60,4 @@ const proxy = Object.create(api); | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
const cancel = (0, import_factory.cancelFactory)(); | ||
ctx.emit("before_send", { api, message, messageType: import_types.MessageScope.PRIVATE, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
@@ -786,4 +70,4 @@ api.sendPrivateMsg(message, targetId, argArray[2]); | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
const cancel = (0, import_factory.cancelFactory)(); | ||
ctx.emit("before_send", { api, message, messageType: import_types.MessageScope.PRIVATE, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
@@ -796,6 +80,6 @@ api.sendGroupMsg(message, targetId, argArray[2]); | ||
function error(type, data) { | ||
return new commandError_default(Object.assign(data ?? {}, { type })); | ||
return new import_commandError.default(Object.assign(data ?? {}, { type })); | ||
} | ||
var Adapter = class { | ||
constructor(ctx, config, identity, Api2, el = new elements_default()) { | ||
class Adapter { | ||
constructor(ctx, config, identity, Api, el = new import_elements.default()) { | ||
this.ctx = ctx; | ||
@@ -805,6 +89,6 @@ this.config = config; | ||
this.platform = config.extends; | ||
this.api = setProxy(new Api2(this), this.ctx); | ||
this.api = setProxy(new Api(this), this.ctx); | ||
this.elements = el; | ||
if (!this.ctx[Symbols.bot].get(this.platform)) this.ctx[Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[Symbols.bot].get(this.platform).add(this.api); | ||
if (!this.ctx[import_global.Symbols.bot].get(this.platform)) this.ctx[import_global.Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[import_global.Symbols.bot].get(this.platform).add(this.api); | ||
} | ||
@@ -824,7 +108,7 @@ online() { | ||
const i18n = this.ctx.i18n.extends(this.config.lang); | ||
const send = sendMessageFactory(this, type, data); | ||
const format = formatFactory(i18n); | ||
const quick = quickFactory(send, i18n); | ||
const prompt = promptFactory(quick, this, data); | ||
const confirm = confirmFactory(quick, this, data); | ||
const send = (0, import_factory.sendMessageFactory)(this, type, data); | ||
const format = (0, import_factory.formatFactory)(i18n); | ||
const quick = (0, import_factory.quickFactory)(send, i18n); | ||
const prompt = (0, import_factory.promptFactory)(quick, this, data); | ||
const confirm = (0, import_factory.confirmFactory)(quick, this, data); | ||
const { api, elements: el } = this; | ||
@@ -851,3 +135,3 @@ this.ctx.emit( | ||
selfId = -1; | ||
}; | ||
} | ||
var adapter_default = Adapter; | ||
@@ -854,0 +138,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/service/api.ts | ||
var api_exports = {}; | ||
@@ -41,3 +39,3 @@ __export(api_exports, { | ||
var import_tools = require("@kotori-bot/tools"); | ||
var Api = class { | ||
class Api { | ||
adapter; | ||
@@ -80,3 +78,3 @@ constructor(adapter) { | ||
} | ||
}; | ||
} | ||
var api_default = Api; | ||
@@ -83,0 +81,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/service/cache.ts | ||
var cache_exports = {}; | ||
@@ -41,3 +39,3 @@ __export(cache_exports, { | ||
var import_fluoro = require("fluoro"); | ||
var Cache = class extends import_fluoro.Service { | ||
class Cache extends import_fluoro.Service { | ||
cache; | ||
@@ -67,3 +65,3 @@ constructor(ctx) { | ||
} | ||
}; | ||
} | ||
var cache_default = Cache; | ||
@@ -70,0 +68,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/service/elements.ts | ||
var elements_exports = {}; | ||
@@ -41,3 +39,3 @@ __export(elements_exports, { | ||
var import_tools = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
class Elements { | ||
default(...args) { | ||
@@ -69,7 +67,7 @@ (0, import_tools.none)(this, args); | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
if (this[key] !== new Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
} | ||
var elements_default = Elements; | ||
@@ -76,0 +74,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,16 +9,10 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
"use strict"; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
@@ -33,821 +27,15 @@ if (from && typeof from === "object" || typeof from === "function") { | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
// If the importer is in node compatibility mode or this is not an ESM | ||
// file that has been converted to a CommonJS file using a Babel- | ||
// compatible transform (i.e. "__esModule" has not been set), then set | ||
// "default" to the CommonJS "module.exports" for node compatibility. | ||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
mod | ||
)); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/service/index.ts | ||
var service_exports = {}; | ||
__export(service_exports, { | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
Cache: () => Cache, | ||
Elements: () => Elements | ||
}); | ||
module.exports = __toCommonJS(service_exports); | ||
// src/types/message.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
import_tsukiko.default.Union([import_tsukiko.default.Literal("string"), import_tsukiko.default.Literal("number")]), | ||
import_tsukiko.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
// src/service/elements.ts | ||
var import_tools = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
default(...args) { | ||
(0, import_tools.none)(this, args); | ||
return ""; | ||
} | ||
at(target, ...extra) { | ||
return this.default(target, extra); | ||
} | ||
image(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
voice(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
video(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
face(id, ...extra) { | ||
return this.default(id, extra); | ||
} | ||
file(data, ...extra) { | ||
return this.default(data, extra); | ||
} | ||
supports() { | ||
const supports = []; | ||
const keys = ["at", "image", "voice", "video", "face", "file"]; | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
var elements_default = Elements; | ||
// src/utils/factory.ts | ||
var import_tools7 = require("@kotori-bot/tools"); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Cache: () => Cache, | ||
Command: () => Command, | ||
CommandAccess: () => CommandAccess, | ||
CommandError: () => CommandError, | ||
Container: () => Container, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
DevError: () => DevError, | ||
Elements: () => Elements, | ||
KotoriError: () => KotoriError, | ||
MessageScope: () => MessageScope, | ||
ModuleError: () => ModuleError, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols, | ||
cancelFactory: () => cancelFactory, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
confirmFactory: () => confirmFactory, | ||
disposeFactory: () => disposeFactory, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema, | ||
formatFactory: () => formatFactory, | ||
promptFactory: () => promptFactory, | ||
quickFactory: () => quickFactory, | ||
sendMessageFactory: () => sendMessageFactory | ||
}); | ||
__reExport(src_exports, require("fluoro")); | ||
// src/components/core.ts | ||
var import_tools5 = require("@kotori-bot/tools"); | ||
var import_i18n2 = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro = require("fluoro"); | ||
// src/components/config.ts | ||
var import_tsukiko2 = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_tools2 = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko2.default.Object({ | ||
name: import_tsukiko2.default.String(), | ||
version: import_tsukiko2.default.String(), | ||
description: import_tsukiko2.default.String(), | ||
main: import_tsukiko2.default.String(), | ||
license: import_tsukiko2.default.Literal("GPL-3.0"), | ||
author: import_tsukiko2.default.String() | ||
}); | ||
var Config = class { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
const info = (0, import_tools2.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
if (!info || Object.values(info).length === 0) { | ||
process.stderr.write(`Cannot find kotori-bot package.json | ||
`); | ||
process.exit(); | ||
} | ||
const result = packageInfoSchema.parseSafe(info); | ||
if (!result.value) { | ||
process.stderr.write(`File package.json format error: ${result.error.message} | ||
`); | ||
process.exit(); | ||
} | ||
this.pkg = result.data; | ||
} | ||
}; | ||
var config_default = Config; | ||
// src/components/message.ts | ||
var import_tools4 = require("@kotori-bot/tools"); | ||
var import_cron = require("cron"); | ||
// src/utils/command.ts | ||
var import_tools3 = require("@kotori-bot/tools"); | ||
var import_minimist = __toESM(require("minimist")); | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
var commandError_default = CommandError; | ||
// src/utils/command.ts | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
if (type === "boolean") return value !== "false" && !!value; | ||
if (type === "number") { | ||
if (typeof value === "number") return value; | ||
if (value === true) return 1; | ||
if (value === false) return 0; | ||
const float = parseFloat(value); | ||
const int = parseInt(value, 10); | ||
return float === int ? int : float; | ||
} | ||
return value.toString(); | ||
} | ||
var Command = class { | ||
static run(input, data) { | ||
let starts = ""; | ||
[data.root, ...data.alias].forEach((el) => { | ||
if (starts) return; | ||
if (input.startsWith(`${el} `) || input === el) starts = el; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
const opts = { | ||
string: [], | ||
boolean: [], | ||
alias: {} | ||
}; | ||
data.options.forEach((option) => { | ||
if (option.type === "string") { | ||
opts.string.push(option.realname); | ||
} else if (option.type === "boolean") { | ||
opts.boolean.push(option.realname); | ||
} | ||
opts.alias[option.realname] = option.name; | ||
}); | ||
const arr = (0, import_tools3.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
const args = result._; | ||
const count = { | ||
expected: data.args.filter((el) => !el.optional).length, | ||
reality: args.length | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
let error2; | ||
data.args.forEach((val, index) => { | ||
if (error2 || index > 0 && !args[index - 1]) return; | ||
if (!args[index] && val.default) { | ||
args[index] = val.default; | ||
return; | ||
} | ||
if (val.rest || !args[index]) return; | ||
args[index] = handleDefaultValue(args[index], val.type); | ||
if (!Number.isNaN(args[index])) return; | ||
error2 = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
if (error2) return error2; | ||
const options = {}; | ||
data.options.forEach((val) => { | ||
if (!(val.realname in result)) return; | ||
options[val.realname] = Array.isArray(result[val.realname]) ? result[val.realname][0] : result[val.realname]; | ||
options[val.realname] = handleDefaultValue(options[val.realname], val.type); | ||
if (Number.isNaN(options[val.realname])) | ||
error2 = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
if (error2) return error2; | ||
return { | ||
args: data.args.length > 0 && data.args[data.args.length - 1].rest ? args : args.slice(0, data.args.length), | ||
options | ||
}; | ||
} | ||
template; | ||
meta = { | ||
root: "", | ||
alias: [], | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
args: [], | ||
options: [] | ||
}; | ||
constructor(template, config) { | ||
this.template = template; | ||
this.meta = Object.assign(this.meta, config); | ||
this.parse(); | ||
} | ||
parse() { | ||
const [str, description] = this.template.trim().split(" - "); | ||
this.meta.description = description; | ||
const requiredIndex = str.indexOf(" <"); | ||
const optionalIndex = str.indexOf(" ["); | ||
if (requiredIndex === -1 && optionalIndex === -1) { | ||
this.meta.root = str.trim(); | ||
return; | ||
} | ||
if (requiredIndex !== -1 && (optionalIndex === -1 || requiredIndex < optionalIndex)) { | ||
this.meta.root = str.substring(0, requiredIndex).trim(); | ||
} else { | ||
this.meta.root = str.substring(0, optionalIndex).trim(); | ||
} | ||
const args = (0, import_minimist.default)(str.split(" "))._; | ||
args.forEach((arg) => { | ||
const current = this.meta.args[this.meta.args.length - 1]; | ||
if (current && current.rest) return; | ||
let result = optionalParamMatch.exec(arg); | ||
if (result) { | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type, | ||
rest: !!result[1], | ||
optional: true, | ||
default: result[6] ? handleDefaultValue(result[6], type) : void 0 | ||
}); | ||
} | ||
result = requiredParamMatch.exec(arg); | ||
if (!result || !result[2]) return; | ||
if (!result[6] && current && current.optional) return; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
optional: false | ||
}); | ||
}); | ||
} | ||
alias(alias) { | ||
if (typeof alias === "string") this.meta.alias.push(alias); | ||
else this.meta.alias.push(...alias); | ||
return this; | ||
} | ||
scope(scope) { | ||
this.meta.scope = scope; | ||
return this; | ||
} | ||
access(access) { | ||
this.meta.access = access; | ||
return this; | ||
} | ||
option(name, template) { | ||
const [str, description] = template.trim().split(" "); | ||
const [realname, type] = str.split(":"); | ||
this.meta.options.push({ | ||
realname, | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
}); | ||
return this; | ||
} | ||
action(callback) { | ||
this.meta.action = callback; | ||
return this; | ||
} | ||
help(text) { | ||
this.meta.help = text; | ||
return this; | ||
} | ||
}; | ||
// src/components/message.ts | ||
var Message = class { | ||
[Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[Symbols.command] = /* @__PURE__ */ new Set(); | ||
[Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
handleMidware(session) { | ||
const { api } = session; | ||
let isPass = true; | ||
let midwares = []; | ||
api.adapter.status.receivedMsg += 1; | ||
this[Symbols.midware].forEach((val) => midwares.push(val)); | ||
midwares = midwares.sort((first, second) => first.priority - second.priority); | ||
let lastMidwareNum = -1; | ||
while (midwares.length > 0) { | ||
if (lastMidwareNum === midwares.length) { | ||
isPass = false; | ||
break; | ||
} | ||
lastMidwareNum = midwares.length; | ||
session.quick(midwares[0].callback(() => midwares.shift(), session)); | ||
} | ||
this.ctx.emit("midwares", { isPass, session }); | ||
} | ||
async handleRegexp(data) { | ||
const { session } = data; | ||
if (!data.isPass) return; | ||
this[Symbols.regexp].forEach((data2) => { | ||
const result = session.message.match(data2.match); | ||
if (!result) return; | ||
session.quick(data2.callback(result, session)); | ||
this.ctx.emit("regexp", { result, session, regexp: data2.match, raw: session.message }); | ||
}); | ||
} | ||
handleCommand(data) { | ||
const { session } = data; | ||
const prefix = session.api.adapter.config["command-prefix"] ?? this.ctx.config.global["command-prefix"]; | ||
if (!session.message.startsWith(prefix)) return; | ||
const params = { | ||
session, | ||
raw: (0, import_tools4.stringRightSplit)(session.message, prefix) | ||
}; | ||
this.ctx.emit("before_parse", params); | ||
const cancel = cancelFactory(); | ||
this.ctx.emit("before_command", { cancel: cancel.get(), ...params }); | ||
if (cancel.value) return; | ||
let matched; | ||
this[Symbols.command].forEach(async (cmd) => { | ||
if (matched || !cmd.meta.action) return; | ||
const result = Command.run(params.raw, cmd.meta); | ||
if (result instanceof commandError_default && result.value.type === "unknown") return; | ||
matched = cmd; | ||
this.ctx.emit("parse", { command: cmd, result, ...params, cancel: cancel.get() }); | ||
if (cancel.value || result instanceof commandError_default) return; | ||
try { | ||
const executed = await cmd.meta.action({ args: result.args, options: result.options }, session); | ||
if (executed instanceof commandError_default) { | ||
this.ctx.emit("command", { command: cmd, result: executed, ...params }); | ||
return; | ||
} | ||
if (executed !== void 0) session.quick(executed); | ||
this.ctx.emit("command", { | ||
command: cmd, | ||
result: executed instanceof commandError_default ? result : executed, | ||
...params | ||
}); | ||
} catch (error2) { | ||
this.ctx.emit("command", { | ||
command: matched, | ||
result: new commandError_default({ type: "error", error: error2 }), | ||
...params | ||
}); | ||
} | ||
}); | ||
if (matched) return; | ||
this.ctx.emit("parse", { | ||
command: new Command(""), | ||
result: new commandError_default({ type: "unknown", input: params.raw }), | ||
...params, | ||
cancel: cancel.get() | ||
}); | ||
} | ||
ctx; | ||
constructor(ctx) { | ||
this.ctx = ctx; | ||
this.ctx.on("on_message", (session) => this.handleMidware(session)); | ||
this.ctx.on("midwares", (data) => this.handleCommand(data)); | ||
this.ctx.on("midwares", (data) => this.handleRegexp(data)); | ||
this.ctx.on("before_send", (data) => { | ||
const { api } = data; | ||
api.adapter.status.sentMsg += 1; | ||
}); | ||
} | ||
midware(callback, priority = 100) { | ||
const data = { callback, priority }; | ||
this[Symbols.midware].add(data); | ||
const dispose = () => this[Symbols.midware].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
command(template, config) { | ||
const command = new Command(template, config); | ||
this[Symbols.command].add(command); | ||
const dispose = () => this[Symbols.command].delete(command); | ||
disposeFactory(this.ctx, dispose); | ||
return command; | ||
} | ||
regexp(match, callback) { | ||
const data = { match, callback }; | ||
this[Symbols.regexp].add(data); | ||
const dispose = () => this[Symbols.regexp].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
// boardcast(type: MessageScope, message: MessageRaw) { | ||
// const send = | ||
// type === 'private' | ||
// ? (api: Api) => api.send_on_message(message, 1) | ||
// : (api: Api) => api.send_on_message(message, 1); | ||
// /* this need support of database... */ | ||
// Object.values(this.botStack).forEach((apis) => { | ||
// apis.forEach((api) => send(api)); | ||
// }); | ||
// } | ||
notify(message) { | ||
const mainAdapterIdentity = Object.keys(this.ctx.config.adapter)[0]; | ||
this.ctx[Symbols.bot].forEach( | ||
(apis) => apis.forEach((api) => { | ||
if (api.adapter.identity !== mainAdapterIdentity) return; | ||
quickFactory( | ||
sendMessageFactory(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
this.ctx.i18n.extends(api.adapter.config.lang) | ||
)(message); | ||
}) | ||
); | ||
} | ||
task(options, callback) { | ||
const [cron, extraOptions] = typeof options === "string" ? [options, {}] : [options.cron, options]; | ||
return new import_cron.CronJob(cron, () => callback(this.ctx), null, extraOptions.start ?? true, extraOptions.timeZone); | ||
} | ||
}; | ||
var message_default = Message; | ||
// src/components/core.ts | ||
var Core = class extends import_fluoro.Context { | ||
[Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[Symbols.bot] = /* @__PURE__ */ new Map(); | ||
constructor(config) { | ||
super(); | ||
this.provide("config", new config_default(config)); | ||
this.mixin("config", ["config", "pkg"]); | ||
this.provide("message", new message_default(this)); | ||
this.mixin("message", ["midware", "command", "regexp", "notify", "task"]); | ||
this.provide("http", new import_tools5.Http({ validateStatus: () => true })); | ||
this.inject("http"); | ||
this.provide("i18n", new import_i18n2.default({ lang: this.config.global.lang })); | ||
this.inject("i18n"); | ||
this.service("cache", new Cache(this.extends())); | ||
} | ||
}; | ||
// src/utils/container.ts | ||
var import_tools6 = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
constructor() { | ||
(0, import_tools6.none)(); | ||
} | ||
static instance = {}; | ||
static setInstance(ctx) { | ||
this.instance = ctx; | ||
} | ||
static getInstance() { | ||
return this.instance; | ||
} | ||
static getMixin() { | ||
return Object.assign( | ||
_Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("@kotori-bot/tools")); | ||
__reExport(src_exports, require("@kotori-bot/i18n")); | ||
__reExport(src_exports, require("tsukiko")); | ||
// src/utils/factory.ts | ||
function disposeFactory(ctx, dispose) { | ||
ctx.once("dispose_module", (data) => { | ||
if ((typeof data.instance === "object" ? data.instance.name : data.instance) !== ctx.identity) { | ||
disposeFactory(ctx, dispose); | ||
return; | ||
} | ||
dispose(); | ||
}); | ||
} | ||
function cancelFactory() { | ||
return { | ||
get() { | ||
return () => this.fn(); | ||
}, | ||
fn() { | ||
this.value = true; | ||
}, | ||
value: false | ||
}; | ||
} | ||
function formatFactory(i18n) { | ||
return (template, data) => { | ||
const params = data; | ||
if (Array.isArray(params)) { | ||
let str = i18n.locale(template); | ||
params.forEach((value, index) => { | ||
str = str.replaceAll(`{${index}}`, i18n.locale(typeof value === "string" ? value : String(value))); | ||
}); | ||
return str; | ||
} | ||
Object.keys(params).forEach((key) => { | ||
if (typeof params[key] !== "string") params[key] = String(params[key]); | ||
params[key] = i18n.locale(params[key]); | ||
}); | ||
return (0, import_tools7.stringTemp)(i18n.locale(template), params); | ||
}; | ||
} | ||
function sendMessageFactory(adapter, type, data) { | ||
if ((data.type === 1 /* GROUP */ || type.includes("group")) && "groupId" in data) { | ||
return (message) => { | ||
adapter.api.sendGroupMsg(message, data.groupId, data.extra); | ||
}; | ||
} | ||
return (message) => { | ||
adapter.api.sendPrivateMsg(message, data.userId, data.extra); | ||
}; | ||
} | ||
function quickFactory(send, i18n) { | ||
return async (message) => { | ||
const msg = await message; | ||
if (!msg || msg instanceof CommandError) return; | ||
if (typeof msg === "string") { | ||
send(i18n.locale(msg)); | ||
return; | ||
} | ||
send(formatFactory(i18n)(...msg)); | ||
}; | ||
} | ||
function isSameSender(adapter, data, session) { | ||
return session.api.adapter.identity === adapter.identity && session.api.adapter.platform === adapter.platform && session.type === data.type && session.groupId === data.groupId && session.userId === data.userId && "messageId" in data && session.messageId !== data.messageId; | ||
} | ||
function promptFactory(quick, adapter, data) { | ||
return (message) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(message ?? "corei18n.template.prompt").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
function confirmFactory(quick, adapter, data) { | ||
return (options) => new Promise((resolve2) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
return; | ||
} | ||
adapter.ctx.once("on_message", handle); | ||
}; | ||
quick(options?.message ?? "corei18n.template.confirm").then(() => adapter.ctx.once("on_message", handle)); | ||
}); | ||
} | ||
// src/service/adapter.ts | ||
function setProxy(api, ctx) { | ||
const proxy = Object.create(api); | ||
proxy.sendPrivateMsg = new Proxy(api.sendPrivateMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendPrivateMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
proxy.sendGroupMsg = new Proxy(api.sendGroupMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendGroupMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
return proxy; | ||
} | ||
function error(type, data) { | ||
return new commandError_default(Object.assign(data ?? {}, { type })); | ||
} | ||
var Adapter = class { | ||
constructor(ctx, config, identity, Api2, el = new elements_default()) { | ||
this.ctx = ctx; | ||
this.config = config; | ||
this.identity = identity; | ||
this.platform = config.extends; | ||
this.api = setProxy(new Api2(this), this.ctx); | ||
this.elements = el; | ||
if (!this.ctx[Symbols.bot].get(this.platform)) this.ctx[Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[Symbols.bot].get(this.platform).add(this.api); | ||
} | ||
online() { | ||
if (this.status.value !== "offline") return; | ||
this.status.value = "online"; | ||
this.ctx.emit("status", { adapter: this, status: "online" }); | ||
} | ||
offline() { | ||
if (this.status.value !== "online") return; | ||
this.status.value = "offline"; | ||
this.status.offlineTimes += 1; | ||
this.ctx.emit("status", { adapter: this, status: "offline" }); | ||
} | ||
session(type, data) { | ||
const i18n = this.ctx.i18n.extends(this.config.lang); | ||
const send = sendMessageFactory(this, type, data); | ||
const format = formatFactory(i18n); | ||
const quick = quickFactory(send, i18n); | ||
const prompt = promptFactory(quick, this, data); | ||
const confirm = confirmFactory(quick, this, data); | ||
const { api, elements: el } = this; | ||
this.ctx.emit( | ||
type, | ||
...[{ ...data, api, el, send, i18n, format, quick, prompt, confirm, error }] | ||
); | ||
} | ||
ctx; | ||
config; | ||
identity; | ||
platform; | ||
api; | ||
elements; | ||
status = { | ||
value: "offline", | ||
createTime: /* @__PURE__ */ new Date(), | ||
lastMsgTime: null, | ||
receivedMsg: 0, | ||
sentMsg: 0, | ||
offlineTimes: 0 | ||
}; | ||
selfId = -1; | ||
}; | ||
// src/service/api.ts | ||
var import_tools8 = require("@kotori-bot/tools"); | ||
var Api = class { | ||
adapter; | ||
constructor(adapter) { | ||
this.adapter = adapter; | ||
} | ||
sendPrivateMsg(message, userId, ...extra) { | ||
(0, import_tools8.none)(this, message, userId, extra); | ||
} | ||
sendGroupMsg(message, groupId, ...extra) { | ||
(0, import_tools8.none)(this, message, groupId, extra, extra); | ||
} | ||
deleteMsg(messageId, ...extra) { | ||
(0, import_tools8.none)(this, messageId, extra); | ||
} | ||
setGroupName(groupId, groupName, ...extra) { | ||
(0, import_tools8.none)(this, groupId, groupName, extra); | ||
} | ||
setGroupAvatar(groupId, image, ...extra) { | ||
(0, import_tools8.none)(this, groupId, image, extra); | ||
} | ||
setGroupAdmin(groupId, userId, enable, ...extra) { | ||
(0, import_tools8.none)(this, groupId, userId, enable, extra); | ||
} | ||
setGroupCard(groupId, userId, card, ...extra) { | ||
(0, import_tools8.none)(this, groupId, userId, card, extra); | ||
} | ||
setGroupBan(groupId, userId, time, ...extra) { | ||
(0, import_tools8.none)(this, groupId, userId, time, extra); | ||
} | ||
sendGroupNotice(groupId, content, image, ...extra) { | ||
(0, import_tools8.none)(this, groupId, content, image, extra); | ||
} | ||
setGroupKick(groupId, userId, ...extra) { | ||
(0, import_tools8.none)(this, groupId, userId, extra); | ||
} | ||
setGroupLeave(groupId, ...extra) { | ||
(0, import_tools8.none)(this, groupId, groupId, extra); | ||
} | ||
}; | ||
// src/service/cache.ts | ||
var import_fluoro2 = require("fluoro"); | ||
var Cache = class extends import_fluoro2.Service { | ||
cache; | ||
constructor(ctx) { | ||
super(ctx, {}, "cache"); | ||
} | ||
start() { | ||
if (this.cache) return; | ||
this.cache = /* @__PURE__ */ new Map(); | ||
} | ||
stop() { | ||
this.cache?.forEach((el) => el.clear()); | ||
this.cache?.clear(); | ||
delete this.cache; | ||
} | ||
getContainer() { | ||
const key = this.ctx.identity ?? "root"; | ||
if (!this.cache.has(key)) this.cache.set(key, /* @__PURE__ */ new Map()); | ||
return this.cache.get(key); | ||
} | ||
get(prop) { | ||
return this.getContainer().get(prop); | ||
} | ||
set(prop, value) { | ||
this.getContainer().set(prop, value); | ||
} | ||
}; | ||
__reExport(service_exports, require("./adapter"), module.exports); | ||
__reExport(service_exports, require("./api"), module.exports); | ||
__reExport(service_exports, require("./elements"), module.exports); | ||
__reExport(service_exports, require("./cache"), module.exports); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
Adapter, | ||
Api, | ||
Cache, | ||
Elements | ||
...require("./adapter"), | ||
...require("./api"), | ||
...require("./elements"), | ||
...require("./cache") | ||
}); |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -27,5 +27,3 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/types/adapter.ts | ||
var adapter_exports = {}; | ||
module.exports = __toCommonJS(adapter_exports); |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -27,5 +27,3 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/types/config.ts | ||
var config_exports = {}; | ||
module.exports = __toCommonJS(config_exports); |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,16 +9,10 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
"use strict"; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
@@ -32,46 +26,14 @@ if (from && typeof from === "object" || typeof from === "function") { | ||
}; | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
// If the importer is in node compatibility mode or this is not an ESM | ||
// file that has been converted to a CommonJS file using a Babel- | ||
// compatible transform (i.e. "__esModule" has not been set), then set | ||
// "default" to the CommonJS "module.exports" for node compatibility. | ||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
mod | ||
)); | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/types/index.ts | ||
var types_exports = {}; | ||
__export(types_exports, { | ||
CommandAccess: () => CommandAccess, | ||
MessageScope: () => MessageScope, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema | ||
}); | ||
module.exports = __toCommonJS(types_exports); | ||
// src/types/message.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
import_tsukiko.default.Union([import_tsukiko.default.Literal("string"), import_tsukiko.default.Literal("number")]), | ||
import_tsukiko.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
__reExport(types_exports, require("./config"), module.exports); | ||
__reExport(types_exports, require("./message"), module.exports); | ||
__reExport(types_exports, require("./adapter"), module.exports); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
CommandAccess, | ||
MessageScope, | ||
commandArgTypeSignSchema, | ||
eventDataTargetIdSchema | ||
...require("./config"), | ||
...require("./message"), | ||
...require("./adapter") | ||
}); |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -41,4 +41,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/types/message.ts | ||
var message_exports = {}; | ||
@@ -59,3 +57,3 @@ __export(message_exports, { | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
const commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
import_tsukiko.default.Union([import_tsukiko.default.Literal("string"), import_tsukiko.default.Literal("number")]), | ||
@@ -69,3 +67,3 @@ import_tsukiko.default.Literal("boolean") | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
const eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
@@ -72,0 +70,0 @@ 0 && (module.exports = { |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -41,4 +41,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/utils/command.ts | ||
var command_exports = {}; | ||
@@ -52,49 +50,7 @@ __export(command_exports, { | ||
var import_minimist = __toESM(require("minimist")); | ||
// src/types/message.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
import_tsukiko.default.Union([import_tsukiko.default.Literal("string"), import_tsukiko.default.Literal("number")]), | ||
import_tsukiko.default.Literal("boolean") | ||
]); | ||
var eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
// src/utils/command.ts | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
var import_types = require("../types"); | ||
var import_commandError = require("./commandError"); | ||
const requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
const optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
const defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
@@ -112,3 +68,3 @@ if (type === "boolean") return value !== "false" && !!value; | ||
} | ||
var Command = class { | ||
class Command { | ||
static run(input, data) { | ||
@@ -120,3 +76,3 @@ let starts = ""; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
if (!starts) return new import_commandError.CommandError({ type: "unknown", input }); | ||
const opts = { | ||
@@ -136,3 +92,3 @@ string: [], | ||
const arr = (0, import_tools.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
if (!Array.isArray(arr)) return new import_commandError.CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
@@ -144,6 +100,6 @@ const args = result._; | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
if (count.reality < count.expected) return new import_commandError.CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
return new import_commandError.CommandError({ type: "arg_many", ...count }); | ||
let error; | ||
@@ -159,3 +115,3 @@ data.args.forEach((val, index) => { | ||
if (!Number.isNaN(args[index])) return; | ||
error = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
error = new import_commandError.CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
@@ -169,3 +125,3 @@ if (error) return error; | ||
if (Number.isNaN(options[val.realname])) | ||
error = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
error = new import_commandError.CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
@@ -183,3 +139,3 @@ if (error) return error; | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
access: import_types.CommandAccess.MEMBER, | ||
args: [], | ||
@@ -214,3 +170,3 @@ options: [] | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
const type = import_types.commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
@@ -229,3 +185,3 @@ name: result[2], | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
type: import_types.commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
@@ -255,3 +211,3 @@ optional: false | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
type: import_types.commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
@@ -269,3 +225,3 @@ }); | ||
} | ||
}; | ||
} | ||
var command_default = Command; | ||
@@ -272,0 +228,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/utils/commandError.ts | ||
var commandError_exports = {}; | ||
@@ -40,30 +38,4 @@ __export(commandError_exports, { | ||
module.exports = __toCommonJS(commandError_exports); | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
var import_error = require("./error"); | ||
class CommandError extends import_error.KotoriError { | ||
value; | ||
@@ -74,3 +46,3 @@ constructor(value) { | ||
} | ||
}; | ||
} | ||
var commandError_default = CommandError; | ||
@@ -77,0 +49,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/utils/container.ts | ||
var container_exports = {}; | ||
@@ -41,3 +39,3 @@ __export(container_exports, { | ||
var import_tools = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
class Container { | ||
constructor() { | ||
@@ -55,7 +53,7 @@ (0, import_tools.none)(); | ||
return Object.assign( | ||
_Container.getInstance() | ||
Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
} | ||
var container_default = Container; | ||
@@ -62,0 +60,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -31,4 +31,2 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/utils/error.ts | ||
var error_exports = {}; | ||
@@ -42,3 +40,3 @@ __export(error_exports, { | ||
module.exports = __toCommonJS(error_exports); | ||
var KotoriError = class _KotoriError extends Error { | ||
class KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
@@ -53,3 +51,3 @@ super(message); | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
return new Proxy(KotoriError, { | ||
construct(Class, params) { | ||
@@ -64,5 +62,5 @@ const args = params; | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
} | ||
const ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
const DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
var error_default = KotoriError; | ||
@@ -69,0 +67,0 @@ // Annotate the CommonJS export names for ESM import in node: |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,11 +9,9 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
"use strict"; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
@@ -32,14 +30,3 @@ var __export = (target, all) => { | ||
}; | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
// If the importer is in node compatibility mode or this is not an ESM | ||
// file that has been converted to a CommonJS file using a Babel- | ||
// compatible transform (i.e. "__esModule" has not been set), then set | ||
// "default" to the CommonJS "module.exports" for node compatibility. | ||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
mod | ||
)); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/utils/factory.ts | ||
var factory_exports = {}; | ||
@@ -56,709 +43,5 @@ __export(factory_exports, { | ||
module.exports = __toCommonJS(factory_exports); | ||
var import_tools8 = require("@kotori-bot/tools"); | ||
// src/types/message.ts | ||
var import_tsukiko = __toESM(require("tsukiko")); | ||
var CommandAccess = /* @__PURE__ */ ((CommandAccess2) => { | ||
CommandAccess2[CommandAccess2["MEMBER"] = 0] = "MEMBER"; | ||
CommandAccess2[CommandAccess2["MANGER"] = 1] = "MANGER"; | ||
CommandAccess2[CommandAccess2["ADMIN"] = 2] = "ADMIN"; | ||
return CommandAccess2; | ||
})(CommandAccess || {}); | ||
var commandArgTypeSignSchema = import_tsukiko.default.Union([ | ||
import_tsukiko.default.Union([import_tsukiko.default.Literal("string"), import_tsukiko.default.Literal("number")]), | ||
import_tsukiko.default.Literal("boolean") | ||
]); | ||
var MessageScope = /* @__PURE__ */ ((MessageScope2) => { | ||
MessageScope2[MessageScope2["PRIVATE"] = 0] = "PRIVATE"; | ||
MessageScope2[MessageScope2["GROUP"] = 1] = "GROUP"; | ||
return MessageScope2; | ||
})(MessageScope || {}); | ||
var eventDataTargetIdSchema = import_tsukiko.default.Union([import_tsukiko.default.Number(), import_tsukiko.default.String()]); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
ADAPTER_PREFIX: () => ADAPTER_PREFIX, | ||
Adapter: () => Adapter, | ||
Api: () => Api, | ||
CUSTOM_PREFIX: () => CUSTOM_PREFIX, | ||
Cache: () => Cache, | ||
Command: () => Command, | ||
CommandAccess: () => CommandAccess, | ||
CommandError: () => CommandError, | ||
Container: () => Container, | ||
Core: () => Core, | ||
DATABASE_PREFIX: () => DATABASE_PREFIX, | ||
DEFAULT_CORE_CONFIG: () => DEFAULT_CORE_CONFIG, | ||
DEFAULT_PORT: () => DEFAULT_PORT, | ||
DevError: () => DevError, | ||
Elements: () => Elements, | ||
KotoriError: () => KotoriError, | ||
MessageScope: () => MessageScope, | ||
ModuleError: () => ModuleError, | ||
OFFICIAL_MODULES_SCOPE: () => OFFICIAL_MODULES_SCOPE, | ||
PLUGIN_PREFIX: () => PLUGIN_PREFIX, | ||
Symbols: () => Symbols, | ||
cancelFactory: () => cancelFactory, | ||
commandArgTypeSignSchema: () => commandArgTypeSignSchema, | ||
confirmFactory: () => confirmFactory, | ||
disposeFactory: () => disposeFactory, | ||
eventDataTargetIdSchema: () => eventDataTargetIdSchema, | ||
formatFactory: () => formatFactory, | ||
promptFactory: () => promptFactory, | ||
quickFactory: () => quickFactory, | ||
sendMessageFactory: () => sendMessageFactory | ||
}); | ||
__reExport(src_exports, require("fluoro")); | ||
// src/components/core.ts | ||
var import_tools6 = require("@kotori-bot/tools"); | ||
var import_i18n2 = __toESM(require("@kotori-bot/i18n")); | ||
var import_fluoro2 = require("fluoro"); | ||
// src/components/config.ts | ||
var import_tsukiko2 = __toESM(require("tsukiko")); | ||
var import_node_path = require("path"); | ||
var import_tools = require("@kotori-bot/tools"); | ||
// src/global/constants.ts | ||
var import_i18n = require("@kotori-bot/i18n"); | ||
var OFFICIAL_MODULES_SCOPE = "@kotori-bot/"; | ||
var PLUGIN_PREFIX = "kotori-plugin-"; | ||
var DATABASE_PREFIX = `${PLUGIN_PREFIX}database-`; | ||
var ADAPTER_PREFIX = `${PLUGIN_PREFIX}adapter-`; | ||
var CUSTOM_PREFIX = `${PLUGIN_PREFIX}custom-`; | ||
var DEFAULT_PORT = 720; | ||
var DEFAULT_CORE_CONFIG = { | ||
global: { | ||
lang: import_i18n.DEFAULT_LANG, | ||
"command-prefix": "/", | ||
port: DEFAULT_PORT | ||
}, | ||
adapter: {}, | ||
plugin: {} | ||
}; | ||
// src/global/symbols.ts | ||
var Symbols = class { | ||
static adapter = Symbol.for("kotori.core.adapter"); | ||
static bot = Symbol.for("kotori.core.bot"); | ||
static midware = Symbol.for("kotori.core.midware"); | ||
static command = Symbol.for("kotori.core.command"); | ||
static regexp = Symbol.for("kotori.core.regexp"); | ||
static modules = Symbol.for("kotori.loader.module"); | ||
static job = Symbol.for("kotori.loader.job"); | ||
}; | ||
// src/components/config.ts | ||
var packageInfoSchema = import_tsukiko2.default.Object({ | ||
name: import_tsukiko2.default.String(), | ||
version: import_tsukiko2.default.String(), | ||
description: import_tsukiko2.default.String(), | ||
main: import_tsukiko2.default.String(), | ||
license: import_tsukiko2.default.Literal("GPL-3.0"), | ||
author: import_tsukiko2.default.String() | ||
}); | ||
var Config = class { | ||
config; | ||
pkg; | ||
constructor(config = DEFAULT_CORE_CONFIG) { | ||
this.config = config; | ||
const info = (0, import_tools.loadConfig)((0, import_node_path.resolve)(__dirname, "../../package.json")); | ||
if (!info || Object.values(info).length === 0) { | ||
process.stderr.write(`Cannot find kotori-bot package.json | ||
`); | ||
process.exit(); | ||
} | ||
const result = packageInfoSchema.parseSafe(info); | ||
if (!result.value) { | ||
process.stderr.write(`File package.json format error: ${result.error.message} | ||
`); | ||
process.exit(); | ||
} | ||
this.pkg = result.data; | ||
} | ||
}; | ||
var config_default = Config; | ||
// src/components/message.ts | ||
var import_tools3 = require("@kotori-bot/tools"); | ||
var import_cron = require("cron"); | ||
// src/utils/command.ts | ||
var import_tools2 = require("@kotori-bot/tools"); | ||
var import_minimist = __toESM(require("minimist")); | ||
// src/utils/error.ts | ||
var KotoriError = class _KotoriError extends Error { | ||
constructor(message, extra, type = "UnknownError") { | ||
super(message); | ||
this.name = type; | ||
this.extra = extra; | ||
} | ||
extra; | ||
name; | ||
extend() { | ||
const { message: fatherMessage, name: fatherType, extra: fatherExtra } = this; | ||
return new Proxy(_KotoriError, { | ||
construct(Class, params) { | ||
const args = params; | ||
args[0] = `${fatherMessage} ${args[0]}`; | ||
args[1] = args[1] ?? fatherExtra; | ||
args[2] = args[2] ?? fatherType; | ||
return new Class(...args); | ||
} | ||
}); | ||
} | ||
}; | ||
var ModuleError = new KotoriError(void 0, void 0, "ModuleError").extend(); | ||
var DevError = new KotoriError(void 0, void 0, "DevError").extend(); | ||
// src/utils/commandError.ts | ||
var CommandError = class extends KotoriError { | ||
value; | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
} | ||
}; | ||
var commandError_default = CommandError; | ||
// src/utils/command.ts | ||
var requiredParamMatch = /<(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?>/; | ||
var optionalParamMatch = /\[(\.\.\.)?(.*?)(:(.*?))?(=(.*?))?\]/; | ||
var defaultType = "string"; | ||
function handleDefaultValue(value, type) { | ||
if (type === "boolean") return value !== "false" && !!value; | ||
if (type === "number") { | ||
if (typeof value === "number") return value; | ||
if (value === true) return 1; | ||
if (value === false) return 0; | ||
const float = parseFloat(value); | ||
const int = parseInt(value, 10); | ||
return float === int ? int : float; | ||
} | ||
return value.toString(); | ||
} | ||
var Command = class { | ||
static run(input, data) { | ||
let starts = ""; | ||
[data.root, ...data.alias].forEach((el) => { | ||
if (starts) return; | ||
if (input.startsWith(`${el} `) || input === el) starts = el; | ||
}); | ||
if (!starts) return new CommandError({ type: "unknown", input }); | ||
const opts = { | ||
string: [], | ||
boolean: [], | ||
alias: {} | ||
}; | ||
data.options.forEach((option) => { | ||
if (option.type === "string") { | ||
opts.string.push(option.realname); | ||
} else if (option.type === "boolean") { | ||
opts.boolean.push(option.realname); | ||
} | ||
opts.alias[option.realname] = option.name; | ||
}); | ||
const arr = (0, import_tools2.parseArgs)(input.slice(starts.length).trim()); | ||
if (!Array.isArray(arr)) return new CommandError({ type: "syntax", ...arr }); | ||
const result = (0, import_minimist.default)(arr, opts); | ||
const args = result._; | ||
const count = { | ||
expected: data.args.filter((el) => !el.optional).length, | ||
reality: args.length | ||
}; | ||
if (count.reality < count.expected) return new CommandError({ type: "arg_few", ...count }); | ||
count.expected = data.args.length; | ||
if ((data.args.length <= 0 || !data.args[data.args.length - 1].rest) && count.reality > count.expected) | ||
return new CommandError({ type: "arg_many", ...count }); | ||
let error2; | ||
data.args.forEach((val, index) => { | ||
if (error2 || index > 0 && !args[index - 1]) return; | ||
if (!args[index] && val.default) { | ||
args[index] = val.default; | ||
return; | ||
} | ||
if (val.rest || !args[index]) return; | ||
args[index] = handleDefaultValue(args[index], val.type); | ||
if (!Number.isNaN(args[index])) return; | ||
error2 = new CommandError({ type: "arg_error", expected: "number", reality: "string", index }); | ||
}); | ||
if (error2) return error2; | ||
const options = {}; | ||
data.options.forEach((val) => { | ||
if (!(val.realname in result)) return; | ||
options[val.realname] = Array.isArray(result[val.realname]) ? result[val.realname][0] : result[val.realname]; | ||
options[val.realname] = handleDefaultValue(options[val.realname], val.type); | ||
if (Number.isNaN(options[val.realname])) | ||
error2 = new CommandError({ type: "option_error", expected: "number", reality: "string", target: val.realname }); | ||
}); | ||
if (error2) return error2; | ||
return { | ||
args: data.args.length > 0 && data.args[data.args.length - 1].rest ? args : args.slice(0, data.args.length), | ||
options | ||
}; | ||
} | ||
template; | ||
meta = { | ||
root: "", | ||
alias: [], | ||
scope: "all", | ||
access: 0 /* MEMBER */, | ||
args: [], | ||
options: [] | ||
}; | ||
constructor(template, config) { | ||
this.template = template; | ||
this.meta = Object.assign(this.meta, config); | ||
this.parse(); | ||
} | ||
parse() { | ||
const [str, description] = this.template.trim().split(" - "); | ||
this.meta.description = description; | ||
const requiredIndex = str.indexOf(" <"); | ||
const optionalIndex = str.indexOf(" ["); | ||
if (requiredIndex === -1 && optionalIndex === -1) { | ||
this.meta.root = str.trim(); | ||
return; | ||
} | ||
if (requiredIndex !== -1 && (optionalIndex === -1 || requiredIndex < optionalIndex)) { | ||
this.meta.root = str.substring(0, requiredIndex).trim(); | ||
} else { | ||
this.meta.root = str.substring(0, optionalIndex).trim(); | ||
} | ||
const args = (0, import_minimist.default)(str.split(" "))._; | ||
args.forEach((arg) => { | ||
const current = this.meta.args[this.meta.args.length - 1]; | ||
if (current && current.rest) return; | ||
let result = optionalParamMatch.exec(arg); | ||
if (result) { | ||
if (!result[2]) return; | ||
const type = commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type, | ||
rest: !!result[1], | ||
optional: true, | ||
default: result[6] ? handleDefaultValue(result[6], type) : void 0 | ||
}); | ||
} | ||
result = requiredParamMatch.exec(arg); | ||
if (!result || !result[2]) return; | ||
if (!result[6] && current && current.optional) return; | ||
this.meta.args.push({ | ||
name: result[2], | ||
type: commandArgTypeSignSchema.parseSafe(result[4]).value ? result[4] : defaultType, | ||
rest: !!result[1], | ||
optional: false | ||
}); | ||
}); | ||
} | ||
alias(alias) { | ||
if (typeof alias === "string") this.meta.alias.push(alias); | ||
else this.meta.alias.push(...alias); | ||
return this; | ||
} | ||
scope(scope) { | ||
this.meta.scope = scope; | ||
return this; | ||
} | ||
access(access) { | ||
this.meta.access = access; | ||
return this; | ||
} | ||
option(name, template) { | ||
const [str, description] = template.trim().split(" "); | ||
const [realname, type] = str.split(":"); | ||
this.meta.options.push({ | ||
realname, | ||
description, | ||
type: commandArgTypeSignSchema.parseSafe(type).value ? type : defaultType, | ||
name: name.charAt(0) | ||
}); | ||
return this; | ||
} | ||
action(callback) { | ||
this.meta.action = callback; | ||
return this; | ||
} | ||
help(text) { | ||
this.meta.help = text; | ||
return this; | ||
} | ||
}; | ||
// src/components/message.ts | ||
var Message = class { | ||
[Symbols.midware] = /* @__PURE__ */ new Set(); | ||
[Symbols.command] = /* @__PURE__ */ new Set(); | ||
[Symbols.regexp] = /* @__PURE__ */ new Set(); | ||
handleMidware(session) { | ||
const { api } = session; | ||
let isPass = true; | ||
let midwares = []; | ||
api.adapter.status.receivedMsg += 1; | ||
this[Symbols.midware].forEach((val) => midwares.push(val)); | ||
midwares = midwares.sort((first, second) => first.priority - second.priority); | ||
let lastMidwareNum = -1; | ||
while (midwares.length > 0) { | ||
if (lastMidwareNum === midwares.length) { | ||
isPass = false; | ||
break; | ||
} | ||
lastMidwareNum = midwares.length; | ||
session.quick(midwares[0].callback(() => midwares.shift(), session)); | ||
} | ||
this.ctx.emit("midwares", { isPass, session }); | ||
} | ||
async handleRegexp(data) { | ||
const { session } = data; | ||
if (!data.isPass) return; | ||
this[Symbols.regexp].forEach((data2) => { | ||
const result = session.message.match(data2.match); | ||
if (!result) return; | ||
session.quick(data2.callback(result, session)); | ||
this.ctx.emit("regexp", { result, session, regexp: data2.match, raw: session.message }); | ||
}); | ||
} | ||
handleCommand(data) { | ||
const { session } = data; | ||
const prefix = session.api.adapter.config["command-prefix"] ?? this.ctx.config.global["command-prefix"]; | ||
if (!session.message.startsWith(prefix)) return; | ||
const params = { | ||
session, | ||
raw: (0, import_tools3.stringRightSplit)(session.message, prefix) | ||
}; | ||
this.ctx.emit("before_parse", params); | ||
const cancel = cancelFactory(); | ||
this.ctx.emit("before_command", { cancel: cancel.get(), ...params }); | ||
if (cancel.value) return; | ||
let matched; | ||
this[Symbols.command].forEach(async (cmd) => { | ||
if (matched || !cmd.meta.action) return; | ||
const result = Command.run(params.raw, cmd.meta); | ||
if (result instanceof commandError_default && result.value.type === "unknown") return; | ||
matched = cmd; | ||
this.ctx.emit("parse", { command: cmd, result, ...params, cancel: cancel.get() }); | ||
if (cancel.value || result instanceof commandError_default) return; | ||
try { | ||
const executed = await cmd.meta.action({ args: result.args, options: result.options }, session); | ||
if (executed instanceof commandError_default) { | ||
this.ctx.emit("command", { command: cmd, result: executed, ...params }); | ||
return; | ||
} | ||
if (executed !== void 0) session.quick(executed); | ||
this.ctx.emit("command", { | ||
command: cmd, | ||
result: executed instanceof commandError_default ? result : executed, | ||
...params | ||
}); | ||
} catch (error2) { | ||
this.ctx.emit("command", { | ||
command: matched, | ||
result: new commandError_default({ type: "error", error: error2 }), | ||
...params | ||
}); | ||
} | ||
}); | ||
if (matched) return; | ||
this.ctx.emit("parse", { | ||
command: new Command(""), | ||
result: new commandError_default({ type: "unknown", input: params.raw }), | ||
...params, | ||
cancel: cancel.get() | ||
}); | ||
} | ||
ctx; | ||
constructor(ctx) { | ||
this.ctx = ctx; | ||
this.ctx.on("on_message", (session) => this.handleMidware(session)); | ||
this.ctx.on("midwares", (data) => this.handleCommand(data)); | ||
this.ctx.on("midwares", (data) => this.handleRegexp(data)); | ||
this.ctx.on("before_send", (data) => { | ||
const { api } = data; | ||
api.adapter.status.sentMsg += 1; | ||
}); | ||
} | ||
midware(callback, priority = 100) { | ||
const data = { callback, priority }; | ||
this[Symbols.midware].add(data); | ||
const dispose = () => this[Symbols.midware].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
command(template, config) { | ||
const command = new Command(template, config); | ||
this[Symbols.command].add(command); | ||
const dispose = () => this[Symbols.command].delete(command); | ||
disposeFactory(this.ctx, dispose); | ||
return command; | ||
} | ||
regexp(match, callback) { | ||
const data = { match, callback }; | ||
this[Symbols.regexp].add(data); | ||
const dispose = () => this[Symbols.regexp].delete(data); | ||
disposeFactory(this.ctx, dispose); | ||
return dispose; | ||
} | ||
// boardcast(type: MessageScope, message: MessageRaw) { | ||
// const send = | ||
// type === 'private' | ||
// ? (api: Api) => api.send_on_message(message, 1) | ||
// : (api: Api) => api.send_on_message(message, 1); | ||
// /* this need support of database... */ | ||
// Object.values(this.botStack).forEach((apis) => { | ||
// apis.forEach((api) => send(api)); | ||
// }); | ||
// } | ||
notify(message) { | ||
const mainAdapterIdentity = Object.keys(this.ctx.config.adapter)[0]; | ||
this.ctx[Symbols.bot].forEach( | ||
(apis) => apis.forEach((api) => { | ||
if (api.adapter.identity !== mainAdapterIdentity) return; | ||
quickFactory( | ||
sendMessageFactory(api.adapter, "on_message", { userId: api.adapter.config.master }), | ||
this.ctx.i18n.extends(api.adapter.config.lang) | ||
)(message); | ||
}) | ||
); | ||
} | ||
task(options, callback) { | ||
const [cron, extraOptions] = typeof options === "string" ? [options, {}] : [options.cron, options]; | ||
return new import_cron.CronJob(cron, () => callback(this.ctx), null, extraOptions.start ?? true, extraOptions.timeZone); | ||
} | ||
}; | ||
var message_default = Message; | ||
// src/service/elements.ts | ||
var import_tools4 = require("@kotori-bot/tools"); | ||
var Elements = class _Elements { | ||
default(...args) { | ||
(0, import_tools4.none)(this, args); | ||
return ""; | ||
} | ||
at(target, ...extra) { | ||
return this.default(target, extra); | ||
} | ||
image(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
voice(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
video(url, ...extra) { | ||
return this.default(url, extra); | ||
} | ||
face(id, ...extra) { | ||
return this.default(id, extra); | ||
} | ||
file(data, ...extra) { | ||
return this.default(data, extra); | ||
} | ||
supports() { | ||
const supports = []; | ||
const keys = ["at", "image", "voice", "video", "face", "file"]; | ||
keys.forEach((key) => { | ||
if (this[key] !== new _Elements()[key]) supports.push(key); | ||
}); | ||
return supports; | ||
} | ||
}; | ||
var elements_default = Elements; | ||
// src/service/adapter.ts | ||
function setProxy(api, ctx) { | ||
const proxy = Object.create(api); | ||
proxy.sendPrivateMsg = new Proxy(api.sendPrivateMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendPrivateMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
proxy.sendGroupMsg = new Proxy(api.sendGroupMsg, { | ||
apply(_, __, argArray) { | ||
const [message, targetId] = argArray; | ||
const cancel = cancelFactory(); | ||
ctx.emit("before_send", { api, message, messageType: 0 /* PRIVATE */, targetId, cancel: cancel.get() }); | ||
if (cancel.value) return; | ||
api.sendGroupMsg(message, targetId, argArray[2]); | ||
} | ||
}); | ||
return proxy; | ||
} | ||
function error(type, data) { | ||
return new commandError_default(Object.assign(data ?? {}, { type })); | ||
} | ||
var Adapter = class { | ||
constructor(ctx, config, identity, Api2, el = new elements_default()) { | ||
this.ctx = ctx; | ||
this.config = config; | ||
this.identity = identity; | ||
this.platform = config.extends; | ||
this.api = setProxy(new Api2(this), this.ctx); | ||
this.elements = el; | ||
if (!this.ctx[Symbols.bot].get(this.platform)) this.ctx[Symbols.bot].set(this.platform, /* @__PURE__ */ new Set()); | ||
this.ctx[Symbols.bot].get(this.platform).add(this.api); | ||
} | ||
online() { | ||
if (this.status.value !== "offline") return; | ||
this.status.value = "online"; | ||
this.ctx.emit("status", { adapter: this, status: "online" }); | ||
} | ||
offline() { | ||
if (this.status.value !== "online") return; | ||
this.status.value = "offline"; | ||
this.status.offlineTimes += 1; | ||
this.ctx.emit("status", { adapter: this, status: "offline" }); | ||
} | ||
session(type, data) { | ||
const i18n = this.ctx.i18n.extends(this.config.lang); | ||
const send = sendMessageFactory(this, type, data); | ||
const format = formatFactory(i18n); | ||
const quick = quickFactory(send, i18n); | ||
const prompt = promptFactory(quick, this, data); | ||
const confirm = confirmFactory(quick, this, data); | ||
const { api, elements: el } = this; | ||
this.ctx.emit( | ||
type, | ||
...[{ ...data, api, el, send, i18n, format, quick, prompt, confirm, error }] | ||
); | ||
} | ||
ctx; | ||
config; | ||
identity; | ||
platform; | ||
api; | ||
elements; | ||
status = { | ||
value: "offline", | ||
createTime: /* @__PURE__ */ new Date(), | ||
lastMsgTime: null, | ||
receivedMsg: 0, | ||
sentMsg: 0, | ||
offlineTimes: 0 | ||
}; | ||
selfId = -1; | ||
}; | ||
// src/service/api.ts | ||
var import_tools5 = require("@kotori-bot/tools"); | ||
var Api = class { | ||
adapter; | ||
constructor(adapter) { | ||
this.adapter = adapter; | ||
} | ||
sendPrivateMsg(message, userId, ...extra) { | ||
(0, import_tools5.none)(this, message, userId, extra); | ||
} | ||
sendGroupMsg(message, groupId, ...extra) { | ||
(0, import_tools5.none)(this, message, groupId, extra, extra); | ||
} | ||
deleteMsg(messageId, ...extra) { | ||
(0, import_tools5.none)(this, messageId, extra); | ||
} | ||
setGroupName(groupId, groupName, ...extra) { | ||
(0, import_tools5.none)(this, groupId, groupName, extra); | ||
} | ||
setGroupAvatar(groupId, image, ...extra) { | ||
(0, import_tools5.none)(this, groupId, image, extra); | ||
} | ||
setGroupAdmin(groupId, userId, enable, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, enable, extra); | ||
} | ||
setGroupCard(groupId, userId, card, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, card, extra); | ||
} | ||
setGroupBan(groupId, userId, time, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, time, extra); | ||
} | ||
sendGroupNotice(groupId, content, image, ...extra) { | ||
(0, import_tools5.none)(this, groupId, content, image, extra); | ||
} | ||
setGroupKick(groupId, userId, ...extra) { | ||
(0, import_tools5.none)(this, groupId, userId, extra); | ||
} | ||
setGroupLeave(groupId, ...extra) { | ||
(0, import_tools5.none)(this, groupId, groupId, extra); | ||
} | ||
}; | ||
// src/service/cache.ts | ||
var import_fluoro = require("fluoro"); | ||
var Cache = class extends import_fluoro.Service { | ||
cache; | ||
constructor(ctx) { | ||
super(ctx, {}, "cache"); | ||
} | ||
start() { | ||
if (this.cache) return; | ||
this.cache = /* @__PURE__ */ new Map(); | ||
} | ||
stop() { | ||
this.cache?.forEach((el) => el.clear()); | ||
this.cache?.clear(); | ||
delete this.cache; | ||
} | ||
getContainer() { | ||
const key = this.ctx.identity ?? "root"; | ||
if (!this.cache.has(key)) this.cache.set(key, /* @__PURE__ */ new Map()); | ||
return this.cache.get(key); | ||
} | ||
get(prop) { | ||
return this.getContainer().get(prop); | ||
} | ||
set(prop, value) { | ||
this.getContainer().set(prop, value); | ||
} | ||
}; | ||
// src/components/core.ts | ||
var Core = class extends import_fluoro2.Context { | ||
[Symbols.adapter] = /* @__PURE__ */ new Map(); | ||
[Symbols.bot] = /* @__PURE__ */ new Map(); | ||
constructor(config) { | ||
super(); | ||
this.provide("config", new config_default(config)); | ||
this.mixin("config", ["config", "pkg"]); | ||
this.provide("message", new message_default(this)); | ||
this.mixin("message", ["midware", "command", "regexp", "notify", "task"]); | ||
this.provide("http", new import_tools6.Http({ validateStatus: () => true })); | ||
this.inject("http"); | ||
this.provide("i18n", new import_i18n2.default({ lang: this.config.global.lang })); | ||
this.inject("i18n"); | ||
this.service("cache", new Cache(this.extends())); | ||
} | ||
}; | ||
// src/utils/container.ts | ||
var import_tools7 = require("@kotori-bot/tools"); | ||
var Container = class _Container { | ||
constructor() { | ||
(0, import_tools7.none)(); | ||
} | ||
static instance = {}; | ||
static setInstance(ctx) { | ||
this.instance = ctx; | ||
} | ||
static getInstance() { | ||
return this.instance; | ||
} | ||
static getMixin() { | ||
return Object.assign( | ||
_Container.getInstance() | ||
/* , Context */ | ||
); | ||
} | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("@kotori-bot/tools")); | ||
__reExport(src_exports, require("@kotori-bot/i18n")); | ||
__reExport(src_exports, require("tsukiko")); | ||
// src/utils/factory.ts | ||
var import_types = require("../types"); | ||
var import__ = require(".."); | ||
function disposeFactory(ctx, dispose) { | ||
@@ -790,2 +73,3 @@ ctx.once("dispose_module", (data) => { | ||
params.forEach((value, index) => { | ||
if (value === void 0 || value === null) return; | ||
str = str.replaceAll(`{${index}}`, i18n.locale(typeof value === "string" ? value : String(value))); | ||
@@ -796,10 +80,11 @@ }); | ||
Object.keys(params).forEach((key) => { | ||
if (params[key] === void 0 || params[key] === null) return; | ||
if (typeof params[key] !== "string") params[key] = String(params[key]); | ||
params[key] = i18n.locale(params[key]); | ||
}); | ||
return (0, import_tools8.stringTemp)(i18n.locale(template), params); | ||
return (0, import_tools.stringTemp)(i18n.locale(template), params); | ||
}; | ||
} | ||
function sendMessageFactory(adapter, type, data) { | ||
if ((data.type === 1 /* GROUP */ || type.includes("group")) && "groupId" in data) { | ||
if ((data.type === import_types.MessageScope.GROUP || type.includes("group")) && "groupId" in data) { | ||
return (message) => { | ||
@@ -816,3 +101,3 @@ adapter.api.sendGroupMsg(message, data.groupId, data.extra); | ||
const msg = await message; | ||
if (!msg || msg instanceof CommandError) return; | ||
if (!msg || msg instanceof import__.CommandError) return; | ||
if (typeof msg === "string") { | ||
@@ -829,6 +114,6 @@ send(i18n.locale(msg)); | ||
function promptFactory(quick, adapter, data) { | ||
return (message) => new Promise((resolve2) => { | ||
return (message) => new Promise((resolve) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message); | ||
resolve(session.message); | ||
return; | ||
@@ -842,6 +127,6 @@ } | ||
function confirmFactory(quick, adapter, data) { | ||
return (options) => new Promise((resolve2) => { | ||
return (options) => new Promise((resolve) => { | ||
const handle = (session) => { | ||
if (isSameSender(adapter, data, session)) { | ||
resolve2(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
resolve(session.message === (options?.sure ?? "corei18n.template.confirm.sure")); | ||
return; | ||
@@ -848,0 +133,0 @@ } |
/** | ||
* @Package @kotori-bot/core | ||
* @Version 1.4.2-beta.1 | ||
* @Version 1.5.0 | ||
* @Author Hotaru <biyuehuya@gmail.com> | ||
@@ -9,3 +9,3 @@ * @Copyright 2024 Hotaru. All rights reserved. | ||
* @Link https://github.com/kotorijs/kotori | ||
* @Date 2024/6/6 21:03:53 | ||
* @Date 2024/6/7 11:22:22 | ||
*/ | ||
@@ -27,5 +27,3 @@ | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/utils/jsxFactory.tsx | ||
var jsxFactory_exports = {}; | ||
module.exports = __toCommonJS(jsxFactory_exports); |
{ | ||
"name": "@kotori-bot/core", | ||
"version": "1.5.0", | ||
"version": "1.5.1", | ||
"description": "Kotori Core", | ||
@@ -32,5 +32,5 @@ "main": "lib/index.js", | ||
"tsukiko": "^1.2.5", | ||
"@kotori-bot/i18n": "^1.3.0", | ||
"@kotori-bot/tools": "^1.4.0" | ||
"@kotori-bot/i18n": "^1.3.1", | ||
"@kotori-bot/tools": "^1.4.1" | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
122532
2290
Updated@kotori-bot/i18n@^1.3.1
Updated@kotori-bot/tools@^1.4.1