koishi-plugin-filter-pro 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # koishi-plugin-filter-pro
package/lib/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`koishi`),t=require(`@koishijs/plugin-console`),n=require(`node:path`),r=require(`node:fs/promises`);const i=e.Schema.object({filename:e.Schema.string().default(`rules.json`).description(`持久化文件名(位于 data/filterpro/ 下)。`),debug:e.Schema.boolean().default(!1).description(`输出规则匹配调试日志。`)}),a=Symbol.for(`koishi.loader.record`);var o=class extends t.DataService{constructor(e,t){super(e,`filter-pro`),this.state=t}async get(){return u(this.state.rules).map(c)}};function s(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}function c(e){return{id:e.id,name:e.name,enabled:e.enabled,priority:e.priority,action:e.action,target:{...e.target},condition:l(e.condition),response:e.response}}function l(e){return e.type===`group`?{type:`group`,operator:e.operator,children:e.children.map(l)}:e.type===`not`?{type:`not`,child:l(e.child)}:{type:`compare`,field:e.field,operator:e.operator,value:e.value}}function u(e){return[...e].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))}function d(e){if(!e||typeof e!=`object`)return s();let t=e;if(t.type===`group`)return{type:`group`,operator:t.operator===`or`?`or`:`and`,children:Array.isArray(t.children)?t.children.map(d):[]};if(t.type===`not`)return{type:`not`,child:d(t.child)};let n=[`eq`,`ne`,`includes`,`regex`,`gt`,`gte`,`lt`,`lte`,`exists`].includes(t.operator)?t.operator:`eq`;return{type:`compare`,field:typeof t.field==`string`?t.field:`content`,operator:n,value:t.value}}function f(t){let n=t.target||{type:`global`},r=typeof n.value==`string`?n.value.trim():``,i=n.type===`plugin`?r:``,a={type:n.type===`plugin`?`plugin`:`global`,value:i};return{id:t.id||e.Random.id(8),name:t.name||`new-rule`,enabled:t.enabled??!0,priority:t.priority??0,action:t.action||`block`,target:a,condition:d(t.condition),response:t.response??``}}function p(e,t){if(!e||e.type===`global`)return!0;let n=typeof t.pluginKey==`string`?t.pluginKey:``,r=e.value?.trim();return r?n===r:!1}function m(e){let t=[],n=new Set,r=new Set,i=e=>{let o=e?.scope?.[a];if(!(!o||r.has(o))){r.add(o);for(let[e,r]of Object.entries(o)){let a=String(e).replace(/^~/,``),[o,s=``]=a.split(`:`,2);o&&o!==`group`&&!n.has(a)&&(n.add(a),t.push({key:a,name:o,ident:s,label:s?`${o}:${s}`:o})),i(r?.ctx)}}};return i(e.root),t.sort((e,t)=>e.key.localeCompare(t.key))}function h(e){let t=[],n=new Map;return{rebuild:()=>{t=m(e),n.clear();let r=new Set,i=e=>{let o=e?.scope?.[a];if(!(!o||r.has(o))){r.add(o);for(let[e,r]of Object.entries(o)){let a=String(e).replace(/^~/,``),o=t.find(e=>e.key===a);o&&r?.ctx?.scope&&n.set(r.ctx.scope,o),i(r?.ctx)}}};i(e.root)},list:()=>t,resolveByCommand:e=>{let t=e?.caller?.scope,r=new Set;for(;t&&!r.has(t);){r.add(t);let e=n.get(t);if(e)return e;t=t.parent}}}}function g(e,t){if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(!r||typeof r!=`object`)return;r=r[e]}return r}function _(e){if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`&&e.trim()){let t=Number(e);return Number.isFinite(t)?t:null}return null}function v(e){return e==null||typeof e==`object`?e:String(e)}function y(e,t){if(t.operator===`exists`)return e!=null;let n=t.value,r=v(e),i=v(n);if(t.operator===`eq`)return r===i;if(t.operator===`ne`)return r!==i;if(t.operator===`includes`)return typeof r==`string`?r.includes(String(i??``)):Array.isArray(e)?e.map(e=>v(e)).includes(i):!1;if(t.operator===`regex`){if(typeof r!=`string`)return!1;try{return new RegExp(String(i??``)).test(r)}catch{return!1}}let a=_(e),o=_(n);return a===null||o===null?!1:t.operator===`gt`?a>o:t.operator===`gte`?a>=o:t.operator===`lt`?a<o:t.operator===`lte`?a<=o:!1}function b(e,t){return e.type===`group`?e.children.length?e.operator===`and`?e.children.every(e=>b(e,t)):e.children.some(e=>b(e,t)):!0:e.type===`not`?!b(e.child,t):y(g(t,e.field),e)}async function x(e){try{let t=await(0,r.readFile)(e,`utf8`),n=JSON.parse(t);return Array.isArray(n)?n.map(e=>f(e)):[]}catch{return null}}function S(e){let t=Promise.resolve();return async n=>{t=t.catch(()=>{}).then(async()=>{await(0,r.writeFile)(e,JSON.stringify(n.map(c),null,2),`utf8`)}),await t}}function C(e,t={}){let i=(0,n.join)(e.baseDir||process.cwd(),`data`,`filterpro`),a=(0,n.join)(i,t.filename||`rules.json`),s={rules:[]},l=S(a),d=h(e),m=e.logger(`filter-pro`),g=!!t.debug,_=(e,t)=>{g&&m.info(`[trace:%s] %s`,e,JSON.stringify(t))},v=(async()=>{await(0,r.mkdir)(i,{recursive:!0});let e=await x(a);if(e){s.rules=e;return}s.rules=[],await l(s.rules)})().catch(t=>{e.logger(`filter-pro`).warn(`failed to initialize persistent rules: %s`,String(t)),s.rules=[]}),y=async()=>{await v,d.rebuild()};y(),e.on(`ready`,y),e.on(`internal/fork`,y),e.on(`internal/update`,y),e.on(`internal/runtime`,y),e.middleware(async(e,t)=>{await v;let n={platform:String(e.platform??``),selfId:String(e.selfId??``),userId:String(e.userId??``),channelId:String(e.channelId??``),guildId:String(e.guildId??``),isDirect:e.isDirect,content:String(e.content??``),type:String(e.type??``),event:e.event,author:e.author,quote:e.quote};_(`message:incoming`,{platform:n.platform,userId:n.userId,channelId:n.channelId,guildId:n.guildId,isDirect:n.isDirect,content:n.content,ruleCount:s.rules.length});for(let e of u(s.rules)){if(!e.enabled||e.target.type!==`global`)continue;if(!p(e.target,n)){_(`message:skip-target`,{ruleId:e.id,ruleName:e.name,target:e.target,pluginKey:n.pluginKey});continue}let r=b(e.condition,n);if(_(`message:evaluate`,{ruleId:e.id,ruleName:e.name,action:e.action,matched:r,expr:e.condition}),r)return e.action===`bypass`?(_(`message:action`,{ruleId:e.id,action:`bypass`}),t()):e.response?(_(`message:action`,{ruleId:e.id,action:`block`,response:e.response}),e.response):(_(`message:action`,{ruleId:e.id,action:`block`,response:``}),``)}return _(`message:pass`,{reason:`no-rule-matched`}),t()},!0),e.before(`command/execute`,async e=>{await v;let t=d.resolveByCommand(e.command),n={platform:String(e.session.platform??``),selfId:String(e.session.selfId??``),userId:String(e.session.userId??``),channelId:String(e.session.channelId??``),guildId:String(e.session.guildId??``),isDirect:e.session.isDirect,content:String(e.session.content??``),type:String(e.session.type??``),event:e.session.event,author:e.session.author,quote:e.session.quote,commandName:String(e.command.name??``),pluginKey:t?.key,pluginName:t?.name};_(`command:incoming`,{command:n.commandName,pluginKey:n.pluginKey,pluginName:n.pluginName,isDirect:n.isDirect,guildId:n.guildId,content:n.content,ruleCount:s.rules.length});for(let e of u(s.rules)){if(!e.enabled||e.target.type===`global`)continue;if(!p(e.target,n)){_(`command:skip-target`,{ruleId:e.id,ruleName:e.name,target:e.target,pluginKey:n.pluginKey});continue}let t=b(e.condition,n);if(_(`command:evaluate`,{ruleId:e.id,ruleName:e.name,action:e.action,matched:t,expr:e.condition}),t){if(e.action===`bypass`){_(`command:action`,{ruleId:e.id,action:`bypass`});return}return e.response?(_(`command:action`,{ruleId:e.id,action:`block`,response:e.response}),e.response):(_(`command:action`,{ruleId:e.id,action:`block`,response:``}),``)}}_(`command:pass`,{reason:`no-rule-matched`})}),e.inject([`console`],e=>{e.console.addEntry({dev:(0,n.resolve)(__dirname,`../client/index.ts`),prod:(0,n.resolve)(__dirname,`../dist`)});let t=new o(e,s),r=e.console.addListener.bind(e.console),i=async()=>{await l(s.rules),t.refresh()};r(`filter-pro/list`,async()=>(await v,t.get()),{authority:3}),r(`filter-pro/targets`,async()=>(await y(),d.list()),{authority:3}),r(`filter-pro/create`,async e=>{await v;let t=f(e||{});return s.rules.push(t),await i(),c(t)},{authority:3}),r(`filter-pro/update`,async e=>{if(await v,!e?.id)return null;let t=s.rules.findIndex(t=>t.id===e.id);if(t<0)return null;let n=s.rules[t];return s.rules[t]=f({...n,...e,id:n.id}),await i(),c(s.rules[t])},{authority:3}),r(`filter-pro/delete`,async e=>{await v;let t=s.rules.findIndex(t=>t.id===e);return t<0?!1:(s.rules.splice(t,1),await i(),!0)},{authority:3}),r(`filter-pro/reorder`,async e=>{if(await v,!Array.isArray(e))return t.get();let n=new Map(e.map((e,t)=>[e,t]));s.rules.sort((e,t)=>(n.has(e.id)?n.get(e.id):2**53-1)-(n.has(t.id)?n.get(t.id):2**53-1));for(let e=0;e<s.rules.length;e++)s.rules[e].priority=e;return await i(),t.get()},{authority:3}),r(`filter-pro/toggle`,async e=>{if(await v,!e?.id)return null;let t=s.rules.find(t=>t.id===e.id);return t?(t.enabled=!!e.enabled,await i(),c(t)):null},{authority:3})})}exports.Config=i,exports.apply=C,exports.name=`filter-pro`;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`koishi`),t=require(`@koishijs/plugin-console`),n=require(`node:path`),r=require(`node:fs/promises`);const i=e.Schema.object({filename:e.Schema.string().default(`rules.json`).description(`持久化文件名(位于 data/filterpro/ 下)。`),debug:e.Schema.boolean().default(!1).description(`输出规则匹配调试日志。`)}),a=Symbol.for(`koishi.loader.record`);var o=class extends t.DataService{constructor(e,t){super(e,`filter-pro`),this.state=t}async get(){return u(this.state.rules).map(c)}};function s(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}function c(e){return{id:e.id,name:e.name,enabled:e.enabled,priority:e.priority,action:e.action,target:{...e.target},condition:l(e.condition),response:e.response}}function l(e){return e.type===`group`?{type:`group`,operator:e.operator,children:e.children.map(l)}:e.type===`not`?{type:`not`,child:l(e.child)}:{type:`compare`,field:e.field,operator:e.operator,value:e.value}}function u(e){return[...e].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))}function d(e){if(!e||typeof e!=`object`)return s();let t=e;if(t.type===`group`)return{type:`group`,operator:t.operator===`or`?`or`:`and`,children:Array.isArray(t.children)?t.children.map(d):[]};if(t.type===`not`)return{type:`not`,child:d(t.child)};let n=[`eq`,`ne`,`includes`,`regex`,`gt`,`gte`,`lt`,`lte`,`exists`].includes(t.operator)?t.operator:`eq`;return{type:`compare`,field:typeof t.field==`string`?t.field:`content`,operator:n,value:t.value}}function f(t){let n=t.target||{type:`global`},r=typeof n.value==`string`?n.value.trim():``,i=n.type===`plugin`?r:``,a={type:n.type===`plugin`?`plugin`:`global`,value:i};return{id:t.id||e.Random.id(8),name:t.name||`new-rule`,enabled:t.enabled??!0,priority:t.priority??0,action:t.action||`block`,target:a,condition:d(t.condition),response:t.response??``}}function p(e,t){if(!e||e.type===`global`)return!0;let n=typeof t.pluginKey==`string`?t.pluginKey:``,r=e.value?.trim();return r?n===r:!1}function m(e){let t=[],n=new Set,r=new Set,i=e=>{let o=e?.scope?.[a];if(!(!o||r.has(o))){r.add(o);for(let[e,r]of Object.entries(o)){let a=String(e).replace(/^~/,``),[o,s=``]=a.split(`:`,2);o&&o!==`group`&&!n.has(a)&&(n.add(a),t.push({key:a,name:o,ident:s,label:s?`${o}:${s}`:o})),i(r?.ctx)}}};return i(e.root),t.sort((e,t)=>e.key.localeCompare(t.key))}function h(e){let t=new Map,n=new Set,r=e=>{let i=e?.scope?.[a];if(!(!i||n.has(i))){n.add(i);for(let[e,n]of Object.entries(i)){let i=String(e).replace(/^~/,``);t.set(i,n),r(n?.ctx)}}};return r(e.root),t}function g(e,t){let n=[],r=new Map,i=new Map,o=new WeakMap,s=t=>{if(!t)return;let n=r.get(t);if(n)return n;let a=e.loader;if(a?.paths){let e=a.paths(t);for(let t of e||[]){let e=String(t).replace(/^~/,``),n=i.get(e);if(n)return n}}};return{rebuild:()=>{n=m(e),r.clear(),i.clear();for(let e of n)i.set(e.key,e);t?.(`resolver:rebuild:start`,{targetCount:n.length,sample:n.slice(0,10).map(e=>e.key)});let o=new Set,s=e=>{let t=e?.scope?.[a];if(!(!t||o.has(t))){o.add(t);for(let[e,n]of Object.entries(t)){let t=String(e).replace(/^~/,``),a=i.get(t);a&&n?.ctx?.scope&&r.set(n.ctx.scope,a),s(n?.ctx)}}};s(e.root),t?.(`resolver:rebuild:done`,{targetCount:n.length,scopeBindings:r.size})},list:()=>n,resolveByCommand:e=>{let n=String(e?.name??``),r=o.get(e);if(r)return t?.(`resolver:resolve:cache-hit`,{command:n,pluginKey:r.key}),r;let i=s(e?.caller?.scope);return i?(o.set(e,i),t?.(`resolver:resolve:resolved`,{command:n,pluginKey:i.key,pluginName:i.name})):t?.(`resolver:resolve:miss`,{command:n}),i},bindCommand:e=>{let n=s(e?.caller?.scope);n?(o.set(e,n),t?.(`resolver:bind:ok`,{command:String(e?.name??``),pluginKey:n.key,pluginName:n.name})):t?.(`resolver:bind:miss`,{command:String(e?.name??``)})}}}function _(e,t){if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(!r||typeof r!=`object`)return;r=r[e]}return r}function v(e){if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`&&e.trim()){let t=Number(e);return Number.isFinite(t)?t:null}return null}function y(e){return e==null||typeof e==`object`?e:String(e)}function b(e,t){if(t.operator===`exists`)return e!=null;let n=t.value,r=y(e),i=y(n);if(t.operator===`eq`)return r===i;if(t.operator===`ne`)return r!==i;if(t.operator===`includes`)return typeof r==`string`?r.includes(String(i??``)):Array.isArray(e)?e.map(e=>y(e)).includes(i):!1;if(t.operator===`regex`){if(typeof r!=`string`)return!1;try{return new RegExp(String(i??``)).test(r)}catch{return!1}}let a=v(e),o=v(n);return a===null||o===null?!1:t.operator===`gt`?a>o:t.operator===`gte`?a>=o:t.operator===`lt`?a<o:t.operator===`lte`?a<=o:!1}function x(e,t){return e.type===`group`?e.children.length?e.operator===`and`?e.children.every(e=>x(e,t)):e.children.some(e=>x(e,t)):!0:e.type===`not`?!x(e.child,t):b(_(t,e.field),e)}async function S(e){try{let t=await(0,r.readFile)(e,`utf8`),n=JSON.parse(t);return Array.isArray(n)?n.map(e=>f(e)):[]}catch{return null}}function C(e){let t=Promise.resolve();return async n=>{t=t.catch(()=>{}).then(async()=>{await(0,r.writeFile)(e,JSON.stringify(n.map(c),null,2),`utf8`)}),await t}}function w(e,t={}){let i=(0,n.join)(e.baseDir||process.cwd(),`data`,`filterpro`),a=(0,n.join)(i,t.filename||`rules.json`),s={rules:[]},l=C(a),d=e.logger(`filter-pro`),m=!!t.debug,_=(e,t)=>{m&&d.info(`[trace:%s] %s`,e,JSON.stringify(t))},v=g(e,_),y=new Map,b=(e,t={})=>({platform:String(e.platform??``),selfId:String(e.selfId??``),userId:String(e.userId??``),channelId:String(e.channelId??``),guildId:String(e.guildId??``),isDirect:e.isDirect,content:String(e.content??``),type:String(e.type??``),event:e.event,author:e.author,quote:e.quote,...t}),w=(e,t)=>{let n=b(t,{pluginKey:e});for(let t of u(s.rules)){if(!t.enabled||t.target.type!==`plugin`||(t.target.value||``).trim()!==e)continue;let r=x(t.condition,n);if(_(`native-filter:evaluate`,{pluginKey:e,ruleId:t.id,ruleName:t.name,action:t.action,matched:r}),r)return t.action===`bypass`}return!0},T=(async()=>{await(0,r.mkdir)(i,{recursive:!0});let e=await S(a);if(e){s.rules=e;return}s.rules=[],await l(s.rules)})().catch(t=>{e.logger(`filter-pro`).warn(`failed to initialize persistent rules: %s`,String(t)),s.rules=[]}),E=async()=>{await T,v.rebuild();let t=e?.$commander?._commandList;if(Array.isArray(t)){_(`resolver:bind-existing:start`,{commandCount:t.length});for(let e of t)v.bindCommand(e);_(`resolver:bind-existing:done`,{commandCount:t.length})}else _(`resolver:bind-existing:skip`,{reason:`$commander not available`})},D=async()=>{await E();let t=h(e),n=new Set(s.rules.filter(e=>e.enabled&&e.target.type===`plugin`&&!!e.target.value).map(e=>(e.target.value||``).trim()));_(`native-filter:sync:start`,{activeTargetCount:n.size,discoveredForks:t.size});for(let[e,r]of t.entries()){let t=r?.parent;if(!t||typeof t.filter!=`function`)continue;y.has(t)||y.set(t,t.filter);let i=y.get(t);if(!n.has(e)){t.filter=i;continue}t.filter=t=>i(t)?w(e,t):!1}_(`native-filter:sync:done`,{activeTargetCount:n.size})};E(),D(),e.on(`ready`,E),e.on(`internal/fork`,D),e.on(`internal/update`,D),e.on(`internal/runtime`,D),e.on(`command-added`,e=>{v.bindCommand(e),_(`command:added`,{command:String(e?.name??``)})}),e.middleware(async(e,t)=>{await T;let n=b(e);_(`message:incoming`,{platform:n.platform,userId:n.userId,channelId:n.channelId,guildId:n.guildId,isDirect:n.isDirect,content:n.content,ruleCount:s.rules.length});for(let e of u(s.rules)){if(!e.enabled||e.target.type!==`global`)continue;if(!p(e.target,n)){_(`message:skip-target`,{ruleId:e.id,ruleName:e.name,target:e.target,pluginKey:n.pluginKey});continue}let r=x(e.condition,n);if(_(`message:evaluate`,{ruleId:e.id,ruleName:e.name,action:e.action,matched:r,expr:e.condition}),r)return e.action===`bypass`?(_(`message:action`,{ruleId:e.id,action:`bypass`}),t()):e.response?(_(`message:action`,{ruleId:e.id,action:`block`,response:e.response}),e.response):(_(`message:action`,{ruleId:e.id,action:`block`,response:``}),``)}return _(`message:pass`,{reason:`no-rule-matched`}),t()},!0),e.before(`command/execute`,async e=>{await T;let t=v.resolveByCommand(e.command),n=b(e.session,{commandName:String(e.command.name??``),pluginKey:t?.key,pluginName:t?.name});_(`command:incoming`,{command:n.commandName,pluginKey:n.pluginKey,pluginName:n.pluginName,isDirect:n.isDirect,guildId:n.guildId,content:n.content,ruleCount:s.rules.length}),_(`command:pass`,{reason:`native-filter-mode`})}),e.inject([`console`],e=>{e.console.addEntry({dev:(0,n.resolve)(__dirname,`../client/index.ts`),prod:(0,n.resolve)(__dirname,`../dist`)});let t=new o(e,s),r=e.console.addListener.bind(e.console),i=async()=>{await l(s.rules),await D(),t.refresh()};r(`filter-pro/list`,async()=>(await T,t.get()),{authority:3}),r(`filter-pro/targets`,async()=>(await E(),v.list()),{authority:3}),r(`filter-pro/create`,async e=>{await T;let t=f(e||{});return s.rules.push(t),await i(),c(t)},{authority:3}),r(`filter-pro/update`,async e=>{if(await T,!e?.id)return null;let t=s.rules.findIndex(t=>t.id===e.id);if(t<0)return null;let n=s.rules[t];return s.rules[t]=f({...n,...e,id:n.id}),await i(),c(s.rules[t])},{authority:3}),r(`filter-pro/delete`,async e=>{await T;let t=s.rules.findIndex(t=>t.id===e);return t<0?!1:(s.rules.splice(t,1),await i(),!0)},{authority:3}),r(`filter-pro/reorder`,async e=>{if(await T,!Array.isArray(e))return t.get();let n=new Map(e.map((e,t)=>[e,t]));s.rules.sort((e,t)=>(n.has(e.id)?n.get(e.id):2**53-1)-(n.has(t.id)?n.get(t.id):2**53-1));for(let e=0;e<s.rules.length;e++)s.rules[e].priority=e;return await i(),t.get()},{authority:3}),r(`filter-pro/toggle`,async e=>{if(await T,!e?.id)return null;let t=s.rules.find(t=>t.id===e.id);return t?(t.enabled=!!e.enabled,await i(),c(t)):null},{authority:3})})}exports.Config=i,exports.apply=w,exports.name=`filter-pro`;
package/lib/index.mjs CHANGED
@@ -1 +1 @@
1
- import{Random as e,Schema as t}from"koishi";import{DataService as n}from"@koishijs/plugin-console";import{join as r,resolve as i}from"node:path";import{mkdir as a,readFile as o,writeFile as s}from"node:fs/promises";const c=`filter-pro`,l=t.object({filename:t.string().default(`rules.json`).description(`持久化文件名(位于 data/filterpro/ 下)。`),debug:t.boolean().default(!1).description(`输出规则匹配调试日志。`)}),u=Symbol.for(`koishi.loader.record`);var d=class extends n{constructor(e,t){super(e,`filter-pro`),this.state=t}async get(){return h(this.state.rules).map(p)}};function f(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}function p(e){return{id:e.id,name:e.name,enabled:e.enabled,priority:e.priority,action:e.action,target:{...e.target},condition:m(e.condition),response:e.response}}function m(e){return e.type===`group`?{type:`group`,operator:e.operator,children:e.children.map(m)}:e.type===`not`?{type:`not`,child:m(e.child)}:{type:`compare`,field:e.field,operator:e.operator,value:e.value}}function h(e){return[...e].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))}function g(e){if(!e||typeof e!=`object`)return f();let t=e;if(t.type===`group`)return{type:`group`,operator:t.operator===`or`?`or`:`and`,children:Array.isArray(t.children)?t.children.map(g):[]};if(t.type===`not`)return{type:`not`,child:g(t.child)};let n=[`eq`,`ne`,`includes`,`regex`,`gt`,`gte`,`lt`,`lte`,`exists`].includes(t.operator)?t.operator:`eq`;return{type:`compare`,field:typeof t.field==`string`?t.field:`content`,operator:n,value:t.value}}function _(t){let n=t.target||{type:`global`},r=typeof n.value==`string`?n.value.trim():``,i=n.type===`plugin`?r:``,a={type:n.type===`plugin`?`plugin`:`global`,value:i};return{id:t.id||e.id(8),name:t.name||`new-rule`,enabled:t.enabled??!0,priority:t.priority??0,action:t.action||`block`,target:a,condition:g(t.condition),response:t.response??``}}function v(e,t){if(!e||e.type===`global`)return!0;let n=typeof t.pluginKey==`string`?t.pluginKey:``,r=e.value?.trim();return r?n===r:!1}function y(e){let t=[],n=new Set,r=new Set,i=e=>{let a=e?.scope?.[u];if(!(!a||r.has(a))){r.add(a);for(let[e,r]of Object.entries(a)){let a=String(e).replace(/^~/,``),[o,s=``]=a.split(`:`,2);o&&o!==`group`&&!n.has(a)&&(n.add(a),t.push({key:a,name:o,ident:s,label:s?`${o}:${s}`:o})),i(r?.ctx)}}};return i(e.root),t.sort((e,t)=>e.key.localeCompare(t.key))}function b(e){let t=[],n=new Map;return{rebuild:()=>{t=y(e),n.clear();let r=new Set,i=e=>{let a=e?.scope?.[u];if(!(!a||r.has(a))){r.add(a);for(let[e,r]of Object.entries(a)){let a=String(e).replace(/^~/,``),o=t.find(e=>e.key===a);o&&r?.ctx?.scope&&n.set(r.ctx.scope,o),i(r?.ctx)}}};i(e.root)},list:()=>t,resolveByCommand:e=>{let t=e?.caller?.scope,r=new Set;for(;t&&!r.has(t);){r.add(t);let e=n.get(t);if(e)return e;t=t.parent}}}}function x(e,t){if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(!r||typeof r!=`object`)return;r=r[e]}return r}function S(e){if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`&&e.trim()){let t=Number(e);return Number.isFinite(t)?t:null}return null}function C(e){return e==null||typeof e==`object`?e:String(e)}function w(e,t){if(t.operator===`exists`)return e!=null;let n=t.value,r=C(e),i=C(n);if(t.operator===`eq`)return r===i;if(t.operator===`ne`)return r!==i;if(t.operator===`includes`)return typeof r==`string`?r.includes(String(i??``)):Array.isArray(e)?e.map(e=>C(e)).includes(i):!1;if(t.operator===`regex`){if(typeof r!=`string`)return!1;try{return new RegExp(String(i??``)).test(r)}catch{return!1}}let a=S(e),o=S(n);return a===null||o===null?!1:t.operator===`gt`?a>o:t.operator===`gte`?a>=o:t.operator===`lt`?a<o:t.operator===`lte`?a<=o:!1}function T(e,t){return e.type===`group`?e.children.length?e.operator===`and`?e.children.every(e=>T(e,t)):e.children.some(e=>T(e,t)):!0:e.type===`not`?!T(e.child,t):w(x(t,e.field),e)}async function E(e){try{let t=await o(e,`utf8`),n=JSON.parse(t);return Array.isArray(n)?n.map(e=>_(e)):[]}catch{return null}}function D(e){let t=Promise.resolve();return async n=>{t=t.catch(()=>{}).then(async()=>{await s(e,JSON.stringify(n.map(p),null,2),`utf8`)}),await t}}function O(e,t={}){let n=r(e.baseDir||process.cwd(),`data`,`filterpro`),o=r(n,t.filename||`rules.json`),s={rules:[]},c=D(o),l=b(e),u=e.logger(`filter-pro`),f=!!t.debug,m=(e,t)=>{f&&u.info(`[trace:%s] %s`,e,JSON.stringify(t))},g=(async()=>{await a(n,{recursive:!0});let e=await E(o);if(e){s.rules=e;return}s.rules=[],await c(s.rules)})().catch(t=>{e.logger(`filter-pro`).warn(`failed to initialize persistent rules: %s`,String(t)),s.rules=[]}),y=async()=>{await g,l.rebuild()};y(),e.on(`ready`,y),e.on(`internal/fork`,y),e.on(`internal/update`,y),e.on(`internal/runtime`,y),e.middleware(async(e,t)=>{await g;let n={platform:String(e.platform??``),selfId:String(e.selfId??``),userId:String(e.userId??``),channelId:String(e.channelId??``),guildId:String(e.guildId??``),isDirect:e.isDirect,content:String(e.content??``),type:String(e.type??``),event:e.event,author:e.author,quote:e.quote};m(`message:incoming`,{platform:n.platform,userId:n.userId,channelId:n.channelId,guildId:n.guildId,isDirect:n.isDirect,content:n.content,ruleCount:s.rules.length});for(let e of h(s.rules)){if(!e.enabled||e.target.type!==`global`)continue;if(!v(e.target,n)){m(`message:skip-target`,{ruleId:e.id,ruleName:e.name,target:e.target,pluginKey:n.pluginKey});continue}let r=T(e.condition,n);if(m(`message:evaluate`,{ruleId:e.id,ruleName:e.name,action:e.action,matched:r,expr:e.condition}),r)return e.action===`bypass`?(m(`message:action`,{ruleId:e.id,action:`bypass`}),t()):e.response?(m(`message:action`,{ruleId:e.id,action:`block`,response:e.response}),e.response):(m(`message:action`,{ruleId:e.id,action:`block`,response:``}),``)}return m(`message:pass`,{reason:`no-rule-matched`}),t()},!0),e.before(`command/execute`,async e=>{await g;let t=l.resolveByCommand(e.command),n={platform:String(e.session.platform??``),selfId:String(e.session.selfId??``),userId:String(e.session.userId??``),channelId:String(e.session.channelId??``),guildId:String(e.session.guildId??``),isDirect:e.session.isDirect,content:String(e.session.content??``),type:String(e.session.type??``),event:e.session.event,author:e.session.author,quote:e.session.quote,commandName:String(e.command.name??``),pluginKey:t?.key,pluginName:t?.name};m(`command:incoming`,{command:n.commandName,pluginKey:n.pluginKey,pluginName:n.pluginName,isDirect:n.isDirect,guildId:n.guildId,content:n.content,ruleCount:s.rules.length});for(let e of h(s.rules)){if(!e.enabled||e.target.type===`global`)continue;if(!v(e.target,n)){m(`command:skip-target`,{ruleId:e.id,ruleName:e.name,target:e.target,pluginKey:n.pluginKey});continue}let t=T(e.condition,n);if(m(`command:evaluate`,{ruleId:e.id,ruleName:e.name,action:e.action,matched:t,expr:e.condition}),t){if(e.action===`bypass`){m(`command:action`,{ruleId:e.id,action:`bypass`});return}return e.response?(m(`command:action`,{ruleId:e.id,action:`block`,response:e.response}),e.response):(m(`command:action`,{ruleId:e.id,action:`block`,response:``}),``)}}m(`command:pass`,{reason:`no-rule-matched`})}),e.inject([`console`],e=>{e.console.addEntry({dev:i(__dirname,`../client/index.ts`),prod:i(__dirname,`../dist`)});let t=new d(e,s),n=e.console.addListener.bind(e.console),r=async()=>{await c(s.rules),t.refresh()};n(`filter-pro/list`,async()=>(await g,t.get()),{authority:3}),n(`filter-pro/targets`,async()=>(await y(),l.list()),{authority:3}),n(`filter-pro/create`,async e=>{await g;let t=_(e||{});return s.rules.push(t),await r(),p(t)},{authority:3}),n(`filter-pro/update`,async e=>{if(await g,!e?.id)return null;let t=s.rules.findIndex(t=>t.id===e.id);if(t<0)return null;let n=s.rules[t];return s.rules[t]=_({...n,...e,id:n.id}),await r(),p(s.rules[t])},{authority:3}),n(`filter-pro/delete`,async e=>{await g;let t=s.rules.findIndex(t=>t.id===e);return t<0?!1:(s.rules.splice(t,1),await r(),!0)},{authority:3}),n(`filter-pro/reorder`,async e=>{if(await g,!Array.isArray(e))return t.get();let n=new Map(e.map((e,t)=>[e,t]));s.rules.sort((e,t)=>(n.has(e.id)?n.get(e.id):2**53-1)-(n.has(t.id)?n.get(t.id):2**53-1));for(let e=0;e<s.rules.length;e++)s.rules[e].priority=e;return await r(),t.get()},{authority:3}),n(`filter-pro/toggle`,async e=>{if(await g,!e?.id)return null;let t=s.rules.find(t=>t.id===e.id);return t?(t.enabled=!!e.enabled,await r(),p(t)):null},{authority:3})})}export{l as Config,O as apply,c as name};
1
+ import{Random as e,Schema as t}from"koishi";import{DataService as n}from"@koishijs/plugin-console";import{join as r,resolve as i}from"node:path";import{mkdir as a,readFile as o,writeFile as s}from"node:fs/promises";const c=`filter-pro`,l=t.object({filename:t.string().default(`rules.json`).description(`持久化文件名(位于 data/filterpro/ 下)。`),debug:t.boolean().default(!1).description(`输出规则匹配调试日志。`)}),u=Symbol.for(`koishi.loader.record`);var d=class extends n{constructor(e,t){super(e,`filter-pro`),this.state=t}async get(){return h(this.state.rules).map(p)}};function f(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}function p(e){return{id:e.id,name:e.name,enabled:e.enabled,priority:e.priority,action:e.action,target:{...e.target},condition:m(e.condition),response:e.response}}function m(e){return e.type===`group`?{type:`group`,operator:e.operator,children:e.children.map(m)}:e.type===`not`?{type:`not`,child:m(e.child)}:{type:`compare`,field:e.field,operator:e.operator,value:e.value}}function h(e){return[...e].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))}function g(e){if(!e||typeof e!=`object`)return f();let t=e;if(t.type===`group`)return{type:`group`,operator:t.operator===`or`?`or`:`and`,children:Array.isArray(t.children)?t.children.map(g):[]};if(t.type===`not`)return{type:`not`,child:g(t.child)};let n=[`eq`,`ne`,`includes`,`regex`,`gt`,`gte`,`lt`,`lte`,`exists`].includes(t.operator)?t.operator:`eq`;return{type:`compare`,field:typeof t.field==`string`?t.field:`content`,operator:n,value:t.value}}function _(t){let n=t.target||{type:`global`},r=typeof n.value==`string`?n.value.trim():``,i=n.type===`plugin`?r:``,a={type:n.type===`plugin`?`plugin`:`global`,value:i};return{id:t.id||e.id(8),name:t.name||`new-rule`,enabled:t.enabled??!0,priority:t.priority??0,action:t.action||`block`,target:a,condition:g(t.condition),response:t.response??``}}function v(e,t){if(!e||e.type===`global`)return!0;let n=typeof t.pluginKey==`string`?t.pluginKey:``,r=e.value?.trim();return r?n===r:!1}function y(e){let t=[],n=new Set,r=new Set,i=e=>{let a=e?.scope?.[u];if(!(!a||r.has(a))){r.add(a);for(let[e,r]of Object.entries(a)){let a=String(e).replace(/^~/,``),[o,s=``]=a.split(`:`,2);o&&o!==`group`&&!n.has(a)&&(n.add(a),t.push({key:a,name:o,ident:s,label:s?`${o}:${s}`:o})),i(r?.ctx)}}};return i(e.root),t.sort((e,t)=>e.key.localeCompare(t.key))}function b(e){let t=new Map,n=new Set,r=e=>{let i=e?.scope?.[u];if(!(!i||n.has(i))){n.add(i);for(let[e,n]of Object.entries(i)){let i=String(e).replace(/^~/,``);t.set(i,n),r(n?.ctx)}}};return r(e.root),t}function x(e,t){let n=[],r=new Map,i=new Map,a=new WeakMap,o=t=>{if(!t)return;let n=r.get(t);if(n)return n;let a=e.loader;if(a?.paths){let e=a.paths(t);for(let t of e||[]){let e=String(t).replace(/^~/,``),n=i.get(e);if(n)return n}}};return{rebuild:()=>{n=y(e),r.clear(),i.clear();for(let e of n)i.set(e.key,e);t?.(`resolver:rebuild:start`,{targetCount:n.length,sample:n.slice(0,10).map(e=>e.key)});let a=new Set,o=e=>{let t=e?.scope?.[u];if(!(!t||a.has(t))){a.add(t);for(let[e,n]of Object.entries(t)){let t=String(e).replace(/^~/,``),a=i.get(t);a&&n?.ctx?.scope&&r.set(n.ctx.scope,a),o(n?.ctx)}}};o(e.root),t?.(`resolver:rebuild:done`,{targetCount:n.length,scopeBindings:r.size})},list:()=>n,resolveByCommand:e=>{let n=String(e?.name??``),r=a.get(e);if(r)return t?.(`resolver:resolve:cache-hit`,{command:n,pluginKey:r.key}),r;let i=o(e?.caller?.scope);return i?(a.set(e,i),t?.(`resolver:resolve:resolved`,{command:n,pluginKey:i.key,pluginName:i.name})):t?.(`resolver:resolve:miss`,{command:n}),i},bindCommand:e=>{let n=o(e?.caller?.scope);n?(a.set(e,n),t?.(`resolver:bind:ok`,{command:String(e?.name??``),pluginKey:n.key,pluginName:n.name})):t?.(`resolver:bind:miss`,{command:String(e?.name??``)})}}}function S(e,t){if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(!r||typeof r!=`object`)return;r=r[e]}return r}function C(e){if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`&&e.trim()){let t=Number(e);return Number.isFinite(t)?t:null}return null}function w(e){return e==null||typeof e==`object`?e:String(e)}function T(e,t){if(t.operator===`exists`)return e!=null;let n=t.value,r=w(e),i=w(n);if(t.operator===`eq`)return r===i;if(t.operator===`ne`)return r!==i;if(t.operator===`includes`)return typeof r==`string`?r.includes(String(i??``)):Array.isArray(e)?e.map(e=>w(e)).includes(i):!1;if(t.operator===`regex`){if(typeof r!=`string`)return!1;try{return new RegExp(String(i??``)).test(r)}catch{return!1}}let a=C(e),o=C(n);return a===null||o===null?!1:t.operator===`gt`?a>o:t.operator===`gte`?a>=o:t.operator===`lt`?a<o:t.operator===`lte`?a<=o:!1}function E(e,t){return e.type===`group`?e.children.length?e.operator===`and`?e.children.every(e=>E(e,t)):e.children.some(e=>E(e,t)):!0:e.type===`not`?!E(e.child,t):T(S(t,e.field),e)}async function D(e){try{let t=await o(e,`utf8`),n=JSON.parse(t);return Array.isArray(n)?n.map(e=>_(e)):[]}catch{return null}}function O(e){let t=Promise.resolve();return async n=>{t=t.catch(()=>{}).then(async()=>{await s(e,JSON.stringify(n.map(p),null,2),`utf8`)}),await t}}function k(e,t={}){let n=r(e.baseDir||process.cwd(),`data`,`filterpro`),o=r(n,t.filename||`rules.json`),s={rules:[]},c=O(o),l=e.logger(`filter-pro`),u=!!t.debug,f=(e,t)=>{u&&l.info(`[trace:%s] %s`,e,JSON.stringify(t))},m=x(e,f),g=new Map,y=(e,t={})=>({platform:String(e.platform??``),selfId:String(e.selfId??``),userId:String(e.userId??``),channelId:String(e.channelId??``),guildId:String(e.guildId??``),isDirect:e.isDirect,content:String(e.content??``),type:String(e.type??``),event:e.event,author:e.author,quote:e.quote,...t}),S=(e,t)=>{let n=y(t,{pluginKey:e});for(let t of h(s.rules)){if(!t.enabled||t.target.type!==`plugin`||(t.target.value||``).trim()!==e)continue;let r=E(t.condition,n);if(f(`native-filter:evaluate`,{pluginKey:e,ruleId:t.id,ruleName:t.name,action:t.action,matched:r}),r)return t.action===`bypass`}return!0},C=(async()=>{await a(n,{recursive:!0});let e=await D(o);if(e){s.rules=e;return}s.rules=[],await c(s.rules)})().catch(t=>{e.logger(`filter-pro`).warn(`failed to initialize persistent rules: %s`,String(t)),s.rules=[]}),w=async()=>{await C,m.rebuild();let t=e?.$commander?._commandList;if(Array.isArray(t)){f(`resolver:bind-existing:start`,{commandCount:t.length});for(let e of t)m.bindCommand(e);f(`resolver:bind-existing:done`,{commandCount:t.length})}else f(`resolver:bind-existing:skip`,{reason:`$commander not available`})},T=async()=>{await w();let t=b(e),n=new Set(s.rules.filter(e=>e.enabled&&e.target.type===`plugin`&&!!e.target.value).map(e=>(e.target.value||``).trim()));f(`native-filter:sync:start`,{activeTargetCount:n.size,discoveredForks:t.size});for(let[e,r]of t.entries()){let t=r?.parent;if(!t||typeof t.filter!=`function`)continue;g.has(t)||g.set(t,t.filter);let i=g.get(t);if(!n.has(e)){t.filter=i;continue}t.filter=t=>i(t)?S(e,t):!1}f(`native-filter:sync:done`,{activeTargetCount:n.size})};w(),T(),e.on(`ready`,w),e.on(`internal/fork`,T),e.on(`internal/update`,T),e.on(`internal/runtime`,T),e.on(`command-added`,e=>{m.bindCommand(e),f(`command:added`,{command:String(e?.name??``)})}),e.middleware(async(e,t)=>{await C;let n=y(e);f(`message:incoming`,{platform:n.platform,userId:n.userId,channelId:n.channelId,guildId:n.guildId,isDirect:n.isDirect,content:n.content,ruleCount:s.rules.length});for(let e of h(s.rules)){if(!e.enabled||e.target.type!==`global`)continue;if(!v(e.target,n)){f(`message:skip-target`,{ruleId:e.id,ruleName:e.name,target:e.target,pluginKey:n.pluginKey});continue}let r=E(e.condition,n);if(f(`message:evaluate`,{ruleId:e.id,ruleName:e.name,action:e.action,matched:r,expr:e.condition}),r)return e.action===`bypass`?(f(`message:action`,{ruleId:e.id,action:`bypass`}),t()):e.response?(f(`message:action`,{ruleId:e.id,action:`block`,response:e.response}),e.response):(f(`message:action`,{ruleId:e.id,action:`block`,response:``}),``)}return f(`message:pass`,{reason:`no-rule-matched`}),t()},!0),e.before(`command/execute`,async e=>{await C;let t=m.resolveByCommand(e.command),n=y(e.session,{commandName:String(e.command.name??``),pluginKey:t?.key,pluginName:t?.name});f(`command:incoming`,{command:n.commandName,pluginKey:n.pluginKey,pluginName:n.pluginName,isDirect:n.isDirect,guildId:n.guildId,content:n.content,ruleCount:s.rules.length}),f(`command:pass`,{reason:`native-filter-mode`})}),e.inject([`console`],e=>{e.console.addEntry({dev:i(__dirname,`../client/index.ts`),prod:i(__dirname,`../dist`)});let t=new d(e,s),n=e.console.addListener.bind(e.console),r=async()=>{await c(s.rules),await T(),t.refresh()};n(`filter-pro/list`,async()=>(await C,t.get()),{authority:3}),n(`filter-pro/targets`,async()=>(await w(),m.list()),{authority:3}),n(`filter-pro/create`,async e=>{await C;let t=_(e||{});return s.rules.push(t),await r(),p(t)},{authority:3}),n(`filter-pro/update`,async e=>{if(await C,!e?.id)return null;let t=s.rules.findIndex(t=>t.id===e.id);if(t<0)return null;let n=s.rules[t];return s.rules[t]=_({...n,...e,id:n.id}),await r(),p(s.rules[t])},{authority:3}),n(`filter-pro/delete`,async e=>{await C;let t=s.rules.findIndex(t=>t.id===e);return t<0?!1:(s.rules.splice(t,1),await r(),!0)},{authority:3}),n(`filter-pro/reorder`,async e=>{if(await C,!Array.isArray(e))return t.get();let n=new Map(e.map((e,t)=>[e,t]));s.rules.sort((e,t)=>(n.has(e.id)?n.get(e.id):2**53-1)-(n.has(t.id)?n.get(t.id):2**53-1));for(let e=0;e<s.rules.length;e++)s.rules[e].priority=e;return await r(),t.get()},{authority:3}),n(`filter-pro/toggle`,async e=>{if(await C,!e?.id)return null;let t=s.rules.find(t=>t.id===e.id);return t?(t.enabled=!!e.enabled,await r(),p(t)):null},{authority:3})})}export{l as Config,k as apply,c as name};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-filter-pro",
3
3
  "description": "A powerful filter plugin for Koishi",
4
- "version": "1.0.9",
4
+ "version": "1.0.11",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "lib/index.mjs",
7
7
  "types": "lib/index.d.ts",