koishi-plugin-filter-pro 1.0.16 → 1.0.17

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,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,withModifiers as E}from"vue";const D=[`disabled`],O={class:`label`},k=[`onClick`];var A=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 E(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`,E),window.addEventListener(`resize`,j),window.addEventListener(`scroll`,j,!0)}),h(()=>{document.removeEventListener(`click`,E),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`,O,x(S.value||e.placeholder),1),n[0]||=l(`span`,{class:`arrow`},`▾`,-1)],10,D)],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,k))),128))],4)):s(`v-if`,!0)]))],64))}}),j=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},M=j(A,[[`__scopeId`,`data-v-4a262c3e`]]);const N={class:`cf-editor`},P={class:`rows-section`},F={key:0,class:`conn-and-wrap`},I={class:`cf-row`},L=[`onUpdate:modelValue`],R={key:1,class:`bool-toggle`},z=[`checked`,`onChange`],B={class:`bool-label`},V=[`onUpdate:modelValue`,`onInput`],H={class:`row-btns`},U=[`disabled`,`onClick`],ee={key:0,class:`add-section`},te={class:`preview-section`},ne={class:`preview-code`};var W=j(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(G(D.modelValue)),A=JSON.stringify(D.modelValue);C(()=>D.modelValue,e=>{let t=JSON.stringify(e);t!==A&&(A=t,k.value=G(e))},{deep:!0});function j(e,t=`guildId`){let n=t===`isDirect`;return{id:i(),field:t,customField:``,operator:`eq`,valueText:n?`false`:``,value:n?!1:``,connector:e}}function W(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 G(e){if(!e)return[j(null)];if(e.type===`compare`)return[W(e,null)];if(e.type===`group`){if(e.children.every(e=>e.type===`compare`))return e.children.map((t,n)=>W(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(W(r,n?null:`or`)),n=!1):r.type===`group`&&r.operator===`and`&&r.children.forEach((e,r)=>{e.type===`compare`&&(t.push(W(e,n?null:r===0?`or`:`and`)),n=!1)});if(t.length>0)return t}}return[j(null)]}function K(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 q(e){if(e.length===0)return{type:`compare`,field:`guildId`,operator:`eq`,value:``};if(e.length===1)return K(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?K(e[0]):{type:`group`,operator:`and`,children:e.map(K)});return r.length===1?r[0]:{type:`group`,operator:`or`,children:r}}function J(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(J).join(t)}return e.type===`not`?`NOT (${J(e.child)})`:``}let Y=a(()=>J(q(k.value)));function X(){let e=q(k.value);A=JSON.stringify(e),O(`update:modelValue`,e)}function Z(e){k.value.push(j(e??`and`)),X()}function Q(e,t){k.value.splice(e+1,0,j(t)),X()}function re(e){k.value.length<=1||(k.value.splice(e,1),e===0&&(k.value[0].connector=null),X())}function $(e){e<=0||(k.value[e].connector=k.value[e].connector===`or`?`and`:`or`,X())}function ie(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`,N,[s(` 条件行 `),l(`div`,P,[(_(!0),c(r,null,y(k.value,(e,i)=>(_(),c(r,{key:e.id},[s(` 连接符(第一行之后显示) `),i>0?(_(),c(`div`,{key:0,class:p([`connector-sep`,`conn-`+e.connector])},[s(` AND:细线 + 按钮 + 细线 `),e.connector===`and`?(_(),c(`div`,F,[t[2]||=l(`div`,{class:`conn-vline`},null,-1),d(n,{title:`点击切换为或(OR)`,onClick:e=>$(i)},{default:w(()=>[...t[1]||=[u(`且(AND)`,-1)]]),_:1},8,[`onClick`]),t[3]||=l(`div`,{class:`conn-vline`},null,-1)])):(_(),c(r,{key:1},[s(` OR:仅按钮 `),d(n,{title:`点击切换为且(AND)`,onClick:e=>$(i)},{default:w(()=>[...t[4]||=[u(`或(OR)`,-1)]]),_:1},8,[`onClick`])],2112))],2)):s(`v-if`,!0),s(` 条件行 `),l(`div`,I,[d(M,{"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=``),X()}},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:X,placeholder:`字段路径,如 author.name`},null,40,L)),[[S,e.customField]]):s(`v-if`,!0),d(M,{"model-value":e.operator,options:e.field===`isDirect`?g:h,class:`sel-op`,"onUpdate:modelValue":t=>{e.operator=t,X()}},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),X()}},null,40,z),l(`span`,B,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=ie(e.valueText),X()},placeholder:`比较值`},null,40,V),[[S,e.valueText]])],2112)):s(`v-if`,!0),l(`div`,H,[d(n,{onClick:e=>Q(i,`and`)},{default:w(()=>[...t[5]||=[u(`且(AND)`,-1)]]),_:1},8,[`onClick`]),i===k.value.length-1?(_(),o(n,{key:0,onClick:e=>Q(i,`or`)},{default:w(()=>[...t[6]||=[u(`或(OR)`,-1)]]),_:1},8,[`onClick`])):s(`v-if`,!0)]),l(`button`,{class:`del-btn`,disabled:k.value.length<=1,onClick:e=>re(i),title:`删除此条件`},` ✕ `,8,U)])],64))),128))]),s(` 添加条件(仅空状态) `),k.value.length===0?(_(),c(`div`,ee,[d(n,{onClick:t[0]||=e=>Z(null)},{default:w(()=>[...t[7]||=[u(`+ 添加条件`,-1)]]),_:1})])):s(`v-if`,!0),s(` 表达式预览 `),l(`div`,te,[t[8]||=l(`div`,{class:`preview-title`},`表达式预览`,-1),l(`code`,ne,x(Y.value||`(空)`),1)])])}}}),[[`__scopeId`,`data-v-40533e84`]]);const G={class:`fp-layout`},K={class:`fp-main`},q={class:`editor-header`},J={class:`rule-list`},Y=[`onClick`],X={class:`top`},Z={class:`name`},Q={class:`meta`},re={class:`editor-header`},$={class:`actions`},ie={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`},me={class:`confirm-dialog`},he={class:`confirm-actions`};var ge=j(f({__name:`page`,setup(e){let f=n,m={bypass:`放行`,block:`拦截`},h=[{label:`全局`,value:`global`},{label:`插件`,value:`plugin`}],g=[{label:`放行(bypass)`,value:`bypass`},{label:`拦截(block)`,value:`block`}],C=a(()=>[{label:`请选择插件实例`,value:``},...O.value.map(e=>({label:e.label,value:e.key}))]),D=v([]),O=v([]),k=v(``),A=a(()=>[...D.value].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))),j=a(()=>A.value.find(e=>e.id===k.value));function N(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}async function P(){let[e,n]=await Promise.all([f(`filter-pro/list`),f(`filter-pro/targets`)]);O.value=n,D.value=e,(!k.value||!D.value.some(e=>e.id===k.value))&&(k.value=A.value[0]?.id||``),t.success(`刷新成功`)}async function F(){await f(`filter-pro/create`,{name:`new-rule`,enabled:!0,priority:(A.value.at(-1)?.priority??-1)+1,action:`block`,target:{type:`global`,value:``},condition:N(),response:``}),await P(),k.value=A.value.at(-1)?.id||k.value,t.success(`创建成功`)}function I(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)),j.value&&(j.value.priority=Number(t.value)))}async function L(e){e.enabled=!e.enabled,await f(`filter-pro/toggle`,{id:e.id,enabled:e.enabled})}async function R(e){let n=e.target.type===`global`?{type:`global`,value:``}:{type:`plugin`,value:e.target.value||``};await f(`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 P(),t.success(`保存成功`)}let z=v(!1);async function B(){j.value&&(z.value=!0)}async function V(){z.value=!1,j.value&&await H(j.value.id)}async function H(e){await f(`filter-pro/delete`,e),await P(),t.success(`删除成功`)}async function U(e,t){let n=A.value,r=n.findIndex(t=>t.id===e);if(r<0)return;let i=r+t;if(i<0||i>=n.length)return;let a=[...n];[a[r],a[i]]=[a[i],a[r]],await f(`filter-pro/reorder`,a.map(e=>e.id)),await P()}return P(),(e,t)=>{let n=b(`k-button`),a=b(`k-card`),f=b(`k-layout`);return _(),c(r,null,[d(f,null,{default:w(()=>[l(`div`,G,[l(`div`,K,[d(a,{class:`panel list`},{header:w(()=>[l(`div`,q,[t[13]||=l(`div`,{class:`panel-title`},`规则列表`,-1),d(n,{onClick:F},{default:w(()=>[...t[12]||=[u(`新建规则`,-1)]]),_:1})])]),default:w(()=>[l(`div`,J,[(_(!0),c(r,null,y(A.value,e=>(_(),c(`button`,{key:e.id,class:p([`rule-item`,{active:k.value===e.id}]),onClick:t=>k.value=e.id},[l(`div`,X,[l(`span`,Z,x(e.name||`未命名规则`),1),l(`span`,{class:p([`badge`,e.action])},x(m[e.action]),3)]),l(`div`,Q,[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,Y))),128))])]),_:1}),j.value?(_(),o(a,{key:0,class:`panel editor`},{header:w(()=>[l(`div`,re,[t[17]||=l(`div`,{class:`panel-title`},`规则编辑`,-1),l(`div`,$,[d(n,{onClick:t[0]||=e=>j.value&&R(j.value),disabled:!j.value},{default:w(()=>[...t[14]||=[u(`保存`,-1)]]),_:1},8,[`disabled`]),d(n,{onClick:B,disabled:!j.value},{default:w(()=>[...t[15]||=[u(`删除`,-1)]]),_:1},8,[`disabled`]),d(n,{onClick:P},{default:w(()=>[...t[16]||=[u(`刷新`,-1)]]),_:1})])])]),default:w(()=>[l(`div`,ie,[l(`div`,ae,[l(`label`,oe,[t[18]||=l(`span`,null,`规则名`,-1),T(l(`input`,{class:`input`,"onUpdate:modelValue":t[1]||=e=>j.value.name=e,placeholder:`输入规则名`},null,512),[[S,j.value.name]])]),l(`label`,se,[t[19]||=l(`span`,null,`目标`,-1),d(M,{modelValue:j.value.target.type,"onUpdate:modelValue":t[2]||=e=>j.value.target.type=e,options:h},null,8,[`modelValue`])]),j.value.target.type===`plugin`?(_(),c(`label`,ce,[t[20]||=l(`span`,null,`插件实例`,-1),d(M,{"model-value":j.value.target.value??``,options:C.value,"onUpdate:modelValue":t[3]||=e=>j.value.target.value=e},null,8,[`model-value`,`options`])])):s(`v-if`,!0),l(`label`,le,[t[21]||=l(`span`,null,`动作`,-1),d(M,{modelValue:j.value.action,"onUpdate:modelValue":t[4]||=e=>j.value.action=e,options:g},null,8,[`modelValue`])]),l(`label`,ue,[t[22]||=l(`span`,null,`优先级`,-1),T(l(`input`,{class:`input`,type:`number`,min:`1`,step:`1`,"onUpdate:modelValue":t[5]||=e=>j.value.priority=e,onInput:I},null,544),[[S,j.value.priority,void 0,{number:!0}]])]),l(`label`,de,[t[24]||=l(`span`,null,`启用状态`,-1),l(`div`,{class:p([`toggle-switch`,{active:j.value.enabled}]),onClick:t[6]||=e=>L(j.value)},[...t[23]||=[l(`div`,{class:`toggle-thumb`},null,-1)]],2)])]),l(`div`,fe,[t[25]||=l(`div`,{class:`panel-title small`},`条件表达式`,-1),d(W,{modelValue:j.value.condition,"onUpdate:modelValue":t[7]||=e=>j.value.condition=e},null,8,[`modelValue`])]),l(`div`,pe,[d(n,{onClick:t[8]||=e=>U(j.value.id,-1)},{default:w(()=>[...t[26]||=[u(`上移`,-1)]]),_:1}),d(n,{onClick:t[9]||=e=>U(j.value.id,1)},{default:w(()=>[...t[27]||=[u(`下移`,-1)]]),_:1})])])]),_:1})):s(`v-if`,!0)])])]),_:1}),s(` 删除确认弹窗 `),(_(),o(i,{to:`body`},[z.value?(_(),c(`div`,{key:0,class:`confirm-overlay`,onClick:t[11]||=E(e=>z.value=!1,[`self`])},[l(`div`,me,[t[29]||=l(`div`,{class:`confirm-title`},`删除规则`,-1),t[30]||=l(`div`,{class:`confirm-body`},`确定要删除这条规则吗?此操作不可撤销。`,-1),l(`div`,he,[d(n,{onClick:t[10]||=e=>z.value=!1},{default:w(()=>[...t[28]||=[u(`取消`,-1)]]),_:1}),l(`button`,{class:`confirm-danger-btn`,onClick:V},`确认删除`)])])])):s(`v-if`,!0)]))],64)}}}),[[`__scopeId`,`data-v-0e916acc`]]);const _e={},ve={class:`k-icon`,viewBox:`0 0 512 512`,xmlns:`http://www.w3.org/2000/svg`};function ye(e,t){return _(),c(`svg`,ve,[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 be=j(_e,[[`render`,ye]]),xe=t=>{e.register(`activity:filter-pro`,be),t.page({name:`规则集`,path:`/filter-pro`,icon:`activity:filter-pro`,order:320,component:ge})};export{xe 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,withKeys as E,withModifiers as D}from"vue";const O=[`disabled`],k={class:`label`},A=[`onClick`];var j=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&&D())}function T(e){u(`update:modelValue`,e),f.value=!1}function E(e){let t=e.target;!d.value||!t||d.value.contains(t)||(f.value=!1)}function D(){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&&D()}return C(f,e=>{e&&D()}),g(()=>{document.addEventListener(`click`,E),window.addEventListener(`resize`,j),window.addEventListener(`scroll`,j,!0)}),h(()=>{document.removeEventListener(`click`,E),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`,k,x(S.value||e.placeholder),1),n[0]||=l(`span`,{class:`arrow`},`▾`,-1)],10,O)],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,A))),128))],4)):s(`v-if`,!0)]))],64))}}),M=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},N=M(j,[[`__scopeId`,`data-v-4a262c3e`]]);const P={class:`chip-text`},F=[`onClick`],I=[`placeholder`,`onKeydown`];var L=M(f({name:`TagInput`,__name:`tag-input`,props:{modelValue:{type:Array,required:!0},placeholder:{type:String,required:!1}},emits:[`update:modelValue`],setup(e,{emit:t}){let n=e,i=t,a=v(null),o=v(``),u=v(!1);function d(){a.value?.focus()}function f(){let e=o.value.trim();e&&(n.modelValue.includes(e)||i(`update:modelValue`,[...n.modelValue,e]),o.value=``)}function m(e){let t=[...n.modelValue];t.splice(e,1),i(`update:modelValue`,t)}function h(){i(`update:modelValue`,[]),o.value=``}function g(){o.value===``&&n.modelValue.length>0&&m(n.modelValue.length-1)}function b(){let e=o.value.trim();e&&!n.modelValue.includes(e)&&i(`update:modelValue`,[...n.modelValue,e]),o.value=``,u.value=!1}return(t,n)=>(_(),c(`div`,{class:p([`tag-input-wrap`,{"is-focused":u.value}]),onClick:d},[(_(!0),c(r,null,y(e.modelValue,(e,t)=>(_(),c(`span`,{key:t,class:`tag-chip`},[l(`span`,P,x(e),1),l(`button`,{class:`chip-del`,onClick:D(e=>m(t),[`stop`]),tabindex:`-1`,title:`移除`},`×`,8,F)]))),128)),T(l(`input`,{ref_key:`inputEl`,ref:a,class:`tag-text-input`,"onUpdate:modelValue":n[0]||=e=>o.value=e,placeholder:e.modelValue.length===0?e.placeholder??``:``,onKeydown:[E(D(f,[`prevent`]),[`enter`]),E(g,[`backspace`])],onFocus:n[1]||=e=>u.value=!0,onBlur:b},null,40,I),[[S,o.value]]),e.modelValue.length>0?(_(),c(`button`,{key:0,class:`tag-clear-btn`,onClick:D(h,[`stop`]),tabindex:`-1`,title:`清空`},`×`)):s(`v-if`,!0)],2))}}),[[`__scopeId`,`data-v-8e9ea736`]]);const R={class:`cf-editor`},z={class:`rows-section`},B={key:0,class:`conn-and-wrap`},V={class:`cf-row`},H=[`onUpdate:modelValue`],U={key:1,class:`bool-toggle`},W=[`checked`,`onChange`],G={class:`bool-label`},ee=[`onUpdate:modelValue`,`onInput`,`placeholder`],te={class:`row-btns`},ne=[`disabled`,`onClick`],re={key:0,class:`add-section`},ie={class:`preview-section`},ae={class:`preview-code`};var K=M(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:`in`,label:`等于以下各项`},{value:`nin`,label:`不等于以下各项`},{value:`includes`,label:`包含以下各项`},{value:`notincludes`,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`,in:`in`,nin:`nin`,includes:`contains`,notincludes:`not-contains`,regex:`matches`,gt:`gt`,gte:`gte`,lt:`lt`,lte:`lte`,exists:`exists`},D=e,O=t,k=v(P(D.modelValue)),A=JSON.stringify(D.modelValue);C(()=>D.modelValue,e=>{let t=JSON.stringify(e);t!==A&&(A=t,k.value=P(e))},{deep:!0});function j(e,t=`guildId`){let n=t===`isDirect`;return{id:i(),field:t,customField:``,operator:`eq`,valueText:n?`false`:``,value:n?!1:``,connector:e}}function M(e,t){let n=f.some(t=>t.value===e.field),r=n?e.field:`__custom__`,a=Q(e.operator),o=r===`isDirect`?!1:a?[]:``,s=e.value??o;return a&&(typeof s==`string`?s=s?s.split(/[,,]/).map(e=>e.trim()).filter(Boolean):[]:Array.isArray(s)||(s=[])),{id:i(),field:r,customField:n?``:e.field,operator:e.operator,valueText:Array.isArray(s)||s==null?``:String(s),value:s,connector:t}}function P(e){if(!e)return[j(null)];if(e.type===`compare`)return[M(e,null)];if(e.type===`group`){if(e.children.every(e=>e.type===`compare`))return e.children.map((t,n)=>M(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(M(r,n?null:`or`)),n=!1):r.type===`group`&&r.operator===`and`&&r.children.forEach((e,r)=>{e.type===`compare`&&(t.push(M(e,n?null:r===0?`or`:`and`)),n=!1)});if(t.length>0)return t}}return[j(null)]}function F(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 I(e){if(e.length===0)return{type:`compare`,field:`guildId`,operator:`eq`,value:``};if(e.length===1)return F(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?F(e[0]):{type:`group`,operator:`and`,children:e.map(F)});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;return n=e.value===void 0?``:Array.isArray(e.value)?`{${e.value.map(e=>JSON.stringify(e)).join(` `)}}`:JSON.stringify(e.value),`(${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(I(k.value)));function J(){let e=I(k.value);A=JSON.stringify(e),O(`update:modelValue`,e)}function Y(e){k.value.push(j(e??`and`)),J()}function X(e,t){k.value.splice(e+1,0,j(t)),J()}function oe(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 se(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}function Q(e){return[`in`,`nin`,`includes`,`notincludes`].includes(e)}function $(e){return Q(e)?`输入后按 Enter 添加`:`比较值`}return(e,t)=>{let n=b(`k-button`);return _(),c(`div`,R,[s(` 条件行 `),l(`div`,z,[(_(!0),c(r,null,y(k.value,(e,i)=>(_(),c(r,{key:e.id},[s(` 连接符(第一行之后显示) `),i>0?(_(),c(`div`,{key:0,class:p([`connector-sep`,`conn-`+e.connector])},[s(` AND:细线 + 按钮 + 细线 `),e.connector===`and`?(_(),c(`div`,B,[t[2]||=l(`div`,{class:`conn-vline`},null,-1),d(n,{title:`点击切换为或(OR)`,onClick:e=>Z(i)},{default:w(()=>[...t[1]||=[u(`且(AND)`,-1)]]),_:1},8,[`onClick`]),t[3]||=l(`div`,{class:`conn-vline`},null,-1)])):(_(),c(r,{key:1},[s(` OR:仅按钮 `),d(n,{title:`点击切换为且(AND)`,onClick:e=>Z(i)},{default:w(()=>[...t[4]||=[u(`或(OR)`,-1)]]),_:1},8,[`onClick`])],2112))],2)):s(`v-if`,!0),s(` 条件行 `),l(`div`,V,[d(N,{"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=Q(e.operator)?[]:``,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,H)),[[S,e.customField]]):s(`v-if`,!0),d(N,{"model-value":e.operator,options:e.field===`isDirect`?g:h,class:`sel-op`,"onUpdate:modelValue":t=>{let n=Q(e.operator),r=Q(t);e.operator=t,r&&!n?(e.value=[],e.valueText=``):!r&&n&&(e.value=``,e.valueText=``),J()}},null,8,[`model-value`,`options`,`onUpdate:modelValue`]),s(` isDirect:开关 `),e.field===`isDirect`&&e.operator!==`exists`?(_(),c(`label`,U,[l(`input`,{type:`checkbox`,checked:e.value===!0,onChange:t=>{e.value=t.target.checked,e.valueText=String(e.value),J()}},null,40,W),l(`span`,G,x(e.value===!0?`是(true)`:`否(false)`),1)])):e.field!==`isDirect`&&e.operator!==`exists`&&Q(e.operator)?(_(),c(r,{key:2},[s(` 数组操作符:Tag 输入 `),d(L,{"model-value":Array.isArray(e.value)?e.value:[],placeholder:$(e.operator),"onUpdate:modelValue":t=>{e.value=t,J()}},null,8,[`model-value`,`placeholder`,`onUpdate:modelValue`])],2112)):e.field!==`isDirect`&&e.operator!==`exists`?(_(),c(r,{key:3},[s(` 普通文本输入 `),T(l(`input`,{class:`input val-input`,"onUpdate:modelValue":t=>e.valueText=t,onInput:()=>{e.value=se(e.valueText),J()},placeholder:$(e.operator)},null,40,ee),[[S,e.valueText]])],2112)):s(`v-if`,!0),l(`div`,te,[d(n,{onClick:e=>X(i,`and`)},{default:w(()=>[...t[5]||=[u(`且(AND)`,-1)]]),_:1},8,[`onClick`]),i===k.value.length-1?(_(),o(n,{key:0,onClick:e=>X(i,`or`)},{default:w(()=>[...t[6]||=[u(`或(OR)`,-1)]]),_:1},8,[`onClick`])):s(`v-if`,!0)]),l(`button`,{class:`del-btn`,disabled:k.value.length<=1,onClick:e=>oe(i),title:`删除此条件`},` ✕ `,8,ne)])],64))),128))]),s(` 添加条件(仅空状态) `),k.value.length===0?(_(),c(`div`,re,[d(n,{onClick:t[0]||=e=>Y(null)},{default:w(()=>[...t[7]||=[u(`+ 添加条件`,-1)]]),_:1})])):s(`v-if`,!0),s(` 表达式预览 `),l(`div`,ie,[t[8]||=l(`div`,{class:`preview-title`},`表达式预览`,-1),l(`code`,ae,x(q.value||`(空)`),1)])])}}}),[[`__scopeId`,`data-v-40533e84`]]);const q={class:`plugin-selector`},J={class:`label`},Y={class:`dialog-header`},X={class:`dialog-body`},oe={class:`toolbar`},Z={class:`checkbox-item select-all`},se=[`checked`],Q=[`placeholder`],$={class:`plugin-list`},ce=[`value`,`checked`,`onChange`],le={key:0,class:`empty-state`};var ue=M(f({__name:`plugin-selector`,props:{modelValue:{type:Array,required:!0},options:{type:Array,required:!0},mode:{type:String,required:!1}},emits:[`update:modelValue`],setup(e,{emit:t}){let n=e,u=t,d=v(!1),f=v(``),p=v([...n.modelValue]),m=a(()=>n.mode===`command`),h=a(()=>m.value?`选择指令`:`选择插件实例`),g=a(()=>m.value?`搜索指令...`:`搜索插件...`),b=a(()=>m.value?`没有找到匹配的指令`:`没有找到匹配的插件`),w=a(()=>{let e=m.value?`指令`:`插件`,t=m.value?`请选择指令`:`请选择插件实例`;return p.value.length===0?t:p.value.length===1?n.options.find(e=>e.key===p.value[0])?.label||`已选择 1 个${e}`:`已选择 ${p.value.length} 个${e}`}),E=a(()=>{if(!f.value)return n.options;let e=f.value.toLowerCase();return n.options.filter(t=>t.label.toLowerCase().includes(e))}),O=a(()=>E.value.length>0&&E.value.every(e=>p.value.includes(e.key)));function k(e){let t=p.value.indexOf(e);t>-1?p.value.splice(t,1):p.value.push(e)}function A(e){if(e.target.checked)for(let e of E.value)p.value.includes(e.key)||p.value.push(e.key);else p.value=p.value.filter(e=>!E.value.some(t=>t.key===e))}function j(){u(`update:modelValue`,[...p.value]),d.value=!1}function M(){p.value=[...n.modelValue],d.value=!1}return C(()=>n.modelValue,e=>{p.value=[...e]}),C(d,e=>{e&&(f.value=``)}),(e,t)=>(_(),c(`div`,q,[s(` 触发按钮 `),l(`button`,{type:`button`,class:`trigger-btn`,onClick:t[0]||=e=>d.value=!0},[l(`span`,J,x(w.value),1),t[5]||=l(`span`,{class:`arrow`},`▾`,-1)]),s(` 多选对话框 `),(_(),o(i,{to:`body`},[d.value?(_(),c(`div`,{key:0,class:`dialog-overlay`,onClick:t[4]||=e=>d.value=!1},[l(`div`,{class:`dialog-content`,onClick:t[3]||=D(()=>{},[`stop`])},[l(`div`,Y,[l(`h3`,null,x(h.value),1),l(`button`,{class:`close-btn`,onClick:t[1]||=e=>d.value=!1},`✕`)]),l(`div`,X,[s(` 搜索和全选 `),l(`div`,oe,[l(`label`,Z,[l(`input`,{type:`checkbox`,checked:O.value,onChange:A},null,40,se),t[6]||=l(`span`,null,`全选`,-1)]),T(l(`input`,{"onUpdate:modelValue":t[2]||=e=>f.value=e,class:`search-input`,placeholder:g.value},null,8,Q),[[S,f.value]])]),s(` 插件/指令列表 `),l(`div`,$,[(_(!0),c(r,null,y(E.value,e=>(_(),c(`label`,{key:e.key,class:`checkbox-item`},[l(`input`,{type:`checkbox`,value:e.key,checked:p.value.includes(e.key),onChange:t=>k(e.key)},null,40,ce),l(`span`,null,x(e.label),1)]))),128)),E.value.length===0?(_(),c(`div`,le,x(b.value),1)):s(`v-if`,!0)])]),l(`div`,{class:`dialog-footer`},[l(`button`,{class:`btn btn-cancel`,onClick:M},`取消`),l(`button`,{class:`btn btn-confirm`,onClick:j},`确定`)])])])):s(`v-if`,!0)]))]))}}),[[`__scopeId`,`data-v-6b39c823`]]);const de={class:`fp-layout`},fe={class:`fp-main`},pe={class:`editor-header`},me={class:`rule-list`},he=[`onClick`],ge={class:`top`},_e={class:`name`},ve={class:`meta`},ye={class:`editor-header`},be={class:`actions`},xe={class:`editor-body`},Se={class:`editor-grid`},Ce={class:`field`},we={class:`field`},Te={key:0,class:`field`},Ee={key:1,class:`field`},De={class:`field`},Oe={class:`field`},ke={class:`field switch`},Ae={class:`expr-wrap`},je={class:`footer-actions`},Me={class:`confirm-dialog`},Ne={class:`confirm-actions`};var Pe=M(f({__name:`page`,setup(e){let f=n,m={bypass:`放行`,block:`拦截`},h=[{label:`全局`,value:`global`},{label:`插件`,value:`plugin`},{label:`指令`,value:`command`}],g=[{label:`放行(bypass)`,value:`bypass`},{label:`拦截(block)`,value:`block`}];a(()=>[{label:`请选择插件实例`,value:``},...O.value.map(e=>({label:e.label,value:e.key}))]);let E=v([]),O=v([]),k=v([]),A=v(``),j=v(!1),M=a(()=>[...E.value].sort((e,t)=>e.priority-t.priority||e.id.localeCompare(t.id))),P=a(()=>M.value.find(e=>e.id===A.value));function F(e){return e.type===`global`?`全局`:e.type===`plugin`?Array.isArray(e.value)?e.value.length>0?`插件 (${e.value.length})`:`未指定插件`:e.value||`未指定插件`:e.type===`command`?Array.isArray(e.value)?e.value.length>0?`指令 (${e.value.length})`:`未指定指令`:e.value||`未指定指令`:`未知`}C(()=>P.value?.target.type,(e,t)=>{e&&t&&e!==t&&P.value&&(P.value.target.value=e===`global`?``:[])});function I(){return{type:`group`,operator:`and`,children:[{type:`compare`,field:`guildId`,operator:`eq`,value:``}]}}async function L(){let[e,n,r]=await Promise.all([f(`filter-pro/list`),f(`filter-pro/targets`),f(`filter-pro/commands`)]);O.value=n,k.value=r,E.value=e,(!A.value||!E.value.some(e=>e.id===A.value))&&(A.value=M.value[0]?.id||``),t.success(`刷新成功`)}async function R(){await f(`filter-pro/create`,{name:`new-rule`,enabled:!0,priority:(M.value.at(-1)?.priority??-1)+1,action:`block`,target:{type:`global`,value:``},condition:I(),response:``}),await L(),A.value=M.value.at(-1)?.id||A.value,t.success(`创建成功`)}function z(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)),P.value&&(P.value.priority=Number(t.value)))}async function B(e){e.enabled=!e.enabled,await f(`filter-pro/toggle`,{id:e.id,enabled:e.enabled})}async function V(e){let n;n=e.target.type===`global`?{type:`global`,value:``}:e.target.type===`plugin`?{type:`plugin`,value:e.target.value||[]}:{type:`command`,value:e.target.value||[]},await f(`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 L(),t.success(`保存成功`)}async function H(){P.value&&(j.value=!0)}async function U(){j.value=!1,P.value&&await W(P.value.id)}async function W(e){await f(`filter-pro/delete`,e),await L(),t.success(`删除成功`)}async function G(e,t){let n=M.value,r=n.findIndex(t=>t.id===e);if(r<0)return;let i=r+t;if(i<0||i>=n.length)return;let a=[...n];[a[r],a[i]]=[a[i],a[r]],await f(`filter-pro/reorder`,a.map(e=>e.id)),await L()}return L(),(e,t)=>{let n=b(`k-button`),a=b(`k-card`),f=b(`k-layout`);return _(),c(r,null,[d(f,null,{default:w(()=>[l(`div`,de,[l(`div`,fe,[d(a,{class:`panel list`},{header:w(()=>[l(`div`,pe,[t[14]||=l(`div`,{class:`panel-title`},`规则列表`,-1),d(n,{onClick:R},{default:w(()=>[...t[13]||=[u(`新建规则`,-1)]]),_:1})])]),default:w(()=>[l(`div`,me,[(_(!0),c(r,null,y(M.value,e=>(_(),c(`button`,{key:e.id,class:p([`rule-item`,{active:A.value===e.id}]),onClick:t=>A.value=e.id},[l(`div`,ge,[l(`span`,_e,x(e.name||`未命名规则`),1),l(`span`,{class:p([`badge`,e.action])},x(m[e.action]),3)]),l(`div`,ve,[l(`span`,null,`#`+x(e.priority),1),l(`span`,null,x(F(e.target)),1),l(`span`,null,x(e.enabled?`启用`:`停用`),1)])],10,he))),128))])]),_:1}),P.value?(_(),o(a,{key:0,class:`panel editor`},{header:w(()=>[l(`div`,ye,[t[18]||=l(`div`,{class:`panel-title`},`规则编辑`,-1),l(`div`,be,[d(n,{onClick:t[0]||=e=>P.value&&V(P.value),disabled:!P.value},{default:w(()=>[...t[15]||=[u(`保存`,-1)]]),_:1},8,[`disabled`]),d(n,{onClick:H,disabled:!P.value},{default:w(()=>[...t[16]||=[u(`删除`,-1)]]),_:1},8,[`disabled`]),d(n,{onClick:L},{default:w(()=>[...t[17]||=[u(`刷新`,-1)]]),_:1})])])]),default:w(()=>[l(`div`,xe,[l(`div`,Se,[l(`label`,Ce,[t[19]||=l(`span`,null,`规则名`,-1),T(l(`input`,{class:`input`,"onUpdate:modelValue":t[1]||=e=>P.value.name=e,placeholder:`输入规则名`},null,512),[[S,P.value.name]])]),l(`label`,we,[t[20]||=l(`span`,null,`目标`,-1),d(N,{modelValue:P.value.target.type,"onUpdate:modelValue":t[2]||=e=>P.value.target.type=e,options:h},null,8,[`modelValue`])]),s(` 插件多选 `),P.value.target.type===`plugin`?(_(),c(`label`,Te,[t[21]||=l(`span`,null,`插件实例`,-1),d(ue,{mode:`plugin`,"model-value":Array.isArray(P.value.target.value)?P.value.target.value:P.value.target.value?[P.value.target.value]:[],options:O.value,"onUpdate:modelValue":t[3]||=e=>P.value.target.value=e},null,8,[`model-value`,`options`])])):s(`v-if`,!0),s(` 指令多选 `),P.value.target.type===`command`?(_(),c(`label`,Ee,[t[22]||=l(`span`,null,`作用指令`,-1),d(ue,{mode:`command`,"model-value":Array.isArray(P.value.target.value)?P.value.target.value:P.value.target.value?[P.value.target.value]:[],options:k.value.map(e=>({key:e.name,name:e.name,ident:``,label:e.label})),"onUpdate:modelValue":t[4]||=e=>P.value.target.value=e},null,8,[`model-value`,`options`])])):s(`v-if`,!0),l(`label`,De,[t[23]||=l(`span`,null,`动作`,-1),d(N,{modelValue:P.value.action,"onUpdate:modelValue":t[5]||=e=>P.value.action=e,options:g},null,8,[`modelValue`])]),l(`label`,Oe,[t[24]||=l(`span`,null,`优先级`,-1),T(l(`input`,{class:`input`,type:`number`,min:`1`,step:`1`,"onUpdate:modelValue":t[6]||=e=>P.value.priority=e,onInput:z},null,544),[[S,P.value.priority,void 0,{number:!0}]])]),l(`label`,ke,[t[26]||=l(`span`,null,`启用状态`,-1),l(`div`,{class:p([`toggle-switch`,{active:P.value.enabled}]),onClick:t[7]||=e=>B(P.value)},[...t[25]||=[l(`div`,{class:`toggle-thumb`},null,-1)]],2)])]),l(`div`,Ae,[t[27]||=l(`div`,{class:`panel-title small`},`条件表达式`,-1),d(K,{modelValue:P.value.condition,"onUpdate:modelValue":t[8]||=e=>P.value.condition=e},null,8,[`modelValue`])]),l(`div`,je,[d(n,{onClick:t[9]||=e=>G(P.value.id,-1)},{default:w(()=>[...t[28]||=[u(`上移`,-1)]]),_:1}),d(n,{onClick:t[10]||=e=>G(P.value.id,1)},{default:w(()=>[...t[29]||=[u(`下移`,-1)]]),_:1})])])]),_:1})):s(`v-if`,!0)])])]),_:1}),s(` 删除确认弹窗 `),(_(),o(i,{to:`body`},[j.value?(_(),c(`div`,{key:0,class:`confirm-overlay`,onClick:t[12]||=D(e=>j.value=!1,[`self`])},[l(`div`,Me,[t[31]||=l(`div`,{class:`confirm-title`},`删除规则`,-1),t[32]||=l(`div`,{class:`confirm-body`},`确定要删除这条规则吗?此操作不可撤销。`,-1),l(`div`,Ne,[d(n,{onClick:t[11]||=e=>j.value=!1},{default:w(()=>[...t[30]||=[u(`取消`,-1)]]),_:1}),l(`button`,{class:`confirm-danger-btn`,onClick:U},`确认删除`)])])])):s(`v-if`,!0)]))],64)}}}),[[`__scopeId`,`data-v-0e916acc`]]);const Fe={},Ie={class:`k-icon`,viewBox:`0 0 512 512`,xmlns:`http://www.w3.org/2000/svg`};function Le(e,t){return _(),c(`svg`,Ie,[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 Re=M(Fe,[[`render`,Le]]),ze=t=>{e.register(`activity:filter-pro`,Re),t.page({name:`规则集`,path:`/filter-pro`,icon:`activity:filter-pro`,order:320,component:Pe})};export{ze as default};
package/dist/style.css CHANGED
@@ -53,6 +53,96 @@
53
53
  }
54
54
 
55
55
 
56
+ .tag-input-wrap[data-v-8e9ea736] {
57
+ display: flex;
58
+ flex-wrap: wrap;
59
+ align-items: center;
60
+ gap: 4px;
61
+ flex: 1;
62
+ min-width: 160px;
63
+ min-height: 35px;
64
+ box-sizing: border-box;
65
+ padding: 4px 8px;
66
+ background: var(--k-input-bg, transparent);
67
+ border: 1px solid var(--k-card-border, rgba(127, 127, 127, 0.35));
68
+ border-radius: 6px;
69
+ cursor: text;
70
+ transition: border-color 0.15s;
71
+ }
72
+ .tag-input-wrap.is-focused[data-v-8e9ea736] {
73
+ border-color: var(--k-color-primary, #4f7cff);
74
+ }
75
+ .tag-chip[data-v-8e9ea736] {
76
+ display: inline-flex;
77
+ align-items: center;
78
+ gap: 2px;
79
+ background: color-mix(in srgb, var(--k-color-primary, #4f7cff) 15%, transparent);
80
+ border: 1px solid color-mix(in srgb, var(--k-color-primary, #4f7cff) 50%, transparent);
81
+ border-radius: 4px;
82
+ padding: 1px 4px 1px 8px;
83
+ font-size: 13px;
84
+ color: var(--k-text-normal, inherit);
85
+ white-space: nowrap;
86
+ line-height: 1.6;
87
+ }
88
+ .chip-text[data-v-8e9ea736] {
89
+ line-height: 1.4;
90
+ }
91
+ .chip-del[data-v-8e9ea736] {
92
+ display: inline-flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ width: 16px;
96
+ height: 16px;
97
+ border: none;
98
+ background: none;
99
+ color: var(--k-text-secondary, #888);
100
+ cursor: pointer;
101
+ padding: 0;
102
+ font-size: 15px;
103
+ border-radius: 3px;
104
+ line-height: 1;
105
+ flex-shrink: 0;
106
+ }
107
+ .chip-del[data-v-8e9ea736]:hover {
108
+ background: color-mix(in srgb, #e74c3c 20%, transparent);
109
+ color: #e74c3c;
110
+ }
111
+ .tag-text-input[data-v-8e9ea736] {
112
+ flex: 1;
113
+ min-width: 80px;
114
+ border: none;
115
+ outline: none;
116
+ background: transparent;
117
+ color: var(--k-text-normal, inherit);
118
+ font-size: 14px;
119
+ padding: 0;
120
+ height: 22px;
121
+ }
122
+ .tag-text-input[data-v-8e9ea736]::placeholder {
123
+ color: var(--k-text-secondary, rgba(127, 127, 127, 0.6));
124
+ }
125
+ .tag-clear-btn[data-v-8e9ea736] {
126
+ display: inline-flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ width: 18px;
130
+ height: 18px;
131
+ border: none;
132
+ background: none;
133
+ color: var(--k-text-secondary, #888);
134
+ cursor: pointer;
135
+ padding: 0;
136
+ font-size: 16px;
137
+ border-radius: 50%;
138
+ margin-left: 2px;
139
+ flex-shrink: 0;
140
+ }
141
+ .tag-clear-btn[data-v-8e9ea736]:hover {
142
+ background: color-mix(in srgb, currentColor 15%, transparent);
143
+ }
144
+
145
+
56
146
  .cf-editor[data-v-40533e84] {
57
147
  display: flex;
58
148
  flex-direction: column;
@@ -229,6 +319,187 @@
229
319
  }
230
320
 
231
321
 
322
+ .plugin-selector[data-v-6b39c823] {
323
+ position: relative;
324
+ min-width: 140px;
325
+ }
326
+ .trigger-btn[data-v-6b39c823] {
327
+ width: 100%;
328
+ display: flex;
329
+ align-items: center;
330
+ justify-content: space-between;
331
+ gap: 8px;
332
+ color: var(--k-text-normal, inherit);
333
+ background: var(--k-input-bg, transparent);
334
+ border: 1px solid var(--k-card-border, rgba(127, 127, 127, 0.35));
335
+ border-radius: 6px;
336
+ padding: 6px 10px;
337
+ cursor: pointer;
338
+ transition: border-color 0.2s;
339
+ }
340
+ .trigger-btn[data-v-6b39c823]:hover {
341
+ border-color: var(--k-color-primary, #4f7cff);
342
+ }
343
+ .label[data-v-6b39c823] {
344
+ overflow: hidden;
345
+ text-overflow: ellipsis;
346
+ white-space: nowrap;
347
+ flex: 1;
348
+ text-align: left;
349
+ }
350
+ .arrow[data-v-6b39c823] {
351
+ flex-shrink: 0;
352
+ }
353
+
354
+ /* 对话框 */
355
+ .dialog-overlay[data-v-6b39c823] {
356
+ position: fixed;
357
+ top: 0;
358
+ left: 0;
359
+ right: 0;
360
+ bottom: 0;
361
+ background: rgba(0, 0, 0, 0.5);
362
+ display: flex;
363
+ align-items: center;
364
+ justify-content: center;
365
+ z-index: 10000;
366
+ }
367
+ .dialog-content[data-v-6b39c823] {
368
+ background: var(--k-card-bg, #1e1e1e);
369
+ border: 1px solid var(--k-card-border, rgba(127, 127, 127, 0.35));
370
+ border-radius: 12px;
371
+ width: 90%;
372
+ max-width: 500px;
373
+ max-height: 80vh;
374
+ display: flex;
375
+ flex-direction: column;
376
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
377
+ }
378
+ .dialog-header[data-v-6b39c823] {
379
+ display: flex;
380
+ align-items: center;
381
+ justify-content: space-between;
382
+ padding: 16px 20px;
383
+ border-bottom: 1px solid var(--k-card-border, rgba(127, 127, 127, 0.2));
384
+ }
385
+ .dialog-header h3[data-v-6b39c823] {
386
+ margin: 0;
387
+ font-size: 16px;
388
+ font-weight: 600;
389
+ color: var(--k-text-normal, inherit);
390
+ }
391
+ .close-btn[data-v-6b39c823] {
392
+ width: 28px;
393
+ height: 28px;
394
+ display: flex;
395
+ align-items: center;
396
+ justify-content: center;
397
+ border: none;
398
+ border-radius: 6px;
399
+ background: transparent;
400
+ color: var(--k-text-secondary, #888);
401
+ cursor: pointer;
402
+ font-size: 18px;
403
+ transition: color 0.15s, background 0.15s;
404
+ }
405
+ .close-btn[data-v-6b39c823]:hover {
406
+ color: var(--k-text-normal, inherit);
407
+ background: color-mix(in srgb, var(--k-card-border, #888) 20%, transparent);
408
+ }
409
+ .dialog-body[data-v-6b39c823] {
410
+ flex: 1;
411
+ min-height: 0;
412
+ display: flex;
413
+ flex-direction: column;
414
+ padding: 16px 20px;
415
+ overflow: hidden;
416
+ }
417
+ .toolbar[data-v-6b39c823] {
418
+ display: flex;
419
+ align-items: center;
420
+ gap: 12px;
421
+ margin-bottom: 12px;
422
+ }
423
+ .select-all[data-v-6b39c823] {
424
+ flex-shrink: 0;
425
+ font-weight: 600;
426
+ }
427
+ .search-input[data-v-6b39c823] {
428
+ flex: 1;
429
+ min-width: 0;
430
+ color: var(--k-text-normal, inherit);
431
+ background: var(--k-input-bg, transparent);
432
+ border: 1px solid var(--k-card-border, rgba(127, 127, 127, 0.35));
433
+ border-radius: 6px;
434
+ padding: 6px 10px;
435
+ font-size: 14px;
436
+ }
437
+ .plugin-list[data-v-6b39c823] {
438
+ flex: 1;
439
+ min-height: 0;
440
+ overflow-y: auto;
441
+ display: flex;
442
+ flex-direction: column;
443
+ gap: 8px;
444
+ }
445
+ .checkbox-item[data-v-6b39c823] {
446
+ display: flex;
447
+ align-items: center;
448
+ gap: 8px;
449
+ padding: 8px;
450
+ border-radius: 6px;
451
+ cursor: pointer;
452
+ transition: background 0.15s;
453
+ user-select: none;
454
+ }
455
+ .checkbox-item[data-v-6b39c823]:hover {
456
+ background: color-mix(in srgb, var(--k-card-border, #888) 15%, transparent);
457
+ }
458
+ .checkbox-item input[type='checkbox'][data-v-6b39c823] {
459
+ width: 16px;
460
+ height: 16px;
461
+ cursor: pointer;
462
+ flex-shrink: 0;
463
+ }
464
+ .checkbox-item span[data-v-6b39c823] {
465
+ color: var(--k-text-normal, inherit);
466
+ font-size: 14px;
467
+ }
468
+ .empty-state[data-v-6b39c823] {
469
+ padding: 40px 20px;
470
+ text-align: center;
471
+ color: var(--k-text-secondary, #888);
472
+ }
473
+ .dialog-footer[data-v-6b39c823] {
474
+ display: flex;
475
+ align-items: center;
476
+ justify-content: flex-end;
477
+ gap: 8px;
478
+ padding: 16px 20px;
479
+ border-top: 1px solid var(--k-card-border, rgba(127, 127, 127, 0.2));
480
+ }
481
+ .btn[data-v-6b39c823] {
482
+ padding: 6px 16px;
483
+ border-radius: 6px;
484
+ border: none;
485
+ cursor: pointer;
486
+ font-size: 14px;
487
+ transition: opacity 0.15s;
488
+ }
489
+ .btn[data-v-6b39c823]:hover {
490
+ opacity: 0.85;
491
+ }
492
+ .btn-cancel[data-v-6b39c823] {
493
+ background: transparent;
494
+ color: var(--k-text-normal, inherit);
495
+ border: 1px solid var(--k-card-border, rgba(127, 127, 127, 0.35));
496
+ }
497
+ .btn-confirm[data-v-6b39c823] {
498
+ background: var(--k-color-primary, #4f7cff);
499
+ color: #fff;
500
+ }
501
+
502
+
232
503
  .fp-layout[data-v-0e916acc] {
233
504
  position: absolute;
234
505
  top: 0;
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);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;
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`,`in`,`nin`,`includes`,`notincludes`,`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;n.type===`global`?r=``:(n.type===`plugin`||n.type===`command`)&&(r=Array.isArray(n.value)?n.value.filter(e=>typeof e==`string`&&e.trim()).map(e=>e.trim()):typeof n.value==`string`&&n.value.trim()?[n.value.trim()]:[]);let i={type:n.type===`command`?`command`:n.type===`plugin`?`plugin`:`global`,value:r};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:i,condition:d(t.condition),response:t.response??``}}function p(e,t){if(!e||e.type===`global`)return!0;if(e.type===`plugin`){let n=typeof t.pluginKey==`string`?t.pluginKey:``;if(!n)return!1;if(Array.isArray(e.value))return e.value.length>0&&e.value.includes(n);let r=typeof e.value==`string`?e.value.trim():``;return r&&n===r}if(e.type===`command`){let n=typeof t.commandName==`string`?t.commandName:``;if(!n)return!1;if(Array.isArray(e.value))return e.value.length>0&&e.value.includes(n);let r=typeof e.value==`string`?e.value.trim():``;return r&&n===r}return!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){if(Array.isArray(e))return e;if(typeof e!=`string`)return[e];let t=e.split(/[,,]/).map(e=>e.trim()).filter(e=>e);return t.length>1?t:[e]}function x(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;let a=b(n);if(t.operator===`in`)return a.some(e=>r===y(e));if(t.operator===`nin`)return a.every(e=>r!==y(e));if(t.operator===`includes`){if(typeof r==`string`)return a.some(e=>r.includes(String(y(e)??``)));if(Array.isArray(e)){let t=e.map(e=>y(e));return a.some(e=>t.includes(y(e)))}return!1}if(t.operator===`notincludes`){if(typeof r==`string`)return a.every(e=>!r.includes(String(y(e)??``)));if(Array.isArray(e)){let t=e.map(e=>y(e));return a.every(e=>!t.includes(y(e)))}return!1}if(t.operator===`regex`){if(typeof r!=`string`)return!1;try{return new RegExp(String(y(a[0])??``)).test(r)}catch{return!1}}let o=y(a[0]),s=v(e),c=v(o);return s===null||c===null?!1:t.operator===`gt`?s>c:t.operator===`gte`?s>=c:t.operator===`lt`?s<c:t.operator===`lte`?s<=c:!1}function S(e,t){return e.type===`group`?e.children.length?e.operator===`and`?e.children.every(e=>S(e,t)):e.children.some(e=>S(e,t)):!0:e.type===`not`?!S(e.child,t):x(_(t,e.field),e)}async function C(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 w(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 T(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=w(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,x=(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=x(t,{pluginKey:e});for(let t of u(s.rules)){if(!t.enabled||t.target.type!==`plugin`)continue;let r=!1;if(Array.isArray(t.target.value)?r=t.target.value.includes(e):typeof t.target.value==`string`&&(r=t.target.value.trim()===e),!r)continue;let i=S(t.condition,n);if(_(`native-filter:evaluate`,{pluginKey:e,ruleId:t.id,ruleName:t.name,action:t.action,matched:i}),i)return t.action===`bypass`}return!0},E=(async()=>{await(0,r.mkdir)(i,{recursive:!0});let e=await C(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;for(let e of s.rules)if(!(!e.enabled||e.target.type!==`plugin`||!e.target.value)){if(Array.isArray(e.target.value))for(let t of e.target.value)n.add(t);else if(typeof e.target.value==`string`){let t=e.target.value.trim();t&&n.add(t)}}_(`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=x(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=S(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=String(e.command.name??``),r=x(e.session,{commandName:n,pluginKey:t?.key,pluginName:t?.name});_(`command:incoming`,{command:r.commandName,pluginKey:r.pluginKey,pluginName:r.pluginName,isDirect:r.isDirect,guildId:r.guildId,content:r.content,ruleCount:s.rules.length});for(let t of u(s.rules)){if(!t.enabled||t.target.type!==`command`||!p(t.target,r))continue;let i=S(t.condition,r);if(_(`command:evaluate`,{ruleId:t.id,ruleName:t.name,action:t.action,matched:i,commandName:n}),i){if(t.action===`bypass`){_(`command:action`,{ruleId:t.id,action:`bypass`});return}return _(`command:action`,{ruleId:t.id,action:`block`,response:t.response||``}),t.response&&await e.session.send(t.response),``}}_(`command:pass`,{reason:`no-command-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),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/commands`,async()=>(e?.$commander?._commandList||[]).map(e=>({name:String(e.name??``),label:String(e.name??``)})),{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=T,exports.filter=!1,exports.name=`filter-pro`,exports.reusable=!0;
package/lib/index.d.ts CHANGED
@@ -7,11 +7,11 @@ declare const reusable = true;
7
7
  declare const filter = false;
8
8
  type RuleAction = 'bypass' | 'block';
9
9
  type GroupOperator = 'and' | 'or';
10
- type CompareOperator = 'eq' | 'ne' | 'includes' | 'regex' | 'gt' | 'gte' | 'lt' | 'lte' | 'exists';
11
- type TargetType = 'global' | 'plugin';
10
+ type CompareOperator = 'eq' | 'ne' | 'in' | 'nin' | 'includes' | 'notincludes' | 'regex' | 'gt' | 'gte' | 'lt' | 'lte' | 'exists';
11
+ type TargetType = 'global' | 'plugin' | 'command';
12
12
  interface RuleTarget {
13
13
  type: TargetType;
14
- value?: string;
14
+ value?: string | string[];
15
15
  }
16
16
  interface GroupExpr {
17
17
  type: 'group';
@@ -63,6 +63,10 @@ interface PluginTargetOption {
63
63
  ident: string;
64
64
  label: string;
65
65
  }
66
+ interface CommandOption {
67
+ name: string;
68
+ label: string;
69
+ }
66
70
  declare module '@koishijs/plugin-console' {
67
71
  namespace Console {
68
72
  interface Services {
@@ -71,6 +75,7 @@ declare module '@koishijs/plugin-console' {
71
75
  interface Events {
72
76
  'filter-pro/list': () => Awaitable<RuleItem[]>;
73
77
  'filter-pro/targets': () => Awaitable<PluginTargetOption[]>;
78
+ 'filter-pro/commands': () => Awaitable<CommandOption[]>;
74
79
  'filter-pro/create': (input: RuleInput) => Awaitable<RuleItem>;
75
80
  'filter-pro/update': (input: RuleInput) => Awaitable<RuleItem | null>;
76
81
  'filter-pro/delete': (id: string) => Awaitable<boolean>;
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=!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};
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`,`in`,`nin`,`includes`,`notincludes`,`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;n.type===`global`?r=``:(n.type===`plugin`||n.type===`command`)&&(r=Array.isArray(n.value)?n.value.filter(e=>typeof e==`string`&&e.trim()).map(e=>e.trim()):typeof n.value==`string`&&n.value.trim()?[n.value.trim()]:[]);let i={type:n.type===`command`?`command`:n.type===`plugin`?`plugin`:`global`,value:r};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:i,condition:v(t.condition),response:t.response??``}}function b(e,t){if(!e||e.type===`global`)return!0;if(e.type===`plugin`){let n=typeof t.pluginKey==`string`?t.pluginKey:``;if(!n)return!1;if(Array.isArray(e.value))return e.value.length>0&&e.value.includes(n);let r=typeof e.value==`string`?e.value.trim():``;return r&&n===r}if(e.type===`command`){let n=typeof t.commandName==`string`?t.commandName:``;if(!n)return!1;if(Array.isArray(e.value))return e.value.length>0&&e.value.includes(n);let r=typeof e.value==`string`?e.value.trim():``;return r&&n===r}return!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){if(Array.isArray(e))return e;if(typeof e!=`string`)return[e];let t=e.split(/[,,]/).map(e=>e.trim()).filter(e=>e);return t.length>1?t:[e]}function O(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;let a=D(n);if(t.operator===`in`)return a.some(e=>r===E(e));if(t.operator===`nin`)return a.every(e=>r!==E(e));if(t.operator===`includes`){if(typeof r==`string`)return a.some(e=>r.includes(String(E(e)??``)));if(Array.isArray(e)){let t=e.map(e=>E(e));return a.some(e=>t.includes(E(e)))}return!1}if(t.operator===`notincludes`){if(typeof r==`string`)return a.every(e=>!r.includes(String(E(e)??``)));if(Array.isArray(e)){let t=e.map(e=>E(e));return a.every(e=>!t.includes(E(e)))}return!1}if(t.operator===`regex`){if(typeof r!=`string`)return!1;try{return new RegExp(String(E(a[0])??``)).test(r)}catch{return!1}}let o=E(a[0]),s=T(e),c=T(o);return s===null||c===null?!1:t.operator===`gt`?s>c:t.operator===`gte`?s>=c:t.operator===`lt`?s<c:t.operator===`lte`?s<=c:!1}function k(e,t){return e.type===`group`?e.children.length?e.operator===`and`?e.children.every(e=>k(e,t)):e.children.some(e=>k(e,t)):!0:e.type===`not`?!k(e.child,t):O(w(t,e.field),e)}async function A(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 j(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 M(e,t={}){let n=r(e.baseDir||process.cwd(),`data`,`filterpro`),o=r(n,t.filename||`rules.json`),s={rules:[]},c=j(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`)continue;let r=!1;if(Array.isArray(t.target.value)?r=t.target.value.includes(e):typeof t.target.value==`string`&&(r=t.target.value.trim()===e),!r)continue;let i=k(t.condition,n);if(d(`native-filter:evaluate`,{pluginKey:e,ruleId:t.id,ruleName:t.name,action:t.action,matched:i}),i)return t.action===`bypass`}return!0},w=(async()=>{await a(n,{recursive:!0});let e=await A(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;for(let e of s.rules)if(!(!e.enabled||e.target.type!==`plugin`||!e.target.value)){if(Array.isArray(e.target.value))for(let t of e.target.value)n.add(t);else if(typeof e.target.value==`string`){let t=e.target.value.trim();t&&n.add(t)}}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=k(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=String(e.command.name??``),r=v(e.session,{commandName:n,pluginKey:t?.key,pluginName:t?.name});d(`command:incoming`,{command:r.commandName,pluginKey:r.pluginKey,pluginName:r.pluginName,isDirect:r.isDirect,guildId:r.guildId,content:r.content,ruleCount:s.rules.length});for(let t of _(s.rules)){if(!t.enabled||t.target.type!==`command`||!b(t.target,r))continue;let i=k(t.condition,r);if(d(`command:evaluate`,{ruleId:t.id,ruleName:t.name,action:t.action,matched:i,commandName:n}),i){if(t.action===`bypass`){d(`command:action`,{ruleId:t.id,action:`bypass`});return}return d(`command:action`,{ruleId:t.id,action:`block`,response:t.response||``}),t.response&&await e.session.send(t.response),``}}d(`command:pass`,{reason:`no-command-rule-matched`})}),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/commands`,async()=>(e?.$commander?._commandList||[]).map(e=>({name:String(e.name??``),label:String(e.name??``)})),{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,M 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.16",
4
+ "version": "1.0.17",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "lib/index.mjs",
7
7
  "types": "lib/index.d.ts",