@@ -292,7 +292,7 @@ index b0e0826..004cff1 100644
292292+ export * from '@cordisjs/plugin-database';
293293 export { version };
294294diff --git a/lib/index.mjs b/lib/index.mjs
295- index b99cd02..cbac35c 100644
295+ index b99cd02..ddbf1bf 100644
296296--- a/lib/index.mjs
297297+++ b/lib/index.mjs
298298@@ -2,16 +2,120 @@ var __defProp = Object.defineProperty;
@@ -691,27 +691,51 @@ index b99cd02..cbac35c 100644
691691 return this;
692692 }
693693 /** @deprecated */
694- @@ -1095,7 +1231,9 @@ __name(toStringType, "toStringType");
694+ @@ -1095,6 +1231,43 @@ __name(toStringType, "toStringType");
695695 // src/command/validate.ts
696696 import { isNullable as isNullable2 } from "cosmokit";
697697 function validate(ctx) {
698- - ctx.permissions.define("command:(name)", {
699- + const permissions = ctx.get("permissions", false);
700- + if (!permissions) return;
701- + permissions.define("command:(name)", {
698+ + // patchbay: the gate comes and goes with the permission service, whichever loads first and across its reloads.
699+ + ctx.inject(["permissions"], (ctx2) => validatePermissions(ctx2));
700+ + ctx.before("command/execute", async (argv) => {
701+ + const { args, options, command, session } = argv;
702+ + function sendHint(message, ...param) {
703+ + return command.config.showWarning ? session.text(message, param) : "";
704+ + }
705+ + __name(sendHint, "sendHint");
706+ + if (command.config.checkArgCount) {
707+ + let index = args.length;
708+ + while (command._arguments[index]?.required) {
709+ + const decl = command._arguments[index];
710+ + await session.send(session.text("internal.prompt-argument", [
711+ + session.text(`commands.${command.name}.arguments.${decl.name}`)
712+ + ]));
713+ + const source = await session.prompt();
714+ + if (isNullable2(source)) {
715+ + return sendHint("internal.insufficient-arguments", decl.name);
716+ + }
717+ + args.push(ctx.$commander.parseValue(source, "argument", argv, decl));
718+ + index++;
719+ + }
720+ + const finalArg = command._arguments[command._arguments.length - 1] || {};
721+ + if (args.length > command._arguments.length && !finalArg.variadic) {
722+ + return sendHint("internal.redunant-arguments");
723+ + }
724+ + }
725+ + if (command.config.checkUnknown) {
726+ + const unknown = Object.keys(options).filter((key) => !command._options[key]);
727+ + if (unknown.length) {
728+ + return sendHint("internal.unknown-option", unknown.join(", "));
729+ + }
730+ + }
731+ + }, true);
732+ + }
733+ + __name(validate, "validate");
734+ + function validatePermissions(ctx) {
735+ ctx.permissions.define("command:(name)", {
702736 depends: /* @__PURE__ */ __name(({ name }) => {
703737 const command = ctx.$commander.get(name);
704- if (!command) return;
705- @@ -1110,7 +1248,7 @@ function validate(ctx) {
706- return ctx.$commander._commandList.map((command) => `command:${command.name}`);
707- }, "list")
708- });
709- - ctx.permissions.define("command:(name):option:(name2)", {
710- + permissions.define("command:(name):option:(name2)", {
711- depends: /* @__PURE__ */ __name(({ name, name2 }) => {
712- return ctx.$commander.get(name)?._options[name2]?.dependencies;
713- }, "depends"),
714- @@ -1130,13 +1268,13 @@ function validate(ctx) {
738+ @@ -1130,50 +1303,19 @@ function validate(ctx) {
715739 return command.config.showWarning ? session.text(message, param) : "";
716740 }
717741 __name(sendHint, "sendHint");
@@ -720,15 +744,55 @@ index b99cd02..cbac35c 100644
720744 for (const option of Object.values(command._options)) {
721745 if (option.name in options) {
722746- permissions.push(`command:${command.name}:option:${option.name}`);
747+ - }
748+ - }
749+ - if (!await ctx.permissions.test(permissions, session)) {
750+ - return sendHint("internal.low-authority");
751+ - }
752+ - }, true);
753+ - ctx.before("command/execute", async (argv) => {
754+ - const { args, options, command, session } = argv;
755+ - function sendHint(message, ...param) {
756+ - return command.config.showWarning ? session.text(message, param) : "";
757+ - }
758+ - __name(sendHint, "sendHint");
759+ - if (command.config.checkArgCount) {
760+ - let index = args.length;
761+ - while (command._arguments[index]?.required) {
762+ - const decl = command._arguments[index];
763+ - await session.send(session.text("internal.prompt-argument", [
764+ - session.text(`commands.${command.name}.arguments.${decl.name}`)
765+ - ]));
766+ - const source = await session.prompt();
767+ - if (isNullable2(source)) {
768+ - return sendHint("internal.insufficient-arguments", decl.name);
769+ - }
770+ - args.push(ctx.$commander.parseValue(source, "argument", argv, decl));
771+ - index++;
772+ - }
773+ - const finalArg = command._arguments[command._arguments.length - 1] || {};
774+ - if (args.length > command._arguments.length && !finalArg.variadic) {
775+ - return sendHint("internal.redunant-arguments");
723776+ required.push(`command:${command.name}:option:${option.name}`);
724777 }
725778 }
726- - if (!await ctx.permissions.test(permissions, session)) {
727- + if (!await permissions.test(required, session)) {
728- return sendHint("internal.low-authority");
779+ - if (command.config.checkUnknown) {
780+ - const unknown = Object.keys(options).filter((key) => !command._options[key]);
781+ - if (unknown.length) {
782+ - return sendHint("internal.unknown-option", unknown.join(", "));
783+ - }
784+ + if (!await ctx.permissions.test(required, session)) {
785+ + const level = command.config.permissions?.map((name) => /^authority:(\d+)$/.exec(name)?.[1]).find(Boolean);
786+ + return level === void 0 ? sendHint("internal.low-authority") : sendHint("internal.low-authority-level", command.displayName, level);
729787 }
730788 }, true);
731- @@ -1182,7 +1320,7 @@ var Commander = class {
789+ }
790+ - __name(validate, "validate");
791+ + __name(validatePermissions, "validatePermissions");
792+
793+ // src/command/index.ts
794+ var isArray = Array.isArray;
795+ @@ -1182,7 +1324,7 @@ var Commander = class {
732796 constructor(ctx, config = {}) {
733797 this.ctx = ctx;
734798 this.config = config;
@@ -737,7 +801,7 @@ index b99cd02..cbac35c 100644
737801 ctx.plugin(validate);
738802 ctx.before("parse", (content, session) => {
739803 const { isDirect, stripped: { prefix, appel } } = session;
740- @@ -1255,7 +1393 ,7 @@ var Commander = class {
804+ @@ -1255,7 +1397 ,7 @@ var Commander = class {
741805 permissions: Schema2.array(String).role("perms").default(["authority:0"]).description("权限继承。"),
742806 dependencies: Schema2.array(String).role("perms").description("权限依赖。")
743807 }), 1e3);
@@ -746,7 +810,7 @@ index b99cd02..cbac35c 100644
746810 const bots = ctx.bots.filter((v) => v.status === Universal3.Status.ONLINE && v.updateCommands);
747811 bots.forEach((bot) => this.updateCommands(bot));
748812 });
749- @@ -1334,6 +1472 ,8 @@ var Commander = class {
813+ @@ -1334,6 +1476 ,8 @@ var Commander = class {
750814 static {
751815 __name(this, "Commander");
752816 }
@@ -755,7 +819,7 @@ index b99cd02..cbac35c 100644
755819 _commandList = [];
756820 defineElementDomain(name, key = name, type = name) {
757821 this.domain(name, (source, session) => {
758- @@ -1456,13 +1596 ,14 @@ var Commander = class {
822+ @@ -1456,13 +1600 ,14 @@ var Commander = class {
759823 });
760824 Object.assign(parent.config, config);
761825 created.forEach((command) => this.ctx.emit("command-added", command));
@@ -773,7 +837,20 @@ index b99cd02..cbac35c 100644
773837 return this.ctx.set(service, { transform, ...options });
774838 }
775839 resolveDomain(type) {
776- @@ -1570,6 +1711,8 @@ var I18n = class {
840+ @@ -1533,10 +1678,10 @@ import { fallback, LocaleTree } from "@koishijs/i18n-utils";
841+ import { h as h4, Logger as Logger2, Schema as Schema3 } from "@satorijs/core";
842+
843+ // src/locales/zh-CN.yml
844+ -var zh_CN_default = { general: { $: "通用设置", name: "中文", paren: "({0})", quote: "“{0}”", comma: ",", and: "和", or: "或", day: "天", hour: "小时", minute: "分钟", second: "秒" }, internal: { $: "核心文本", "error-encountered": "发生未知错误。", "low-authority": "权限不足。", "prompt-argument": "请发送{0}。", "insufficient-arguments": "缺少参数,输入帮助以查看用法。", "redunant-arguments": "存在多余参数,输入帮助以查看用法。", "invalid-argument": "参数 {0} 输入无效,{1}", "unknown-option": "存在未知选项 {0},输入帮助以查看用法。", "invalid-option": "选项 {0} 输入无效,{1}", "check-syntax": "输入帮助以查看用法。", "invalid-number": "请提供一个数字。", "invalid-integer": "请提供一个整数。", "invalid-posint": "请提供一个正整数。", "invalid-natural": "请提供一个非负整数。", "invalid-date": "请输入合法的时间。", "invalid-user": "请指定正确的用户。", "invalid-channel": "请指定正确的频道。", "invalid-image": "请上传图片。", "invalid-audio": "请上传音频。", "invalid-video": "请上传视频。", "invalid-file": "请上传文件。", "suggest-hint": "您要找的是不是{0}?", "suggest-command": "回复句号以使用推测的指令。" }, commands: { $: "指令系统" } };
845+ +var zh_CN_default = { general: { $: "通用设置", name: "中文", paren: "({0})", quote: "“{0}”", comma: ",", and: "和", or: "或", day: "天", hour: "小时", minute: "分钟", second: "秒" }, internal: { $: "核心文本", "error-encountered": "发生未知错误。", "low-authority": "权限不足。", "low-authority-level": "权限不足:{0} 需要 {1} 级权限。", "prompt-argument": "请发送{0}。", "insufficient-arguments": "缺少参数,输入帮助以查看用法。", "redunant-arguments": "存在多余参数,输入帮助以查看用法。", "invalid-argument": "参数 {0} 输入无效,{1}", "unknown-option": "存在未知选项 {0},输入帮助以查看用法。", "invalid-option": "选项 {0} 输入无效,{1}", "check-syntax": "输入帮助以查看用法。", "invalid-number": "请提供一个数字。", "invalid-integer": "请提供一个整数。", "invalid-posint": "请提供一个正整数。", "invalid-natural": "请提供一个非负整数。", "invalid-date": "请输入合法的时间。", "invalid-user": "请指定正确的用户。", "invalid-channel": "请指定正确的频道。", "invalid-image": "请上传图片。", "invalid-audio": "请上传音频。", "invalid-video": "请上传视频。", "invalid-file": "请上传文件。", "suggest-hint": "您要找的是不是{0}?", "suggest-command": "回复句号以使用推测的指令。" }, commands: { $: "指令系统" } };
846+
847+ // src/locales/en-US.yml
848+ -var en_US_default = { general: { $: "General Settings", name: "English", paren: " ({0}) ", quote: '"{0}"', comma: ",", and: "and", or: "or", day: "day", hour: "hour", minute: "minute", second: "second" }, internal: { $: "Internal Text", "error-encountered": "An unknown error has occurred.", "low-authority": "Low authority.", "prompt-argument": "请发送{0}。", "insufficient-arguments": "Insufficient arguments, type help to see usage.", "redunant-arguments": "Redunant arguments, type help to see usage.", "invalid-argument": "Invalid argument {0}, {1}", "unknown-option": "Unknown option {0}, type help to see usage.", "invalid-option": "Invalid option {0}, {1}", "check-syntax": "Type help to see usage.", "invalid-number": "Expect a number.", "invalid-integer": "Expect an integer.", "invalid-posint": "Expect a positive integer.", "invalid-natural": "Expect a non-negative integer.", "invalid-date": "Expect a valid date.", "invalid-user": "Expect a valid user.", "invalid-channel": "Expect a valid channel.", "invalid-image": "Expect an image.", "invalid-audio": "Expect an audio.", "invalid-video": "Expect a video.", "invalid-file": "Expect a file.", "suggest-hint": "Do you mean {0}?", "suggest-command": "Send a period to apply the suggestion." }, commands: { $: "Command System" } };
849+ +var en_US_default = { general: { $: "General Settings", name: "English", paren: " ({0}) ", quote: '"{0}"', comma: ",", and: "and", or: "or", day: "day", hour: "hour", minute: "minute", second: "second" }, internal: { $: "Internal Text", "error-encountered": "An unknown error has occurred.", "low-authority": "Low authority.", "low-authority-level": "Low authority: {0} needs level {1}.", "prompt-argument": "请发送{0}。", "insufficient-arguments": "Insufficient arguments, type help to see usage.", "redunant-arguments": "Redunant arguments, type help to see usage.", "invalid-argument": "Invalid argument {0}, {1}", "unknown-option": "Unknown option {0}, type help to see usage.", "invalid-option": "Invalid option {0}, {1}", "check-syntax": "Type help to see usage.", "invalid-number": "Expect a number.", "invalid-integer": "Expect an integer.", "invalid-posint": "Expect a positive integer.", "invalid-natural": "Expect a non-negative integer.", "invalid-date": "Expect a valid date.", "invalid-user": "Expect a valid user.", "invalid-channel": "Expect a valid channel.", "invalid-image": "Expect an image.", "invalid-audio": "Expect an audio.", "invalid-video": "Expect a video.", "invalid-file": "Expect a file.", "suggest-hint": "Do you mean {0}?", "suggest-command": "Send a period to apply the suggestion." }, commands: { $: "Command System" } };
850+
851+ // src/i18n.ts
852+ var logger2 = new Logger2("i18n");
853+ @@ -1570,6 +1715,8 @@ var I18n = class {
777854 static {
778855 __name(this, "I18n");
779856 }
@@ -782,7 +859,7 @@ index b99cd02..cbac35c 100644
782859 _data = {};
783860 _presets = {};
784861 locales;
785- @@ -1613,7 +1756 ,7 @@ var I18n = class {
862+ @@ -1613,7 +1760 ,7 @@ var I18n = class {
786863 const dict = this._data[locale] ||= {};
787864 const paths = [...typeof args[0] === "string" ? this.set(locale, args[0] + ".", args[1]) : this.set(locale, "", args[0])];
788865 this.ctx.emit("internal/i18n");
@@ -791,7 +868,7 @@ index b99cd02..cbac35c 100644
791868 for (const path2 of paths) {
792869 delete dict[path2];
793870 }
794- @@ -1680,7 +1823 ,7 @@ var I18n = class {
871+ @@ -1680,7 +1827 ,7 @@ var I18n = class {
795872 import { observe } from "@koishijs/utils";
796873 import { isNullable as isNullable4, makeArray as makeArray2 } from "cosmokit";
797874 import { h as h5, Logger as Logger3 } from "@satorijs/core";
@@ -800,7 +877,7 @@ index b99cd02..cbac35c 100644
800877 var logger3 = new Logger3("session");
801878 function collectFields(argv, collectors, fields) {
802879 for (const collector of collectors) {
803- @@ -1700,7 +1843 ,8 @@ var KoishiSession = class {
880+ @@ -1700,7 +1847 ,8 @@ var KoishiSession = class {
804881 __name(this, "KoishiSession");
805882 }
806883 constructor(ctx) {
@@ -810,7 +887,7 @@ index b99cd02..cbac35c 100644
810887 resolve: "session.resolve",
811888 stripped: "session.stripped",
812889 username: "session.username",
813- @@ -1969,7 +2113 ,7 @@ var KoishiSession = class {
890+ @@ -1969,7 +2117 ,7 @@ var KoishiSession = class {
814891 }
815892 }
816893 const { command } = argv;
@@ -819,7 +896,7 @@ index b99cd02..cbac35c 100644
819896 if (this.app.database) {
820897 if (!this.isDirect) {
821898 await this.observeChannel(this.collect("channel", argv, /* @__PURE__ */ new Set(["permissions", "locales"])));
822- @@ -2058,8 +2202 ,7 @@ var logger4 = new Logger4("app");
899+ @@ -2058,8 +2206 ,7 @@ var logger4 = new Logger4("app");
823900 var Permissions = class {
824901 constructor(ctx) {
825902 this.ctx = ctx;
@@ -829,7 +906,7 @@ index b99cd02..cbac35c 100644
829906 this.define("authority:(value)", {
830907 check: /* @__PURE__ */ __name(({ value }, { user }) => {
831908 return !user || user.authority >= +value;
832- @@ -2076,6 +2219 ,8 @@ var Permissions = class {
909+ @@ -2076,6 +2223 ,8 @@ var Permissions = class {
833910 static {
834911 __name(this, "Permissions");
835912 }
@@ -838,7 +915,7 @@ index b99cd02..cbac35c 100644
838915 store = [];
839916 define(pattern, options) {
840917 const entry = {
841- @@ -2167,7 +2312 ,8 @@ var KoishiBot = class {
918+ @@ -2167,7 +2316 ,8 @@ var KoishiBot = class {
842919 __name(this, "KoishiBot");
843920 }
844921 constructor(ctx) {
@@ -848,7 +925,7 @@ index b99cd02..cbac35c 100644
848925 getGuildMemberMap: "bot.getGuildMemberMap",
849926 broadcast: "bot.broadcast"
850927 });
851- @@ -2238,9 +2384 ,11 @@ var SchemaService = class {
928+ @@ -2238,9 +2388 ,11 @@ var SchemaService = class {
852929 static {
853930 __name(this, "SchemaService");
854931 }
@@ -861,7 +938,7 @@ index b99cd02..cbac35c 100644
861938 const target = this.get(name);
862939 const index = target.list.findIndex((a) => a[kSchemaOrder] < order);
863940 schema[kSchemaOrder] = order;
864- @@ -2250,7 +2398 ,7 @@ var SchemaService = class {
941+ @@ -2250,7 +2402 ,7 @@ var SchemaService = class {
865942 target.list.push(schema);
866943 }
867944 this.ctx.emit("internal/schema", name);
@@ -870,7 +947,7 @@ index b99cd02..cbac35c 100644
870947 remove3(target.list, schema);
871948 this.ctx.emit("internal/schema", name);
872949 });
873- @@ -2259,10 +2407 ,10 @@ var SchemaService = class {
950+ @@ -2259,10 +2411 ,10 @@ var SchemaService = class {
874951 return this._data[name] ||= Schema4.intersect([]);
875952 }
876953 set(name, schema) {
@@ -883,7 +960,7 @@ index b99cd02..cbac35c 100644
883960 delete this._data[name];
884961 this.ctx.emit("internal/schema", name);
885962 });
886- @@ -2272,6 +2420 ,95 @@ var SchemaService = class {
963+ @@ -2272,6 +2424 ,95 @@ var SchemaService = class {
887964 // src/context.ts
888965 import { Adapter as Adapter2, Bot as Bot3, Element, h as h6, HTTP as HTTP2, Logger as Logger5, MessageEncoder, Messenger, Quester, Schema as Schema6, segment, Universal as Universal5, z } from "@satorijs/core";
889966 import { resolveConfig } from "cordis";
@@ -979,7 +1056,7 @@ index b99cd02..cbac35c 100644
9791056 var Context = class extends satori.Context {
9801057 static {
9811058 __name(this, "Context");
982- @@ -2279,31 +2516 ,8 @@ var Context = class extends satori.Context {
1059+ @@ -2279,31 +2520 ,8 @@ var Context = class extends satori.Context {
9831060 static shadow = /* @__PURE__ */ Symbol.for("session.shadow");
9841061 constructor(config = {}) {
9851062 super(config);
@@ -1013,7 +1090,7 @@ index b99cd02..cbac35c 100644
10131090 }
10141091 /** @deprecated use `ctx.root` instead */
10151092 get app() {
1016- @@ -2313,25 +2527 ,6 @@ var Context = class extends satori.Context {
1093+ @@ -2313,25 +2531 ,6 @@ var Context = class extends satori.Context {
10171094 get options() {
10181095 return this.root.config;
10191096 }
@@ -1039,7 +1116,7 @@ index b99cd02..cbac35c 100644
10391116 before(name, listener, append = false) {
10401117 const seg = name.split("/");
10411118 seg[seg.length - 1] = "before-" + seg[seg.length - 1];
1042- @@ -2339,19 +2534 ,36 @@ var Context = class extends satori.Context {
1119+ @@ -2339,19 +2538 ,36 @@ var Context = class extends satori.Context {
10431120 }
10441121 };
10451122 var Koishi = class extends cordis.Service {
@@ -1083,7 +1160,7 @@ index b99cd02..cbac35c 100644
10831160 };
10841161 ((Context3) => {
10851162 Context3.Config = Schema5.intersect([
1086- @@ -2399,12 +2611 ,15 @@ var Service3 = class extends satori.Service {
1163+ @@ -2399,12 +2615 ,15 @@ var Service3 = class extends satori.Service {
10871164 this.ctx = new Context();
10881165 }
10891166 };
@@ -1099,7 +1176,7 @@ index b99cd02..cbac35c 100644
10991176 Context as App,
11001177 Argv,
11011178 Bot3 as Bot,
1102- @@ -2426,6 +2641 ,7 @@ export {
1179+ @@ -2426,6 +2645 ,7 @@ export {
11031180 Schema6 as Schema,
11041181 SchemaService,
11051182 Service3 as Service,
0 commit comments