koishi-plugin-filter-pro 1.0.13 → 1.0.14

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/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{icons as e,send as t}from"@koishijs/client";import{Fragment as n,Teleport as r,computed as i,createBlock as a,createCommentVNode as o,createElementBlock as s,createElementVNode as c,createTextVNode as l,createVNode as u,defineComponent as d,normalizeClass as f,normalizeStyle as p,onBeforeUnmount as m,onMounted as h,openBlock as g,ref as _,renderList as v,resolveComponent as y,toDisplayString as b,vModelText as x,watch as S,withCtx as C,withDirectives as w}from"vue";const T=[`disabled`],E={class:`label`},D=[`onClick`];var O=d({__name:`fp-select`,props:{modelValue:{type:String,required:!0},options:{type:Array,required:!0},placeholder:{type:String,required:!1},disabled:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(e,{emit:t}){let l=e,u=t,d=_(null),y=_(!1),x=_({left:0,top:0,width:0}),C=i(()=>l.options.find(e=>e.value===l.modelValue)?.label||``);function w(){l.disabled||(y.value=!y.value,y.value&&A())}function O(e){u(`update:modelValue`,e),y.value=!1}function k(e){let t=e.target;!d.value||!t||d.value.contains(t)||(y.value=!1)}function A(){if(!d.value)return;let e=d.value.getBoundingClientRect(),t=window.innerHeight-e.bottom-6,n=e.top-6,r=t<180&&n>t,i=Math.min(240,r?n:t);x.value={left:e.left,width:e.width,top:r?Math.max(8,e.top-Math.max(120,i)-6):e.bottom+6}}function j(){y.value&&A()}return S(y,e=>{e&&A()}),h(()=>{document.addEventListener(`click`,k),window.addEventListener(`resize`,j),window.addEventListener(`scroll`,j,!0)}),m(()=>{document.removeEventListener(`click`,k),window.removeEventListener(`resize`,j),window.removeEventListener(`scroll`,j,!0)}),(t,i)=>(g(),s(n,null,[c(`div`,{class:`fp-select`,ref_key:`root`,ref:d},[c(`button`,{type:`button`,class:f([`trigger`,{disabled:e.disabled}]),onClick:w,disabled:e.disabled},[c(`span`,E,b(C.value||e.placeholder),1),i[0]||=c(`span`,{class:`arrow`},`▾`,-1)],10,T)],512),(g(),a(r,{to:`body`},[y.value?(g(),s(`div`,{key:0,class:`menu`,style:p({left:`${x.value.left}px`,top:`${x.value.top}px`,width:`${x.value.width}px`})},[(g(!0),s(n,null,v(e.options,t=>(g(),s(`button`,{key:t.value,type:`button`,class:f([`item`,{active:t.value===e.modelValue}]),onClick:e=>O(t.value)},b(t.label),11,D))),128))],4)):o(`v-if`,!0)]))],64))}}),k=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},A=k(O,[[`__scopeId`,`data-v-4a262c3e`]]);const j={class:`cf-editor`},M={class:`rows-section`},N={key:0,class:`connector-sep`},P=[`title`,`onClick`],F={class:`cf-row`},I=[`onUpdate:modelValue`],L={key:1,class:`bool-toggle`},ee=[`checked`,`onChange`],te={class:`bool-label`},ne=[`onUpdate:modelValue`,`onInput`],re=[`disabled`,`onClick`],ie={class:`add-section`},R={class:`preview-section`},z={class:`preview-code`};var B=k(d({name:`ExprEditor`,__name:`expr-editor`,props:{modelValue:{type:Object,required:!0}},emits:[`update:modelValue`],setup(e,{emit:t}){let r=0,d=()=>String(++r),p=[{value:`guildId`,label:`群组 ID(guildId)`},{value:`channelId`,label:`频道 ID(channelId)`},{value:`userId`,label:`用户 ID(userId)`},{value:`platform`,label:`平台(platform)`},{value:`content`,label:`消息内容(content)`},{value:`isDirect`,label:`私聊(isDirect)`},{value:`type`,label:`消息类型(type)`}],m=[...p,{value:`__custom__`,label:`自定义字段...`}],h=[{value:`eq`,label:`等于`},{value:`ne`,label:`不等于`},{value:`includes`,label:`包含`},{value:`regex`,label:`正则匹配`},{value:`gt`,label:`大于`},{value:`gte`,label:`大于等于`},{value:`lt`,label:`小于`},{value:`lte`,label:`小于等于`},{value:`exists`,label:`存在`}],T=[{value:`eq`,label:`等于`},{value:`ne`,label:`不等于`},{value:`exists`,label:`存在`}],E={eq:`eq`,ne:`ne`,includes:`contains`,regex:`matches`,gt:`gt`,gte:`gte`,lt:`lt`,lte:`lte`,exists:`exists`},D=e,O=t,k=_(U(D.modelValue)),B=JSON.stringify(D.modelValue);S(()=>D.modelValue,e=>{let t=JSON.stringify(e);t!==B&&(B=t,k.value=U(e))},{deep:!0});function V(e,t=`guildId`){let n=t===`isDirect`;return{id:d(),field:t,customField:``,operator:`eq`,valueText:n?`false`:``,value:n?!1:``,connector:e}}function H(e,t){let n=p.some(t=>t.value===e.field),r=n?e.field:`__custom__`,i=r===`isDirect`?!1:``,a=e.value??i;return{id:d(),field:r,customField:n?``:e.field,operator:e.operator,valueText:a==null?``:String(a),value:a,connector:t}}function U(e){if(!e)return[V(null)];if(e.type===`compare`)return[H(e,null)];if(e.type===`group`){if(e.children.every(e=>e.type===`compare`))return e.children.map((t,n)=>H(t,n===0?null:e.operator));if(e.operator===`or`){let t=[],n=!0;for(let r of e.children)r.type===`compare`?(t.push(H(r,n?null:`or`)),n=!1):r.type===`group`&&r.operator===`and`&&r.children.forEach((e,r)=>{e.type===`compare`&&(t.push(H(e,n?null:r===0?`or`:`and`)),n=!1)});if(t.length>0)return t}}return[V(null)]}function W(e){return{type:`compare`,field:e.field===`__custom__`?(e.customField||``).trim()||`guildId`:e.field,operator:e.operator,value:e.operator===`exists`?void 0:e.value}}function G(e){if(e.length===0)return{type:`compare`,field:`guildId`,operator:`eq`,value:``};if(e.length===1)return W(e[0]);let t=[],n=[e[0]];for(let r=1;r<e.length;r++)e[r].connector===`or`?(t.push(n),n=[e[r]]):n.push(e[r]);t.push(n);let r=t.map(e=>e.length===1?W(e[0]):{type:`group`,operator:`and`,children:e.map(W)});return r.length===1?r[0]:{type:`group`,operator:`or`,children:r}}function K(e){if(e.type===`compare`){let t=E[e.operator]||e.operator,n=e.value===void 0?``:JSON.stringify(e.value);return`(${e.field} ${t} ${n})`}if(e.type===`group`){let t=e.operator===`and`?` AND `:` OR `;return e.children.map(K).join(t)}return e.type===`not`?`NOT (${K(e.child)})`:``}let q=i(()=>K(G(k.value)));function J(){let e=G(k.value);B=JSON.stringify(e),O(`update:modelValue`,e)}function Y(e){k.value.push(V(e??`and`)),J()}function X(e){k.value.length<=1||(k.value.splice(e,1),e===0&&(k.value[0].connector=null),J())}function Z(e){e<=0||(k.value[e].connector=k.value[e].connector===`or`?`and`:`or`,J())}function Q(e){let t=e.trim();if(!t)return``;if(t===`true`)return!0;if(t===`false`)return!1;if(t===`null`)return null;let n=Number(t);return Number.isFinite(n)?n:e}return(e,t)=>{let r=y(`k-button`);return g(),s(`div`,j,[o(` 条件行 `),c(`div`,M,[(g(!0),s(n,null,v(k.value,(e,t)=>(g(),s(n,{key:e.id},[o(` 连接符(第一行之后显示) `),t>0?(g(),s(`div`,N,[c(`button`,{class:f([`connector-toggle`,`conn-`+e.connector]),title:`点击切换为`+(e.connector===`or`?`且(AND)`:`或(OR)`),onClick:e=>Z(t)},b(e.connector===`or`?`或(OR)`:`且(AND)`),11,P)])):o(`v-if`,!0),o(` 条件行 `),c(`div`,F,[u(A,{"model-value":e.field,options:m,class:`sel-field`,"onUpdate:modelValue":t=>{let n=e.field===`isDirect`;e.field=t,t===`isDirect`?(e.value=!1,e.valueText=`false`,[`eq`,`ne`,`exists`].includes(e.operator)||(e.operator=`eq`)):n&&(e.value=``,e.valueText=``),J()}},null,8,[`model-value`,`onUpdate:modelValue`]),e.field===`__custom__`?w((g(),s(`input`,{key:0,class:`input custom-input`,"onUpdate:modelValue":t=>e.customField=t,onInput:J,placeholder:`字段路径,如 author.name`},null,40,I)),[[x,e.customField]]):o(`v-if`,!0),u(A,{"model-value":e.operator,options:e.field===`isDirect`?T:h,class:`sel-op`,"onUpdate:modelValue":t=>{e.operator=t,J()}},null,8,[`model-value`,`options`,`onUpdate:modelValue`]),o(` isDirect:开关 `),e.field===`isDirect`&&e.operator!==`exists`?(g(),s(`label`,L,[c(`input`,{type:`checkbox`,checked:e.value===!0,onChange:t=>{e.value=t.target.checked,e.valueText=String(e.value),J()}},null,40,ee),c(`span`,te,b(e.value===!0?`是(true)`:`否(false)`),1)])):e.field!==`isDirect`&&e.operator!==`exists`?(g(),s(n,{key:2},[o(` 普通文本输入 `),w(c(`input`,{class:`input val-input`,"onUpdate:modelValue":t=>e.valueText=t,onInput:()=>{e.value=Q(e.valueText),J()},placeholder:`比较值`},null,40,ne),[[x,e.valueText]])],2112)):o(`v-if`,!0),c(`button`,{class:`del-btn`,disabled:k.value.length<=1,onClick:e=>X(t),title:`删除此条件`},`✕`,8,re)])],64))),128))]),o(` 添加条件 `),c(`div`,ie,[k.value.length===0?(g(),a(r,{key:0,onClick:t[0]||=e=>Y(null)},{default:C(()=>[...t[3]||=[l(`+ 添加条件`,-1)]]),_:1})):(g(),s(n,{key:1},[u(r,{onClick:t[1]||=e=>Y(`and`)},{default:C(()=>[...t[4]||=[l(`且(AND)`,-1)]]),_:1}),u(r,{onClick:t[2]||=e=>Y(`or`)},{default:C(()=>[...t[5]||=[l(`或(OR)`,-1)]]),_:1})],64))]),o(` 表达式预览 `),c(`div`,R,[t[6]||=c(`div`,{class:`preview-title`},`表达式预览`,-1),c(`code`,z,b(q.value||`(空)`),1)])])}}}),[[`__scopeId`,`data-v-40533e84`]]);const V={class:`fp-layout`},H={class:`fp-header`},U={class:`actions`},W={class:`fp-main`},G={class:`rule-list`},K=[`onClick`],q={class:`top`},J={class:`name`},Y={class:`meta`},X={class:`editor-body`},Z={class:`editor-grid`},Q={class:`field`},ae={class:`field`},oe={key:0,class:`field`},se={class:`field`},ce={class:`field`},le={class:`field switch`},ue={key:0,class:`field`},de={class:`expr-wrap`},fe={class:`footer-actions`};var pe=k(d({__name:`page`,setup(e){let r=t,d={bypass:`放行`,block:`拦截`},p=[{label:`全局`,value:`global`},{label:`插件`,value:`plugin`}],m=[{label:`放行(bypass)`,value:`bypass`},{label:`拦截(block)`,value:`block`}],h=i(()=>[{label:`请选择插件实例`,value:``},...T.value.map(e=>({label:e.label,value:e.key}))]),S=_([]),T=_([]),E=_(``),D=i(()=>[...S.value].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))),O=i(()=>D.value.find(e=>e.id===E.value));function k(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}async function j(){let[e,t]=await Promise.all([r(`filter-pro/list`),r(`filter-pro/targets`)]);T.value=t,S.value=e,(!E.value||!S.value.some(e=>e.id===E.value))&&(E.value=D.value[0]?.id||``)}async function M(){await r(`filter-pro/create`,{name:`new-rule`,enabled:!0,priority:(D.value.at(-1)?.priority??-1)+1,action:`block`,target:{type:`global`,value:``},condition:k(),response:``}),await j(),E.value=D.value.at(-1)?.id||E.value}async function N(e){e.enabled=!e.enabled,await r(`filter-pro/toggle`,{id:e.id,enabled:e.enabled})}async function P(e){let t=e.target.type===`global`?{type:`global`,value:``}:{type:`plugin`,value:e.target.value||``};await r(`filter-pro/update`,{id:e.id,name:e.name,enabled:e.enabled,priority:e.priority,action:e.action,target:t,condition:e.condition,response:e.response||``}),await j()}async function F(e){await r(`filter-pro/delete`,e),await j()}async function I(e,t){let n=D.value,i=n.findIndex(t=>t.id===e);if(i<0)return;let a=i+t;if(a<0||a>=n.length)return;let o=[...n];[o[i],o[a]]=[o[a],o[i]],await r(`filter-pro/reorder`,o.map(e=>e.id)),await j()}return j(),(e,t)=>{let r=y(`k-button`),i=y(`k-card`),_=y(`k-layout`);return g(),a(_,null,{default:C(()=>[c(`div`,V,[c(`div`,H,[t[16]||=c(`div`,null,[c(`h2`,null,`Filter Pro`),c(`p`,null,[l(`持久化目录:`),c(`code`,null,`data/filterpro`)])],-1),c(`div`,U,[u(r,{onClick:M},{default:C(()=>[...t[12]||=[l(`新建规则`,-1)]]),_:1}),u(r,{onClick:t[0]||=e=>O.value&&P(O.value),disabled:!O.value},{default:C(()=>[...t[13]||=[l(`保存`,-1)]]),_:1},8,[`disabled`]),u(r,{onClick:t[1]||=e=>O.value&&F(O.value.id),disabled:!O.value},{default:C(()=>[...t[14]||=[l(`删除`,-1)]]),_:1},8,[`disabled`]),u(r,{onClick:j},{default:C(()=>[...t[15]||=[l(`刷新`,-1)]]),_:1})])]),c(`div`,W,[u(i,{class:`panel list`},{header:C(()=>[...t[17]||=[c(`div`,{class:`panel-title`},`规则列表`,-1)]]),default:C(()=>[c(`div`,G,[(g(!0),s(n,null,v(D.value,e=>(g(),s(`button`,{key:e.id,class:f([`rule-item`,{active:E.value===e.id}]),onClick:t=>E.value=e.id},[c(`div`,q,[c(`span`,J,b(e.name||`未命名规则`),1),c(`span`,{class:f([`badge`,e.action])},b(d[e.action]),3)]),c(`div`,Y,[c(`span`,null,`#`+b(e.priority),1),c(`span`,null,b(e.target.type===`global`?`全局`:e.target.value||`未指定插件`),1),c(`span`,null,b(e.enabled?`启用`:`停用`),1)])],10,K))),128))])]),_:1}),O.value?(g(),a(i,{key:0,class:`panel editor`},{header:C(()=>[...t[18]||=[c(`div`,{class:`panel-title`},`规则编辑`,-1)]]),default:C(()=>[c(`div`,X,[c(`div`,Z,[c(`label`,Q,[t[19]||=c(`span`,null,`规则名`,-1),w(c(`input`,{class:`input`,"onUpdate:modelValue":t[2]||=e=>O.value.name=e,placeholder:`输入规则名`},null,512),[[x,O.value.name]])]),c(`label`,ae,[t[20]||=c(`span`,null,`目标`,-1),u(A,{modelValue:O.value.target.type,"onUpdate:modelValue":t[3]||=e=>O.value.target.type=e,options:p},null,8,[`modelValue`])]),O.value.target.type===`plugin`?(g(),s(`label`,oe,[t[21]||=c(`span`,null,`插件实例`,-1),u(A,{"model-value":O.value.target.value??``,options:h.value,"onUpdate:modelValue":t[4]||=e=>O.value.target.value=e},null,8,[`model-value`,`options`])])):o(`v-if`,!0),c(`label`,se,[t[22]||=c(`span`,null,`动作`,-1),u(A,{modelValue:O.value.action,"onUpdate:modelValue":t[5]||=e=>O.value.action=e,options:m},null,8,[`modelValue`])]),c(`label`,ce,[t[23]||=c(`span`,null,`优先级`,-1),w(c(`input`,{class:`input`,type:`number`,"onUpdate:modelValue":t[6]||=e=>O.value.priority=e},null,512),[[x,O.value.priority,void 0,{number:!0}]])]),c(`label`,le,[t[25]||=c(`span`,null,`启用状态`,-1),c(`div`,{class:f([`toggle-switch`,{active:O.value.enabled}]),onClick:t[7]||=e=>N(O.value)},[...t[24]||=[c(`div`,{class:`toggle-thumb`},null,-1)]],2)])]),O.value.action===`block`?(g(),s(`label`,ue,[t[26]||=c(`span`,null,`拦截响应`,-1),w(c(`input`,{class:`input`,"onUpdate:modelValue":t[8]||=e=>O.value.response=e,placeholder:`可选,留空则静默拦截`},null,512),[[x,O.value.response]])])):o(`v-if`,!0),c(`div`,de,[t[27]||=c(`div`,{class:`panel-title small`},`条件表达式`,-1),u(B,{modelValue:O.value.condition,"onUpdate:modelValue":t[9]||=e=>O.value.condition=e},null,8,[`modelValue`])]),c(`div`,fe,[u(r,{onClick:t[10]||=e=>I(O.value.id,-1)},{default:C(()=>[...t[28]||=[l(`上移`,-1)]]),_:1}),u(r,{onClick:t[11]||=e=>I(O.value.id,1)},{default:C(()=>[...t[29]||=[l(`下移`,-1)]]),_:1})])])]),_:1})):o(`v-if`,!0)])])]),_:1})}}}),[[`__scopeId`,`data-v-0e916acc`]]);const $={},me={class:`k-icon`,viewBox:`0 0 512 512`,xmlns:`http://www.w3.org/2000/svg`};function he(e,t){return g(),s(`svg`,me,[o(` 漏斗主体 `),t[0]||=c(`path`,{fill:`none`,stroke:`currentColor`,"stroke-width":`32`,"stroke-linejoin":`round`,d:`M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z`},null,-1)])}var ge=k($,[[`render`,he]]),_e=t=>{e.register(`activity:filter-pro`,ge),t.page({name:`规则集`,path:`/filter-pro`,icon:`activity:filter-pro`,order:320,component:pe})};export{_e as default};
1
+ import{icons as e,message as t,send as n}from"@koishijs/client";import{Fragment as r,Teleport as i,computed as a,createBlock as o,createCommentVNode as s,createElementBlock as c,createElementVNode as l,createTextVNode as u,createVNode as d,defineComponent as f,normalizeClass as p,normalizeStyle as m,onBeforeUnmount as h,onMounted as g,openBlock as _,ref as v,renderList as y,resolveComponent as b,toDisplayString as x,vModelText as S,watch as C,withCtx as w,withDirectives as T}from"vue";const E=[`disabled`],D={class:`label`},O=[`onClick`];var k=f({__name:`fp-select`,props:{modelValue:{type:String,required:!0},options:{type:Array,required:!0},placeholder:{type:String,required:!1},disabled:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(e,{emit:t}){let n=e,u=t,d=v(null),f=v(!1),b=v({left:0,top:0,width:0}),S=a(()=>n.options.find(e=>e.value===n.modelValue)?.label||``);function w(){n.disabled||(f.value=!f.value,f.value&&A())}function T(e){u(`update:modelValue`,e),f.value=!1}function k(e){let t=e.target;!d.value||!t||d.value.contains(t)||(f.value=!1)}function A(){if(!d.value)return;let e=d.value.getBoundingClientRect(),t=window.innerHeight-e.bottom-6,n=e.top-6,r=t<180&&n>t,i=Math.min(240,r?n:t);b.value={left:e.left,width:e.width,top:r?Math.max(8,e.top-Math.max(120,i)-6):e.bottom+6}}function j(){f.value&&A()}return C(f,e=>{e&&A()}),g(()=>{document.addEventListener(`click`,k),window.addEventListener(`resize`,j),window.addEventListener(`scroll`,j,!0)}),h(()=>{document.removeEventListener(`click`,k),window.removeEventListener(`resize`,j),window.removeEventListener(`scroll`,j,!0)}),(t,n)=>(_(),c(r,null,[l(`div`,{class:`fp-select`,ref_key:`root`,ref:d},[l(`button`,{type:`button`,class:p([`trigger`,{disabled:e.disabled}]),onClick:w,disabled:e.disabled},[l(`span`,D,x(S.value||e.placeholder),1),n[0]||=l(`span`,{class:`arrow`},`▾`,-1)],10,E)],512),(_(),o(i,{to:`body`},[f.value?(_(),c(`div`,{key:0,class:`menu`,style:m({left:`${b.value.left}px`,top:`${b.value.top}px`,width:`${b.value.width}px`})},[(_(!0),c(r,null,y(e.options,t=>(_(),c(`button`,{key:t.value,type:`button`,class:p([`item`,{active:t.value===e.modelValue}]),onClick:e=>T(t.value)},x(t.label),11,O))),128))],4)):s(`v-if`,!0)]))],64))}}),A=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},j=A(k,[[`__scopeId`,`data-v-4a262c3e`]]);const M={class:`cf-editor`},N={class:`rows-section`},P={key:0,class:`connector-sep`},F=[`title`,`onClick`],I={class:`cf-row`},L=[`onUpdate:modelValue`],R={key:1,class:`bool-toggle`},z=[`checked`,`onChange`],ee={class:`bool-label`},B=[`onUpdate:modelValue`,`onInput`],te=[`disabled`,`onClick`],ne={class:`add-section`},re={class:`preview-section`},ie={class:`preview-code`};var V=A(f({name:`ExprEditor`,__name:`expr-editor`,props:{modelValue:{type:Object,required:!0}},emits:[`update:modelValue`],setup(e,{emit:t}){let n=0,i=()=>String(++n),f=[{value:`guildId`,label:`群组 ID(guildId)`},{value:`channelId`,label:`频道 ID(channelId)`},{value:`userId`,label:`用户 ID(userId)`},{value:`platform`,label:`平台(platform)`},{value:`content`,label:`消息内容(content)`},{value:`isDirect`,label:`私聊(isDirect)`},{value:`type`,label:`消息类型(type)`}],m=[...f,{value:`__custom__`,label:`自定义字段...`}],h=[{value:`eq`,label:`等于`},{value:`ne`,label:`不等于`},{value:`includes`,label:`包含`},{value:`regex`,label:`正则匹配`},{value:`gt`,label:`大于`},{value:`gte`,label:`大于等于`},{value:`lt`,label:`小于`},{value:`lte`,label:`小于等于`},{value:`exists`,label:`存在`}],g=[{value:`eq`,label:`等于`},{value:`ne`,label:`不等于`},{value:`exists`,label:`存在`}],E={eq:`eq`,ne:`ne`,includes:`contains`,regex:`matches`,gt:`gt`,gte:`gte`,lt:`lt`,lte:`lte`,exists:`exists`},D=e,O=t,k=v(U(D.modelValue)),A=JSON.stringify(D.modelValue);C(()=>D.modelValue,e=>{let t=JSON.stringify(e);t!==A&&(A=t,k.value=U(e))},{deep:!0});function V(e,t=`guildId`){let n=t===`isDirect`;return{id:i(),field:t,customField:``,operator:`eq`,valueText:n?`false`:``,value:n?!1:``,connector:e}}function H(e,t){let n=f.some(t=>t.value===e.field),r=n?e.field:`__custom__`,a=r===`isDirect`?!1:``,o=e.value??a;return{id:i(),field:r,customField:n?``:e.field,operator:e.operator,valueText:o==null?``:String(o),value:o,connector:t}}function U(e){if(!e)return[V(null)];if(e.type===`compare`)return[H(e,null)];if(e.type===`group`){if(e.children.every(e=>e.type===`compare`))return e.children.map((t,n)=>H(t,n===0?null:e.operator));if(e.operator===`or`){let t=[],n=!0;for(let r of e.children)r.type===`compare`?(t.push(H(r,n?null:`or`)),n=!1):r.type===`group`&&r.operator===`and`&&r.children.forEach((e,r)=>{e.type===`compare`&&(t.push(H(e,n?null:r===0?`or`:`and`)),n=!1)});if(t.length>0)return t}}return[V(null)]}function W(e){return{type:`compare`,field:e.field===`__custom__`?(e.customField||``).trim()||`guildId`:e.field,operator:e.operator,value:e.operator===`exists`?void 0:e.value}}function G(e){if(e.length===0)return{type:`compare`,field:`guildId`,operator:`eq`,value:``};if(e.length===1)return W(e[0]);let t=[],n=[e[0]];for(let r=1;r<e.length;r++)e[r].connector===`or`?(t.push(n),n=[e[r]]):n.push(e[r]);t.push(n);let r=t.map(e=>e.length===1?W(e[0]):{type:`group`,operator:`and`,children:e.map(W)});return r.length===1?r[0]:{type:`group`,operator:`or`,children:r}}function K(e){if(e.type===`compare`){let t=E[e.operator]||e.operator,n=e.value===void 0?``:JSON.stringify(e.value);return`(${e.field} ${t} ${n})`}if(e.type===`group`){let t=e.operator===`and`?` AND `:` OR `;return e.children.map(K).join(t)}return e.type===`not`?`NOT (${K(e.child)})`:``}let q=a(()=>K(G(k.value)));function J(){let e=G(k.value);A=JSON.stringify(e),O(`update:modelValue`,e)}function Y(e){k.value.push(V(e??`and`)),J()}function X(e){k.value.length<=1||(k.value.splice(e,1),e===0&&(k.value[0].connector=null),J())}function Z(e){e<=0||(k.value[e].connector=k.value[e].connector===`or`?`and`:`or`,J())}function Q(e){let t=e.trim();if(!t)return``;if(t===`true`)return!0;if(t===`false`)return!1;if(t===`null`)return null;let n=Number(t);return Number.isFinite(n)?n:e}return(e,t)=>{let n=b(`k-button`);return _(),c(`div`,M,[s(` 条件行 `),l(`div`,N,[(_(!0),c(r,null,y(k.value,(e,t)=>(_(),c(r,{key:e.id},[s(` 连接符(第一行之后显示) `),t>0?(_(),c(`div`,P,[l(`button`,{class:p([`connector-toggle`,`conn-`+e.connector]),title:`点击切换为`+(e.connector===`or`?`且(AND)`:`或(OR)`),onClick:e=>Z(t)},x(e.connector===`or`?`或(OR)`:`且(AND)`),11,F)])):s(`v-if`,!0),s(` 条件行 `),l(`div`,I,[d(j,{"model-value":e.field,options:m,class:`sel-field`,"onUpdate:modelValue":t=>{let n=e.field===`isDirect`;e.field=t,t===`isDirect`?(e.value=!1,e.valueText=`false`,[`eq`,`ne`,`exists`].includes(e.operator)||(e.operator=`eq`)):n&&(e.value=``,e.valueText=``),J()}},null,8,[`model-value`,`onUpdate:modelValue`]),e.field===`__custom__`?T((_(),c(`input`,{key:0,class:`input custom-input`,"onUpdate:modelValue":t=>e.customField=t,onInput:J,placeholder:`字段路径,如 author.name`},null,40,L)),[[S,e.customField]]):s(`v-if`,!0),d(j,{"model-value":e.operator,options:e.field===`isDirect`?g:h,class:`sel-op`,"onUpdate:modelValue":t=>{e.operator=t,J()}},null,8,[`model-value`,`options`,`onUpdate:modelValue`]),s(` isDirect:开关 `),e.field===`isDirect`&&e.operator!==`exists`?(_(),c(`label`,R,[l(`input`,{type:`checkbox`,checked:e.value===!0,onChange:t=>{e.value=t.target.checked,e.valueText=String(e.value),J()}},null,40,z),l(`span`,ee,x(e.value===!0?`是(true)`:`否(false)`),1)])):e.field!==`isDirect`&&e.operator!==`exists`?(_(),c(r,{key:2},[s(` 普通文本输入 `),T(l(`input`,{class:`input val-input`,"onUpdate:modelValue":t=>e.valueText=t,onInput:()=>{e.value=Q(e.valueText),J()},placeholder:`比较值`},null,40,B),[[S,e.valueText]])],2112)):s(`v-if`,!0),l(`button`,{class:`del-btn`,disabled:k.value.length<=1,onClick:e=>X(t),title:`删除此条件`},`✕`,8,te)])],64))),128))]),s(` 添加条件 `),l(`div`,ne,[k.value.length===0?(_(),o(n,{key:0,onClick:t[0]||=e=>Y(null)},{default:w(()=>[...t[3]||=[u(`+ 添加条件`,-1)]]),_:1})):(_(),c(r,{key:1},[d(n,{onClick:t[1]||=e=>Y(`and`)},{default:w(()=>[...t[4]||=[u(`且(AND)`,-1)]]),_:1}),d(n,{onClick:t[2]||=e=>Y(`or`)},{default:w(()=>[...t[5]||=[u(`或(OR)`,-1)]]),_:1})],64))]),s(` 表达式预览 `),l(`div`,re,[t[6]||=l(`div`,{class:`preview-title`},`表达式预览`,-1),l(`code`,ie,x(q.value||`(空)`),1)])])}}}),[[`__scopeId`,`data-v-40533e84`]]);const H={class:`fp-layout`},U={class:`fp-main`},W={class:`editor-header`},G={class:`rule-list`},K=[`onClick`],q={class:`top`},J={class:`name`},Y={class:`meta`},X={class:`editor-header`},Z={class:`actions`},Q={class:`editor-body`},ae={class:`editor-grid`},oe={class:`field`},se={class:`field`},ce={key:0,class:`field`},le={class:`field`},ue={class:`field`},de={class:`field switch`},fe={class:`expr-wrap`},pe={class:`footer-actions`};var $=A(f({__name:`page`,setup(e){let i=n,f={bypass:`放行`,block:`拦截`},m=[{label:`全局`,value:`global`},{label:`插件`,value:`plugin`}],h=[{label:`放行(bypass)`,value:`bypass`},{label:`拦截(block)`,value:`block`}],g=a(()=>[{label:`请选择插件实例`,value:``},...E.value.map(e=>({label:e.label,value:e.key}))]),C=v([]),E=v([]),D=v(``),O=a(()=>[...C.value].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))),k=a(()=>O.value.find(e=>e.id===D.value));function A(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}async function M(){let[e,n]=await Promise.all([i(`filter-pro/list`),i(`filter-pro/targets`)]);E.value=n,C.value=e,(!D.value||!C.value.some(e=>e.id===D.value))&&(D.value=O.value[0]?.id||``),t.success(`刷新成功`)}async function N(){await i(`filter-pro/create`,{name:`new-rule`,enabled:!0,priority:(O.value.at(-1)?.priority??-1)+1,action:`block`,target:{type:`global`,value:``},condition:A(),response:``}),await M(),D.value=O.value.at(-1)?.id||D.value,t.success(`创建成功`)}function P(e){let t=e.target,n=Number(t.value);(n<1||!Number.isInteger(n))&&(t.value=String(Math.max(1,Math.floor(Math.abs(n))||1)),k.value&&(k.value.priority=Number(t.value)))}async function F(e){e.enabled=!e.enabled,await i(`filter-pro/toggle`,{id:e.id,enabled:e.enabled})}async function I(e){let n=e.target.type===`global`?{type:`global`,value:``}:{type:`plugin`,value:e.target.value||``};await i(`filter-pro/update`,{id:e.id,name:e.name,enabled:e.enabled,priority:e.priority,action:e.action,target:n,condition:e.condition,response:e.response||``}),await M(),t.success(`保存成功`)}async function L(){k.value&&confirm(`确定要删除这条规则吗?`)&&await R(k.value.id)}async function R(e){await i(`filter-pro/delete`,e),await M(),t.success(`删除成功`)}async function z(e,t){let n=O.value,r=n.findIndex(t=>t.id===e);if(r<0)return;let a=r+t;if(a<0||a>=n.length)return;let o=[...n];[o[r],o[a]]=[o[a],o[r]],await i(`filter-pro/reorder`,o.map(e=>e.id)),await M()}return M(),(e,t)=>{let n=b(`k-button`),i=b(`k-card`),a=b(`k-layout`);return _(),o(a,null,{default:w(()=>[l(`div`,H,[l(`div`,U,[d(i,{class:`panel list`},{header:w(()=>[l(`div`,W,[t[11]||=l(`div`,{class:`panel-title`},`规则列表`,-1),d(n,{onClick:N},{default:w(()=>[...t[10]||=[u(`新建规则`,-1)]]),_:1})])]),default:w(()=>[l(`div`,G,[(_(!0),c(r,null,y(O.value,e=>(_(),c(`button`,{key:e.id,class:p([`rule-item`,{active:D.value===e.id}]),onClick:t=>D.value=e.id},[l(`div`,q,[l(`span`,J,x(e.name||`未命名规则`),1),l(`span`,{class:p([`badge`,e.action])},x(f[e.action]),3)]),l(`div`,Y,[l(`span`,null,`#`+x(e.priority),1),l(`span`,null,x(e.target.type===`global`?`全局`:e.target.value||`未指定插件`),1),l(`span`,null,x(e.enabled?`启用`:`停用`),1)])],10,K))),128))])]),_:1}),k.value?(_(),o(i,{key:0,class:`panel editor`},{header:w(()=>[l(`div`,X,[t[15]||=l(`div`,{class:`panel-title`},`规则编辑`,-1),l(`div`,Z,[d(n,{onClick:t[0]||=e=>k.value&&I(k.value),disabled:!k.value},{default:w(()=>[...t[12]||=[u(`保存`,-1)]]),_:1},8,[`disabled`]),d(n,{onClick:L,disabled:!k.value},{default:w(()=>[...t[13]||=[u(`删除`,-1)]]),_:1},8,[`disabled`]),d(n,{onClick:M},{default:w(()=>[...t[14]||=[u(`刷新`,-1)]]),_:1})])])]),default:w(()=>[l(`div`,Q,[l(`div`,ae,[l(`label`,oe,[t[16]||=l(`span`,null,`规则名`,-1),T(l(`input`,{class:`input`,"onUpdate:modelValue":t[1]||=e=>k.value.name=e,placeholder:`输入规则名`},null,512),[[S,k.value.name]])]),l(`label`,se,[t[17]||=l(`span`,null,`目标`,-1),d(j,{modelValue:k.value.target.type,"onUpdate:modelValue":t[2]||=e=>k.value.target.type=e,options:m},null,8,[`modelValue`])]),k.value.target.type===`plugin`?(_(),c(`label`,ce,[t[18]||=l(`span`,null,`插件实例`,-1),d(j,{"model-value":k.value.target.value??``,options:g.value,"onUpdate:modelValue":t[3]||=e=>k.value.target.value=e},null,8,[`model-value`,`options`])])):s(`v-if`,!0),l(`label`,le,[t[19]||=l(`span`,null,`动作`,-1),d(j,{modelValue:k.value.action,"onUpdate:modelValue":t[4]||=e=>k.value.action=e,options:h},null,8,[`modelValue`])]),l(`label`,ue,[t[20]||=l(`span`,null,`优先级`,-1),T(l(`input`,{class:`input`,type:`number`,min:`1`,step:`1`,"onUpdate:modelValue":t[5]||=e=>k.value.priority=e,onInput:P},null,544),[[S,k.value.priority,void 0,{number:!0}]])]),l(`label`,de,[t[22]||=l(`span`,null,`启用状态`,-1),l(`div`,{class:p([`toggle-switch`,{active:k.value.enabled}]),onClick:t[6]||=e=>F(k.value)},[...t[21]||=[l(`div`,{class:`toggle-thumb`},null,-1)]],2)])]),l(`div`,fe,[t[23]||=l(`div`,{class:`panel-title small`},`条件表达式`,-1),d(V,{modelValue:k.value.condition,"onUpdate:modelValue":t[7]||=e=>k.value.condition=e},null,8,[`modelValue`])]),l(`div`,pe,[d(n,{onClick:t[8]||=e=>z(k.value.id,-1)},{default:w(()=>[...t[24]||=[u(`上移`,-1)]]),_:1}),d(n,{onClick:t[9]||=e=>z(k.value.id,1)},{default:w(()=>[...t[25]||=[u(`下移`,-1)]]),_:1})])])]),_:1})):s(`v-if`,!0)])])]),_:1})}}}),[[`__scopeId`,`data-v-0e916acc`]]);const me={},he={class:`k-icon`,viewBox:`0 0 512 512`,xmlns:`http://www.w3.org/2000/svg`};function ge(e,t){return _(),c(`svg`,he,[s(` 漏斗主体 `),t[0]||=l(`path`,{fill:`none`,stroke:`currentColor`,"stroke-width":`32`,"stroke-linejoin":`round`,d:`M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z`},null,-1)])}var _e=A(me,[[`render`,ge]]),ve=t=>{e.register(`activity:filter-pro`,_e),t.page({name:`规则集`,path:`/filter-pro`,icon:`activity:filter-pro`,order:320,component:$})};export{ve as default};
package/dist/style.css CHANGED
@@ -229,20 +229,11 @@
229
229
  box-sizing: border-box;
230
230
  overflow: hidden;
231
231
  }
232
- .fp-header[data-v-0e916acc] {
232
+ .editor-header[data-v-0e916acc] {
233
233
  display: flex;
234
234
  justify-content: space-between;
235
- align-items: flex-start;
235
+ align-items: center;
236
236
  gap: 12px;
237
- margin-bottom: 12px;
238
- }
239
- .fp-header h2[data-v-0e916acc] {
240
- margin: 0;
241
- font-size: 20px;
242
- }
243
- .fp-header p[data-v-0e916acc] {
244
- margin: 4px 0 0;
245
- color: var(--k-text-secondary, #888);
246
237
  }
247
238
  .actions[data-v-0e916acc] {
248
239
  display: flex;
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=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&&e===`native-filter:evaluate`&&t?.matched&&d.info(`[trace:%s] %s`,e,JSON.stringify(t))},v=g(e,_),y=new Map,b=new Map,w=(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}),T=(e,t)=>{let n=w(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},E=(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=[]}),D=async()=>{await E,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`})},O=async()=>{await D();for(let[e,t]of b.entries()){if(e?.filter!==t)continue;let n=y.get(e);n&&(e.filter=n)}b.clear();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}let a=t=>i(t)?T(e,t):!1;t.filter=a,b.set(t,a)}_(`native-filter:sync:done`,{activeTargetCount:n.size})};D(),O(),e.on(`ready`,O),e.on(`internal/fork`,O),e.on(`internal/before-update`,O),e.on(`internal/update`,O),e.on(`internal/runtime`,O),e.on(`dispose`,()=>{for(let[e,t]of b.entries()){if(e?.filter!==t)continue;let n=y.get(e);n&&(e.filter=n)}b.clear()}),e.on(`command-added`,e=>{v.bindCommand(e),_(`command:added`,{command:String(e?.name??``)})}),e.middleware(async(e,t)=>{await E;let n=w(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 E;let t=v.resolveByCommand(e.command),n=w(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 O(),t.refresh()};r(`filter-pro/list`,async()=>(await E,t.get()),{authority:3}),r(`filter-pro/targets`,async()=>(await D(),v.list()),{authority:3}),r(`filter-pro/create`,async e=>{await E;let t=f(e||{});return s.rules.push(t),await i(),c(t)},{authority:3}),r(`filter-pro/update`,async e=>{if(await E,!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 E;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 E,!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 E,!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`;
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);r?.runtime?.plugin?.filter!==!1&&(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&&e===`native-filter:evaluate`&&t?.matched&&d.info(`[trace:%s] %s`,e,JSON.stringify(t))},v=g(e,_),y=new Map,b=new Map,w=(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}),T=(e,t)=>{let n=w(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},E=(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=[]}),D=async()=>{await E,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`})},O=async()=>{await D();for(let[e,t]of b.entries()){if(e?.filter!==t)continue;let n=y.get(e);n&&(e.filter=n)}b.clear();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}let a=t=>i(t)?T(e,t):!1;t.filter=a,b.set(t,a)}_(`native-filter:sync:done`,{activeTargetCount:n.size})};D(),O(),e.on(`ready`,O),e.on(`internal/fork`,O),e.on(`internal/before-update`,O),e.on(`internal/update`,O),e.on(`internal/runtime`,O),e.on(`dispose`,()=>{for(let[e,t]of b.entries()){if(e?.filter!==t)continue;let n=y.get(e);n&&(e.filter=n)}b.clear()}),e.on(`command-added`,e=>{v.bindCommand(e),_(`command:added`,{command:String(e?.name??``)})}),e.middleware(async(e,t)=>{await E;let n=w(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 E;let t=v.resolveByCommand(e.command),n=w(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 O(),t.refresh()};r(`filter-pro/list`,async()=>(await E,t.get()),{authority:3}),r(`filter-pro/targets`,async()=>(await D(),v.list()),{authority:3}),r(`filter-pro/create`,async e=>{await E;let t=f(e||{});return s.rules.push(t),await i(),c(t)},{authority:3}),r(`filter-pro/update`,async e=>{if(await E,!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 E;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 E,!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 E,!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.filter=!1,exports.name=`filter-pro`,exports.reusable=!0;
package/lib/index.d.ts CHANGED
@@ -3,6 +3,8 @@ import { DataService } from "@koishijs/plugin-console";
3
3
 
4
4
  //#region src/index.d.ts
5
5
  declare const name = "filter-pro";
6
+ declare const reusable = true;
7
+ declare const filter = false;
6
8
  type RuleAction = 'bypass' | 'block';
7
9
  type GroupOperator = 'and' | 'or';
8
10
  type CompareOperator = 'eq' | 'ne' | 'includes' | 'regex' | 'gt' | 'gte' | 'lt' | 'lte' | 'exists';
@@ -87,4 +89,4 @@ declare class FilterProProvider extends DataService<RuleItem[]> {
87
89
  }
88
90
  declare function apply(ctx: Context, config?: Config): void;
89
91
  //#endregion
90
- export { CompareExpr, CompareOperator, Config, GroupExpr, GroupOperator, NotExpr, RuleAction, RuleExpr, RuleItem, RuleTarget, TargetType, apply, name };
92
+ export { CompareExpr, CompareOperator, Config, GroupExpr, GroupOperator, NotExpr, RuleAction, RuleExpr, RuleItem, RuleTarget, TargetType, apply, filter, name, reusable };
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=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&&e===`native-filter:evaluate`&&t?.matched&&l.info(`[trace:%s] %s`,e,JSON.stringify(t))},m=x(e,f),g=new Map,y=new Map,S=(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}),C=(e,t)=>{let n=S(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},w=(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=[]}),T=async()=>{await w,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`})},k=async()=>{await T();for(let[e,t]of y.entries()){if(e?.filter!==t)continue;let n=g.get(e);n&&(e.filter=n)}y.clear();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}let a=t=>i(t)?C(e,t):!1;t.filter=a,y.set(t,a)}f(`native-filter:sync:done`,{activeTargetCount:n.size})};T(),k(),e.on(`ready`,k),e.on(`internal/fork`,k),e.on(`internal/before-update`,k),e.on(`internal/update`,k),e.on(`internal/runtime`,k),e.on(`dispose`,()=>{for(let[e,t]of y.entries()){if(e?.filter!==t)continue;let n=g.get(e);n&&(e.filter=n)}y.clear()}),e.on(`command-added`,e=>{m.bindCommand(e),f(`command:added`,{command:String(e?.name??``)})}),e.middleware(async(e,t)=>{await w;let n=S(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 w;let t=m.resolveByCommand(e.command),n=S(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 k(),t.refresh()};n(`filter-pro/list`,async()=>(await w,t.get()),{authority:3}),n(`filter-pro/targets`,async()=>(await T(),m.list()),{authority:3}),n(`filter-pro/create`,async e=>{await w;let t=_(e||{});return s.rules.push(t),await r(),p(t)},{authority:3}),n(`filter-pro/update`,async e=>{if(await w,!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 w;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 w,!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 w,!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};
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=!0,u=!1,d=t.object({filename:t.string().default(`rules.json`).description(`持久化文件名(位于 data/filterpro/ 下)。`),debug:t.boolean().default(!1).description(`输出规则匹配调试日志。`)}),f=Symbol.for(`koishi.loader.record`);var p=class extends n{constructor(e,t){super(e,`filter-pro`),this.state=t}async get(){return _(this.state.rules).map(h)}};function m(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}function h(e){return{id:e.id,name:e.name,enabled:e.enabled,priority:e.priority,action:e.action,target:{...e.target},condition:g(e.condition),response:e.response}}function g(e){return e.type===`group`?{type:`group`,operator:e.operator,children:e.children.map(g)}:e.type===`not`?{type:`not`,child:g(e.child)}:{type:`compare`,field:e.field,operator:e.operator,value:e.value}}function _(e){return[...e].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))}function v(e){if(!e||typeof e!=`object`)return m();let t=e;if(t.type===`group`)return{type:`group`,operator:t.operator===`or`?`or`:`and`,children:Array.isArray(t.children)?t.children.map(v):[]};if(t.type===`not`)return{type:`not`,child:v(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 y(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:v(t.condition),response:t.response??``}}function b(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 x(e){let t=[],n=new Set,r=new Set,i=e=>{let a=e?.scope?.[f];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);r?.runtime?.plugin?.filter!==!1&&(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 S(e){let t=new Map,n=new Set,r=e=>{let i=e?.scope?.[f];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 C(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=x(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?.[f];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 w(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 T(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 E(e){return e==null||typeof e==`object`?e:String(e)}function D(e,t){if(t.operator===`exists`)return e!=null;let n=t.value,r=E(e),i=E(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=>E(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=T(e),o=T(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 O(e,t){return e.type===`group`?e.children.length?e.operator===`and`?e.children.every(e=>O(e,t)):e.children.some(e=>O(e,t)):!0:e.type===`not`?!O(e.child,t):D(w(t,e.field),e)}async function k(e){try{let t=await o(e,`utf8`),n=JSON.parse(t);return Array.isArray(n)?n.map(e=>y(e)):[]}catch{return null}}function A(e){let t=Promise.resolve();return async n=>{t=t.catch(()=>{}).then(async()=>{await s(e,JSON.stringify(n.map(h),null,2),`utf8`)}),await t}}function j(e,t={}){let n=r(e.baseDir||process.cwd(),`data`,`filterpro`),o=r(n,t.filename||`rules.json`),s={rules:[]},c=A(o),l=e.logger(`filter-pro`),u=!!t.debug,d=(e,t)=>{u&&e===`native-filter:evaluate`&&t?.matched&&l.info(`[trace:%s] %s`,e,JSON.stringify(t))},f=C(e,d),m=new Map,g=new Map,v=(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}),x=(e,t)=>{let n=v(t,{pluginKey:e});for(let t of _(s.rules)){if(!t.enabled||t.target.type!==`plugin`||(t.target.value||``).trim()!==e)continue;let r=O(t.condition,n);if(d(`native-filter:evaluate`,{pluginKey:e,ruleId:t.id,ruleName:t.name,action:t.action,matched:r}),r)return t.action===`bypass`}return!0},w=(async()=>{await a(n,{recursive:!0});let e=await k(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=[]}),T=async()=>{await w,f.rebuild();let t=e?.$commander?._commandList;if(Array.isArray(t)){d(`resolver:bind-existing:start`,{commandCount:t.length});for(let e of t)f.bindCommand(e);d(`resolver:bind-existing:done`,{commandCount:t.length})}else d(`resolver:bind-existing:skip`,{reason:`$commander not available`})},E=async()=>{await T();for(let[e,t]of g.entries()){if(e?.filter!==t)continue;let n=m.get(e);n&&(e.filter=n)}g.clear();let t=S(e),n=new Set(s.rules.filter(e=>e.enabled&&e.target.type===`plugin`&&!!e.target.value).map(e=>(e.target.value||``).trim()));d(`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;m.has(t),m.set(t,t.filter);let i=m.get(t);if(!n.has(e)){t.filter=i;continue}let a=t=>i(t)?x(e,t):!1;t.filter=a,g.set(t,a)}d(`native-filter:sync:done`,{activeTargetCount:n.size})};T(),E(),e.on(`ready`,E),e.on(`internal/fork`,E),e.on(`internal/before-update`,E),e.on(`internal/update`,E),e.on(`internal/runtime`,E),e.on(`dispose`,()=>{for(let[e,t]of g.entries()){if(e?.filter!==t)continue;let n=m.get(e);n&&(e.filter=n)}g.clear()}),e.on(`command-added`,e=>{f.bindCommand(e),d(`command:added`,{command:String(e?.name??``)})}),e.middleware(async(e,t)=>{await w;let n=v(e);d(`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 _(s.rules)){if(!e.enabled||e.target.type!==`global`)continue;if(!b(e.target,n)){d(`message:skip-target`,{ruleId:e.id,ruleName:e.name,target:e.target,pluginKey:n.pluginKey});continue}let r=O(e.condition,n);if(d(`message:evaluate`,{ruleId:e.id,ruleName:e.name,action:e.action,matched:r,expr:e.condition}),r)return e.action===`bypass`?(d(`message:action`,{ruleId:e.id,action:`bypass`}),t()):e.response?(d(`message:action`,{ruleId:e.id,action:`block`,response:e.response}),e.response):(d(`message:action`,{ruleId:e.id,action:`block`,response:``}),``)}return d(`message:pass`,{reason:`no-rule-matched`}),t()},!0),e.before(`command/execute`,async e=>{await w;let t=f.resolveByCommand(e.command),n=v(e.session,{commandName:String(e.command.name??``),pluginKey:t?.key,pluginName:t?.name});d(`command:incoming`,{command:n.commandName,pluginKey:n.pluginKey,pluginName:n.pluginName,isDirect:n.isDirect,guildId:n.guildId,content:n.content,ruleCount:s.rules.length}),d(`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 p(e,s),n=e.console.addListener.bind(e.console),r=async()=>{await c(s.rules),await E(),t.refresh()};n(`filter-pro/list`,async()=>(await w,t.get()),{authority:3}),n(`filter-pro/targets`,async()=>(await T(),f.list()),{authority:3}),n(`filter-pro/create`,async e=>{await w;let t=y(e||{});return s.rules.push(t),await r(),h(t)},{authority:3}),n(`filter-pro/update`,async e=>{if(await w,!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]=y({...n,...e,id:n.id}),await r(),h(s.rules[t])},{authority:3}),n(`filter-pro/delete`,async e=>{await w;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 w,!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 w,!e?.id)return null;let t=s.rules.find(t=>t.id===e.id);return t?(t.enabled=!!e.enabled,await r(),h(t)):null},{authority:3})})}export{d as Config,j as apply,u as filter,c as name,l as reusable};
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.13",
4
+ "version": "1.0.14",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "lib/index.mjs",
7
7
  "types": "lib/index.d.ts",