koishi-plugin-chat-patch 2.0.1 → 2.1.1

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/style.css CHANGED
@@ -1 +1 @@
1
- .scrollbar-hide::-webkit-scrollbar{display:none}.chat-patch-wrapper .el-textarea__inner{border-radius:12px;padding:10px 12px;resize:none}.chat-patch-wrapper .el-button--primary{border-radius:10px}.forward-dialog .el-dialog__body{padding:0}.image-viewer-dialog .el-dialog__header{padding-bottom:10px}.fixed{position:fixed!important}.absolute{position:absolute!important}.relative{position:relative!important}.inset-0{top:0!important;right:0!important;bottom:0!important;left:0!important}.-right-2{right:-.5rem!important}.-top-2{top:-.5rem!important}.z-10{z-index:10!important}.z-50{z-index:50!important}.z-\[2000\]{z-index:2000!important}.z-\[60\]{z-index:60!important}.mx-0\.5{margin-left:.125rem!important;margin-right:.125rem!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-1\.5{margin-top:.375rem!important;margin-bottom:.375rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.mb-1{margin-bottom:.25rem!important}.mb-1\.5{margin-bottom:.375rem!important}.mb-2{margin-bottom:.5rem!important}.mb-2\.5{margin-bottom:.625rem!important}.mb-3{margin-bottom:.75rem!important}.mb-6{margin-bottom:1.5rem!important}.ml-2{margin-left:.5rem!important}.ml-3{margin-left:.75rem!important}.mr-1{margin-right:.25rem!important}.mr-3{margin-right:.75rem!important}.mt-2{margin-top:.5rem!important}.block{display:block!important}.flex{display:flex!important}.\!h-10,.h-10{height:2.5rem!important}.h-14{height:3.5rem!important}.h-2\.5{height:.625rem!important}.h-20{height:5rem!important}.h-full{height:100%!important}.max-h-\[100px\]{max-height:100px!important}.max-h-\[400px\]{max-height:400px!important}.max-h-\[70vh\]{max-height:70vh!important}.max-h-full{max-height:100%!important}.min-h-\[1em\]{min-height:1em!important}.min-h-full{min-height:100%!important}.\!w-10{width:2.5rem!important}.w-2\.5{width:.625rem!important}.w-20{width:5rem!important}.w-full{width:100%!important}.min-w-\[140px\]{min-width:140px!important}.min-w-\[20px\]{min-width:20px!important}.max-w-\[100px\]{max-width:100px!important}.max-w-\[300px\]{max-width:300px!important}.max-w-\[85\%\]{max-width:85%!important}.max-w-full{max-width:100%!important}.flex-1{flex:1 1 0%!important}.flex-shrink-0{flex-shrink:0!important}.cursor-default{cursor:default!important}.cursor-pointer{cursor:pointer!important}.resize{resize:both!important}.flex-row{flex-direction:row!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-col{flex-direction:column!important}.items-start{align-items:flex-start!important}.items-end{align-items:flex-end!important}.items-center{align-items:center!important}.justify-center{justify-content:center!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:.75rem!important}.gap-4{gap:1rem!important}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0 !important;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)))!important;margin-bottom:calc(.375rem * var(--tw-space-y-reverse))!important}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0 !important;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)))!important;margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))!important}.overflow-hidden{overflow:hidden!important}.overflow-x-auto{overflow-x:auto!important}.truncate{overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.break-all{word-break:break-all!important}.rounded{border-radius:.25rem!important}.rounded-2xl{border-radius:1rem!important}.rounded-full{border-radius:9999px!important}.rounded-lg{border-radius:.5rem!important}.rounded-xl{border-radius:.75rem!important}.rounded-tl-none{border-top-left-radius:0!important}.rounded-tr-none{border-top-right-radius:0!important}.border{border-width:1px!important}.border-2{border-width:2px!important}.border-b{border-bottom-width:1px!important}.border-l-4{border-left-width:4px!important}.border-r{border-right-width:1px!important}.border-t{border-top-width:1px!important}.\!border-none{border-style:none!important}.\!border-\[var\(--k-color-primary\)\]{border-color:var(--k-color-primary)!important}.border-\[var\(--k-border-color\)\]{border-color:var(--k-border-color)!important}.border-black\/10{border-color:#0000001a!important}.border-black\/5{border-color:#0000000d!important}.border-gray-400\/50{border-color:#9ca3af80!important}.border-transparent{border-color:transparent!important}.border-white\/10{border-color:#ffffff1a!important}.\!bg-white\/10{background-color:#ffffff1a!important}.bg-\[\#95ec69\]{--tw-bg-opacity: 1 !important;background-color:rgb(149 236 105 / var(--tw-bg-opacity, 1))!important}.bg-\[var\(--k-button-active-bg\)\]{background-color:var(--k-button-active-bg)!important}.bg-\[var\(--k-card-bg\)\]{background-color:var(--k-card-bg)!important}.bg-\[var\(--k-page-bg\)\]{background-color:var(--k-page-bg)!important}.bg-black{--tw-bg-opacity: 1 !important;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))!important}.bg-black\/5{background-color:#0000000d!important}.bg-gray-100{--tw-bg-opacity: 1 !important;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))!important}.bg-gray-400{--tw-bg-opacity: 1 !important;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))!important}.bg-gray-50{--tw-bg-opacity: 1 !important;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))!important}.bg-green-500{--tw-bg-opacity: 1 !important;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))!important}.bg-white{--tw-bg-opacity: 1 !important;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))!important}.bg-opacity-50{--tw-bg-opacity: .5 !important}.bg-opacity-90{--tw-bg-opacity: .9 !important}.object-contain{-o-object-fit:contain!important;object-fit:contain!important}.p-0{padding:0!important}.p-2\.5{padding:.625rem!important}.p-3{padding:.75rem!important}.p-3\.5{padding:.875rem!important}.p-4{padding:1rem!important}.p-6{padding:1.5rem!important}.px-4{padding-left:1rem!important;padding-right:1rem!important}.px-6{padding-left:1.5rem!important;padding-right:1.5rem!important}.py-1\.5{padding-top:.375rem!important;padding-bottom:.375rem!important}.py-2\.5{padding-top:.625rem!important;padding-bottom:.625rem!important}.py-4{padding-top:1rem!important;padding-bottom:1rem!important}.pb-2{padding-bottom:.5rem!important}.pt-2{padding-top:.5rem!important}.text-left{text-align:left!important}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"!important}.\!text-base{font-size:1rem!important;line-height:1.5rem!important}.\!text-xl{font-size:1.25rem!important;line-height:1.75rem!important}.text-\[10px\]{font-size:10px!important}.text-\[15px\]{font-size:15px!important}.text-lg{font-size:1.125rem!important;line-height:1.75rem!important}.text-sm{font-size:.875rem!important;line-height:1.25rem!important}.text-xs{font-size:.75rem!important;line-height:1rem!important}.font-bold{font-weight:700!important}.font-medium{font-weight:500!important}.italic{font-style:italic!important}.leading-relaxed{line-height:1.625!important}.\!text-white{--tw-text-opacity: 1 !important;color:rgb(255 255 255 / var(--tw-text-opacity, 1))!important}.text-\[var\(--k-color-primary\)\]{color:var(--k-color-primary)!important}.text-\[var\(--k-text-color\)\]{color:var(--k-text-color)!important}.text-\[var\(--k-text-color-secondary\)\]{color:var(--k-text-color-secondary)!important}.text-black{--tw-text-opacity: 1 !important;color:rgb(0 0 0 / var(--tw-text-opacity, 1))!important}.text-blue-500{--tw-text-opacity: 1 !important;color:rgb(59 130 246 / var(--tw-text-opacity, 1))!important}.text-gray-400{--tw-text-opacity: 1 !important;color:rgb(156 163 175 / var(--tw-text-opacity, 1))!important}.text-orange-400{--tw-text-opacity: 1 !important;color:rgb(251 146 60 / var(--tw-text-opacity, 1))!important}.text-red-500{--tw-text-opacity: 1 !important;color:rgb(239 68 68 / var(--tw-text-opacity, 1))!important}.text-white{--tw-text-opacity: 1 !important;color:rgb(255 255 255 / var(--tw-text-opacity, 1))!important}.opacity-0{opacity:0!important}.opacity-50{opacity:.5!important}.opacity-60{opacity:.6!important}.opacity-70{opacity:.7!important}.opacity-80{opacity:.8!important}.opacity-90{opacity:.9!important}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25) !important;--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-\[0_-2px_10px_rgba\(0\,0\,0\,0\.05\)\]{--tw-shadow: 0 -2px 10px rgba(0,0,0,.05) !important;--tw-shadow-colored: 0 -2px 10px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.brightness-100{--tw-brightness: brightness(1) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.brightness-105{--tw-brightness: brightness(1.05) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.brightness-95{--tw-brightness: brightness(.95) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px) !important;-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)!important;backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)!important}.transition-all{transition-property:all!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-opacity{transition-property:opacity!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-transform{transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}:root{--chat-bg: var(--k-page-bg);--chat-panel-bg: var(--k-card-bg);--chat-border: var(--k-border-color);--chat-text: var(--k-text-color);--chat-text-sub: var(--k-text-color-secondary)}.chat-patch-wrapper{color:var(--chat-text);background-color:var(--chat-bg)}.chat-patch-wrapper .el-aside,.chat-patch-wrapper .el-main,.chat-patch-wrapper .el-header,.chat-patch-wrapper .el-footer{background-color:transparent!important;color:inherit!important}.chat-patch-wrapper .el-scrollbar{background-color:transparent!important}.chat-patch-wrapper .el-input__wrapper,.chat-patch-wrapper .el-textarea__inner{background-color:var(--k-input-bg)!important;color:var(--chat-text)!important;box-shadow:0 0 0 1px var(--chat-border) inset!important}.chat-patch-wrapper .el-empty{background-color:transparent!important}.layout-iframe{width:100%;height:100%;border:none}.hover\:scale-105:hover{--tw-scale-x: 1.05 !important;--tw-scale-y: 1.05 !important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.hover\:bg-\[var\(--k-button-hover-bg\)\]:hover{background-color:var(--k-button-hover-bg)!important}.hover\:bg-black\/10:hover{background-color:#0000001a!important}.hover\:underline:hover{text-decoration-line:underline!important}.hover\:opacity-90:hover{opacity:.9!important}.group:hover .group-hover\:opacity-100{opacity:1!important}@media (min-width: 768px){.md\:max-w-\[75\%\]{max-width:75%!important}}@media (prefers-color-scheme: dark){.dark\:border-white\/10{border-color:#ffffff1a!important}.dark\:border-white\/5{border-color:#ffffff0d!important}.dark\:bg-black\/10{background-color:#0000001a!important}.dark\:bg-black\/20{background-color:#0003!important}.dark\:bg-white\/5{background-color:#ffffff0d!important}.dark\:brightness-100{--tw-brightness: brightness(1) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.dark\:brightness-90{--tw-brightness: brightness(.9) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.dark\:brightness-95{--tw-brightness: brightness(.95) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.dark\:hover\:bg-white\/10:hover{background-color:#ffffff1a!important}}
1
+ @charset "UTF-8";.scrollbar-hide::-webkit-scrollbar{display:none}.chat-patch-wrapper .el-textarea__inner{border-radius:12px;padding:10px 12px;resize:none}.chat-patch-wrapper .raw-content-area .el-textarea__inner{font-family:monospace;font-size:14px;line-height:1.5;background:var(--k-card-bg)!important}.chat-patch-wrapper .el-button--primary{border-radius:10px}.forward-dialog .el-dialog__body{padding:0}.image-viewer-dialog .el-dialog__header{padding-bottom:10px}.fixed{position:fixed!important}.absolute{position:absolute!important}.relative{position:relative!important}.inset-0{top:0!important;right:0!important;bottom:0!important;left:0!important}.-right-1\.5{right:-.375rem!important}.-top-1\.5{top:-.375rem!important}.left-0{left:0!important}.right-0{right:0!important}.right-1{right:.25rem!important}.top-1{top:.25rem!important}.z-10{z-index:10!important}.z-50{z-index:50!important}.z-\[2000\]{z-index:2000!important}.z-\[60\]{z-index:60!important}.z-\[70\]{z-index:70!important}.z-\[80\]{z-index:80!important}.mx-0\.5{margin-left:.125rem!important;margin-right:.125rem!important}.mx-1{margin-left:.25rem!important;margin-right:.25rem!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-1\.5{margin-top:.375rem!important;margin-bottom:.375rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.mb-1{margin-bottom:.25rem!important}.mb-1\.5{margin-bottom:.375rem!important}.mb-2{margin-bottom:.5rem!important}.mb-2\.5{margin-bottom:.625rem!important}.mb-3{margin-bottom:.75rem!important}.mb-6{margin-bottom:1.5rem!important}.ml-2{margin-left:.5rem!important}.ml-3{margin-left:.75rem!important}.mr-1{margin-right:.25rem!important}.mr-2{margin-right:.5rem!important}.mr-3{margin-right:.75rem!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-4{margin-top:1rem!important}.block{display:block!important}.flex{display:flex!important}.hidden{display:none!important}.\!h-10,.h-10{height:2.5rem!important}.h-14{height:3.5rem!important}.h-2\.5{height:.625rem!important}.h-20{height:5rem!important}.h-8{height:2rem!important}.h-full{height:100%!important}.max-h-\[100px\]{max-height:100px!important}.max-h-\[400px\]{max-height:400px!important}.max-h-\[70vh\]{max-height:70vh!important}.max-h-full{max-height:100%!important}.min-h-\[1em\]{min-height:1em!important}.\!w-10{width:2.5rem!important}.w-2\.5{width:.625rem!important}.w-20{width:5rem!important}.w-8{width:2rem!important}.w-full{width:100%!important}.min-w-\[140px\]{min-width:140px!important}.min-w-\[20px\]{min-width:20px!important}.max-w-\[100px\]{max-width:100px!important}.max-w-\[300px\]{max-width:300px!important}.max-w-\[85\%\]{max-width:85%!important}.max-w-full{max-width:100%!important}.flex-1{flex:1 1 0%!important}.flex-shrink-0{flex-shrink:0!important}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.cursor-context-menu{cursor:context-menu!important}.cursor-default{cursor:default!important}.cursor-pointer{cursor:pointer!important}.resize{resize:both!important}.flex-row{flex-direction:row!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-col{flex-direction:column!important}.items-start{align-items:flex-start!important}.items-end{align-items:flex-end!important}.items-center{align-items:center!important}.justify-center{justify-content:center!important}.justify-between{justify-content:space-between!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:.75rem!important}.gap-4{gap:1rem!important}.gap-6{gap:1.5rem!important}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0 !important;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)))!important;margin-bottom:calc(.375rem * var(--tw-space-y-reverse))!important}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0 !important;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)))!important;margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-x-auto{overflow-x:auto!important}.truncate{overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.break-all{word-break:break-all!important}.rounded{border-radius:.25rem!important}.rounded-2xl{border-radius:1rem!important}.rounded-full{border-radius:9999px!important}.rounded-lg{border-radius:.5rem!important}.rounded-xl{border-radius:.75rem!important}.rounded-tl-none{border-top-left-radius:0!important}.rounded-tr-none{border-top-right-radius:0!important}.border{border-width:1px!important}.border-2{border-width:2px!important}.border-b{border-bottom-width:1px!important}.border-l-4{border-left-width:4px!important}.border-r{border-right-width:1px!important}.border-t{border-top-width:1px!important}.\!border-none{border-style:none!important}.\!border-\[var\(--k-color-primary\)\]{border-color:var(--k-color-primary)!important}.border-\[var\(--k-border-color\)\]{border-color:var(--k-border-color)!important}.border-black\/10{border-color:#0000001a!important}.border-black\/5{border-color:#0000000d!important}.border-blue-500{--tw-border-opacity: 1 !important;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))!important}.border-gray-400\/50{border-color:#9ca3af80!important}.border-transparent{border-color:transparent!important}.border-white\/10{border-color:#ffffff1a!important}.\!bg-white\/10{background-color:#ffffff1a!important}.bg-\[\#95ec69\]{--tw-bg-opacity: 1 !important;background-color:rgb(149 236 105 / var(--tw-bg-opacity, 1))!important}.bg-\[var\(--k-button-active-bg\)\]{background-color:var(--k-button-active-bg)!important}.bg-\[var\(--k-card-bg\)\]{background-color:var(--k-card-bg)!important}.bg-\[var\(--k-page-bg\)\]{background-color:var(--k-page-bg)!important}.bg-black{--tw-bg-opacity: 1 !important;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))!important}.bg-black\/5{background-color:#0000000d!important}.bg-blue-50\/10{background-color:#eff6ff1a!important}.bg-gray-100{--tw-bg-opacity: 1 !important;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))!important}.bg-gray-400{--tw-bg-opacity: 1 !important;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))!important}.bg-gray-50{--tw-bg-opacity: 1 !important;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))!important}.bg-green-500{--tw-bg-opacity: 1 !important;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))!important}.bg-white{--tw-bg-opacity: 1 !important;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))!important}.bg-opacity-50{--tw-bg-opacity: .5 !important}.bg-opacity-90{--tw-bg-opacity: .9 !important}.object-contain{-o-object-fit:contain!important;object-fit:contain!important}.p-0{padding:0!important}.p-10{padding:2.5rem!important}.p-2\.5{padding:.625rem!important}.p-3{padding:.75rem!important}.p-3\.5{padding:.875rem!important}.p-4{padding:1rem!important}.p-6{padding:1.5rem!important}.p-8{padding:2rem!important}.px-3{padding-left:.75rem!important;padding-right:.75rem!important}.px-4{padding-left:1rem!important;padding-right:1rem!important}.px-6{padding-left:1.5rem!important;padding-right:1.5rem!important}.py-1\.5{padding-top:.375rem!important;padding-bottom:.375rem!important}.py-2\.5{padding-top:.625rem!important;padding-bottom:.625rem!important}.py-4{padding-top:1rem!important;padding-bottom:1rem!important}.pb-2{padding-bottom:.5rem!important}.pb-8{padding-bottom:2rem!important}.pr-8{padding-right:2rem!important}.pt-2{padding-top:.5rem!important}.text-left{text-align:left!important}.text-center{text-align:center!important}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"!important}.\!text-base{font-size:1rem!important;line-height:1.5rem!important}.\!text-xl{font-size:1.25rem!important;line-height:1.75rem!important}.text-2xl{font-size:1.5rem!important;line-height:2rem!important}.text-\[10px\]{font-size:10px!important}.text-\[15px\]{font-size:15px!important}.text-lg{font-size:1.125rem!important;line-height:1.75rem!important}.text-sm{font-size:.875rem!important;line-height:1.25rem!important}.text-xl{font-size:1.25rem!important;line-height:1.75rem!important}.text-xs{font-size:.75rem!important;line-height:1rem!important}.font-bold{font-weight:700!important}.font-medium{font-weight:500!important}.italic{font-style:italic!important}.leading-relaxed{line-height:1.625!important}.\!text-white{--tw-text-opacity: 1 !important;color:rgb(255 255 255 / var(--tw-text-opacity, 1))!important}.text-\[var\(--k-color-primary\)\]{color:var(--k-color-primary)!important}.text-\[var\(--k-text-color\)\]{color:var(--k-text-color)!important}.text-\[var\(--k-text-color-secondary\)\]{color:var(--k-text-color-secondary)!important}.text-black{--tw-text-opacity: 1 !important;color:rgb(0 0 0 / var(--tw-text-opacity, 1))!important}.text-blue-500{--tw-text-opacity: 1 !important;color:rgb(59 130 246 / var(--tw-text-opacity, 1))!important}.text-gray-400{--tw-text-opacity: 1 !important;color:rgb(156 163 175 / var(--tw-text-opacity, 1))!important}.text-orange-400{--tw-text-opacity: 1 !important;color:rgb(251 146 60 / var(--tw-text-opacity, 1))!important}.text-red-500{--tw-text-opacity: 1 !important;color:rgb(239 68 68 / var(--tw-text-opacity, 1))!important}.text-white{--tw-text-opacity: 1 !important;color:rgb(255 255 255 / var(--tw-text-opacity, 1))!important}.opacity-0{opacity:0!important}.opacity-100{opacity:1!important}.opacity-40{opacity:.4!important}.opacity-50{opacity:.5!important}.opacity-60{opacity:.6!important}.opacity-70{opacity:.7!important}.opacity-80{opacity:.8!important}.opacity-90{opacity:.9!important}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-\[0_-2px_10px_rgba\(0\,0\,0\,0\.05\)\]{--tw-shadow: 0 -2px 10px rgba(0,0,0,.05) !important;--tw-shadow-colored: 0 -2px 10px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.blur{--tw-blur: blur(8px) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.brightness-100{--tw-brightness: brightness(1) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.brightness-105{--tw-brightness: brightness(1.05) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.brightness-95{--tw-brightness: brightness(.95) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px) !important;-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)!important;backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)!important}.transition-all{transition-property:all!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-opacity{transition-property:opacity!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-transform{transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.duration-200{transition-duration:.2s!important}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)!important}.will-change-transform{will-change:transform!important}:root{--chat-bg: var(--k-page-bg);--chat-panel-bg: var(--k-card-bg);--chat-border: var(--k-border-color);--chat-text: var(--k-text-color);--chat-text-sub: var(--k-text-color-secondary)}.chat-patch-wrapper .mobile-scrollbar-fix .el-scrollbar__bar{display:none!important;opacity:0!important;width:0!important;height:0!important}.chat-patch-wrapper .mobile-scrollbar-fix .el-scrollbar__thumb{display:none!important}.chat-patch-wrapper .mobile-scrollbar-fix .el-scrollbar__wrap{overflow-x:hidden!important;scrollbar-width:none!important;-ms-overflow-style:none!important}.chat-patch-wrapper .mobile-scrollbar-fix .el-scrollbar__wrap::-webkit-scrollbar{display:none!important;width:0!important;height:0!important;background:transparent!important}.chat-patch-wrapper .mobile-scrollbar-fix .el-scrollbar__wrap::-webkit-scrollbar-track{display:none!important}.chat-patch-wrapper .mobile-scrollbar-fix .el-scrollbar__wrap::-webkit-scrollbar-thumb{display:none!important}.chat-patch-wrapper{color:var(--chat-text);background-color:var(--chat-bg)}.chat-patch-wrapper .el-aside,.chat-patch-wrapper .el-main,.chat-patch-wrapper .el-header,.chat-patch-wrapper .el-footer{background-color:transparent!important;color:inherit!important}.chat-patch-wrapper .el-scrollbar{background-color:transparent!important}.chat-patch-wrapper .el-input__wrapper,.chat-patch-wrapper .el-textarea__inner{background-color:var(--k-input-bg)!important;color:var(--chat-text)!important;box-shadow:0 0 0 1px var(--chat-border) inset!important}.chat-patch-wrapper .el-empty{background-color:transparent!important}.layout-iframe{width:100%;height:100%;border:none}.message-highlight{animation:highlight-fade 1.5s ease-in-out;border-radius:8px}@keyframes highlight-fade{0%{background-color:transparent}10%{background-color:#409eff66;filter:brightness(1.2)}30%{background-color:#409eff66;filter:brightness(1.2)}to{background-color:transparent}}.hover\:scale-105:hover{--tw-scale-x: 1.05 !important;--tw-scale-y: 1.05 !important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.hover\:scale-110:hover{--tw-scale-x: 1.1 !important;--tw-scale-y: 1.1 !important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.hover\:bg-\[var\(--k-button-hover-bg\)\]:hover{background-color:var(--k-button-hover-bg)!important}.hover\:bg-black\/10:hover{background-color:#0000001a!important}.hover\:text-red-500:hover{--tw-text-opacity: 1 !important;color:rgb(239 68 68 / var(--tw-text-opacity, 1))!important}.hover\:underline:hover{text-decoration-line:underline!important}.hover\:opacity-90:hover{opacity:.9!important}.hover\:brightness-90:hover{--tw-brightness: brightness(.9) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.active\:scale-95:active{--tw-scale-x: .95 !important;--tw-scale-y: .95 !important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.group\/msg:hover .group-hover\/msg\:opacity-100,.group:hover .group-hover\:opacity-100{opacity:1!important}@media (min-width: 768px){.md\:inline{display:inline!important}.md\:max-w-\[75\%\]{max-width:75%!important}}@media (prefers-color-scheme: dark){.dark\:border-white\/10{border-color:#ffffff1a!important}.dark\:border-white\/5{border-color:#ffffff0d!important}.dark\:bg-black\/10{background-color:#0000001a!important}.dark\:bg-black\/20{background-color:#0003!important}.dark\:bg-white\/5{background-color:#ffffff0d!important}.dark\:brightness-100{--tw-brightness: brightness(1) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.dark\:brightness-90{--tw-brightness: brightness(.9) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.dark\:brightness-95{--tw-brightness: brightness(.95) !important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.dark\:hover\:bg-white\/10:hover{background-color:#ffffff1a!important}}
@@ -0,0 +1,19 @@
1
+ import { FileManager } from './file-manager';
2
+ import { MessageHandler } from './message-handler';
3
+ import { Context } from 'koishi';
4
+ import { Config } from './config';
5
+ export declare class ApiHandlers {
6
+ private ctx;
7
+ private config;
8
+ private fileManager;
9
+ private messageHandler;
10
+ private logger;
11
+ constructor(ctx: Context, config: Config, fileManager: FileManager, messageHandler: MessageHandler);
12
+ registerApiHandlers(): void;
13
+ private isFileUrl;
14
+ private createFileUrl;
15
+ private handleLocalFileRequest;
16
+ private setupTempFileCleanup;
17
+ private cleanupMediaCache;
18
+ private logInfo;
19
+ }
@@ -0,0 +1,13 @@
1
+ import { Schema } from 'koishi';
2
+ export interface Config {
3
+ loggerinfo: boolean;
4
+ clearIndexedDBOnStart: boolean;
5
+ maxMessagesPerChannel: number;
6
+ keepMessagesOnClear: number;
7
+ maxPersistImages: number;
8
+ blockedPlatforms: Array<{
9
+ platformName: string;
10
+ exactMatch: boolean;
11
+ }>;
12
+ }
13
+ export declare const Config: Schema<Config>;
package/lib/index.js CHANGED
@@ -197,55 +197,120 @@ var MessageHandler = class {
197
197
  }
198
198
  // 更新频道信息到JSON文件
199
199
  async updateChannelInfoToFile(session) {
200
+ const isDirect = session.isDirect || session.channelId?.includes("private");
200
201
  let guildName = session.channelId;
201
- let directUserName = session.username || session.userId || "未知用户";
202
+ const directUserName = session.username || session.event?.user?.name || session.userId;
202
203
  const data = this.fileManager.readChatDataFromFile();
203
- try {
204
- if (session.guildId && session.bot.getGuild && typeof session.bot.getGuild === "function") {
205
- const guild = await session.bot.getGuild(session.guildId);
206
- guildName = guild?.name || session.channelId;
207
- }
208
- if (session.userId && session.isDirect && session.bot.getUser && typeof session.bot.getUser === "function") {
209
- try {
210
- const user = await session.bot.getUser(session.userId);
211
- directUserName = user?.name || session.username || session.userId || "未知用户";
212
- } catch (userError) {
213
- this.logInfo("获取用户信息失败,使用备用名称:", userError);
204
+ if (!isDirect) {
205
+ try {
206
+ if (session.guildId && session.bot.getGuild && typeof session.bot.getGuild === "function") {
207
+ const guild = await session.bot.getGuild(session.guildId);
208
+ guildName = guild?.name || session.channelId;
214
209
  }
215
- }
216
- if (session.guildId && !session.bot.getGuild && session.bot.getChannel && typeof session.bot.getChannel === "function") {
217
- try {
218
- const channel = await session.bot.getChannel(session.guildId);
219
- guildName = channel?.name || session.channelId;
220
- } catch (channelError) {
221
- this.logInfo("获取频道信息失败,使用频道ID作为备用:", channelError);
210
+ if (session.guildId && !session.bot.getGuild && session.bot.getChannel && typeof session.bot.getChannel === "function") {
211
+ try {
212
+ const channel = await session.bot.getChannel(session.guildId);
213
+ guildName = channel?.name || session.channelId;
214
+ } catch (channelError) {
215
+ this.logInfo("获取频道信息失败,使用频道ID作为备用:", channelError);
216
+ }
222
217
  }
218
+ } catch (error) {
219
+ this.logInfo("获取频道信息失败,使用频道ID作为备用:", error);
220
+ guildName = session.channelId;
223
221
  }
224
- } catch (error) {
225
- this.logInfo("获取频道信息失败,使用频道ID作为备用:", error);
226
- guildName = session.channelId;
227
222
  }
228
223
  if (!data.channels[session.selfId]) {
229
224
  data.channels[session.selfId] = {};
230
225
  }
226
+ const existingChannel = data.channels[session.selfId][session.channelId];
227
+ let finalName;
228
+ if (isDirect) {
229
+ if (directUserName && directUserName !== session.userId) {
230
+ finalName = `私聊(${directUserName})`;
231
+ } else if (existingChannel?.name && !existingChannel.name.includes("未知")) {
232
+ finalName = existingChannel.name;
233
+ } else if (session.platform && session.platform.toLowerCase().includes("sandbox")) {
234
+ finalName = `私聊(${session.userId})`;
235
+ } else {
236
+ finalName = "私聊(未知用户)";
237
+ }
238
+ } else {
239
+ finalName = guildName || session.channelId;
240
+ }
231
241
  const channelInfo = {
232
242
  id: session.channelId,
233
- name: session.isDirect ? `私聊(${session.username || session.userId || directUserName})` : `${guildName} (${session.channelId})`,
243
+ name: finalName,
234
244
  type: session.type || 0,
235
245
  channelId: session.channelId,
236
246
  guildName,
237
- isDirect: session.isDirect
247
+ isDirect: !!isDirect
238
248
  };
249
+ if (existingChannel && existingChannel.name !== finalName) {
250
+ this.logInfo("更新频道名称:", {
251
+ channelId: session.channelId,
252
+ oldName: existingChannel.name,
253
+ newName: finalName
254
+ });
255
+ }
239
256
  data.channels[session.selfId][session.channelId] = channelInfo;
240
257
  this.fileManager.writeChatDataToFile(data);
241
258
  this.logInfo("更新频道信息到文件:", channelInfo.name);
242
259
  return guildName;
243
260
  }
261
+ // 下载并缓存媒体文件
262
+ async downloadAndCacheMedia(url, type) {
263
+ try {
264
+ if (!url || url.startsWith("data:") || url.startsWith("file:")) return url;
265
+ let folder = "media";
266
+ if (type === "image") folder = "images";
267
+ else if (type === "avatar") folder = "avatars";
268
+ const dir = require("node:path").join(this.ctx.baseDir, "data", "chat-patch", "persist-media", folder);
269
+ if (!require("node:fs").existsSync(dir)) {
270
+ require("node:fs").mkdirSync(dir, { recursive: true });
271
+ }
272
+ const crypto = require("node:crypto");
273
+ const hash = crypto.createHash("md5").update(url).digest("hex");
274
+ const ext = require("node:path").extname(new URL(url).pathname) || (type === "image" ? ".jpg" : ".mp4");
275
+ const filename = `${hash}${ext}`;
276
+ const filePath = require("node:path").join(dir, filename);
277
+ if (require("node:fs").existsSync(filePath)) {
278
+ return require("node:url").pathToFileURL(filePath).href;
279
+ }
280
+ const buffer = await this.ctx.http.get(url, { responseType: "arraybuffer" });
281
+ require("node:fs").writeFileSync(filePath, Buffer.from(buffer));
282
+ return require("node:url").pathToFileURL(filePath).href;
283
+ } catch (e) {
284
+ return url;
285
+ }
286
+ }
287
+ // 处理消息中的媒体元素并缓存
288
+ async processMediaElements(elements) {
289
+ if (!elements) return elements;
290
+ for (const el of elements) {
291
+ if (["image", "img", "mface"].includes(el.type)) {
292
+ const src = el.attrs.src || el.attrs.url || el.attrs.file;
293
+ if (src) el.attrs.src = await this.downloadAndCacheMedia(src, "image");
294
+ } else if (["audio", "video"].includes(el.type)) {
295
+ const src = el.attrs.src || el.attrs.url || el.attrs.file;
296
+ if (src) el.attrs.src = await this.downloadAndCacheMedia(src, "media");
297
+ }
298
+ if (el.children) await this.processMediaElements(el.children);
299
+ }
300
+ return elements;
301
+ }
244
302
  async broadcastMessageEvent(session) {
245
303
  try {
246
304
  await this.updateBotInfoToFile(session);
247
305
  const guildName = await this.updateChannelInfoToFile(session);
306
+ const isDirect = session.isDirect || session.channelId?.includes("private");
248
307
  const timestamp = Date.now();
308
+ if (session.elements) {
309
+ await this.processMediaElements(session.elements);
310
+ }
311
+ if (session.quote?.elements) {
312
+ await this.processMediaElements(session.quote.elements);
313
+ }
249
314
  let quoteInfo = void 0;
250
315
  if (session.quote) {
251
316
  quoteInfo = {
@@ -290,7 +355,7 @@ var MessageHandler = class {
290
355
  guildName,
291
356
  platform: session.platform || "unknown",
292
357
  quote: quoteInfo ? this.utils.cleanBase64Content(quoteInfo) : void 0,
293
- isDirect: session.isDirect
358
+ isDirect: !!isDirect
294
359
  };
295
360
  await this.fileManager.addMessageToFile(messageInfo);
296
361
  const messageEvent = {
@@ -323,22 +388,47 @@ var MessageHandler = class {
323
388
  async broadcastBotMessageEvent(session) {
324
389
  try {
325
390
  const correctChannelId = this.getCorrectChannelId(session.selfId);
326
- this.logInfo("机器人发送消息调试信息:", {
327
- "session.channelId": session.channelId,
328
- "session.event?.channel?.id": session.event?.channel?.id,
329
- "correctChannelId": correctChannelId,
330
- "session.guildId": session.guildId,
331
- "session.isDirect": session.isDirect,
332
- "session.platform": session.platform
333
- });
334
391
  const finalChannelId = correctChannelId || session.channelId;
335
392
  await this.updateBotInfoToFile(session);
336
393
  const guildName = await this.updateChannelInfoToFile(session);
394
+ const isDirect = session.isDirect || finalChannelId?.includes("private");
337
395
  const timestamp = Date.now();
396
+ if (session.event?.message?.elements) {
397
+ await this.processMediaElements(session.event.message.elements);
398
+ }
338
399
  let content = session.content || "";
339
400
  if (!content && session.event?.message?.elements) {
340
401
  content = this.utils.extractTextContent(session.event.message.elements).trim();
341
402
  }
403
+ let quoteInfo = void 0;
404
+ const quoteMatch = content.match(/<quote id="([^"]+)"\/>/);
405
+ if (quoteMatch) {
406
+ const quoteId = quoteMatch[1];
407
+ const data = this.fileManager.readChatDataFromFile();
408
+ const channelKey = `${session.selfId}:${finalChannelId}`;
409
+ const quotedMsg = data.messages[channelKey]?.find((m) => m.id === quoteId);
410
+ if (quotedMsg) {
411
+ const realId = quotedMsg.id.startsWith("bot-msg-") ? quotedMsg.realId : quotedMsg.id;
412
+ quoteInfo = {
413
+ messageId: realId || quotedMsg.id,
414
+ id: realId || quotedMsg.id,
415
+ content: quotedMsg.content,
416
+ elements: quotedMsg.elements,
417
+ user: {
418
+ id: quotedMsg.userId,
419
+ name: quotedMsg.username,
420
+ userId: quotedMsg.userId,
421
+ avatar: quotedMsg.avatar,
422
+ username: quotedMsg.username
423
+ },
424
+ timestamp: quotedMsg.timestamp
425
+ };
426
+ content = content.replace(/<quote id="[^"]+"\/>\s*/, "");
427
+ if (realId) {
428
+ session.content = session.content.replace(/id="[^"]+"/, `id="${realId}"`);
429
+ }
430
+ }
431
+ }
342
432
  const messageInfo = {
343
433
  id: `bot-msg-${timestamp}`,
344
434
  content,
@@ -352,7 +442,10 @@ var MessageHandler = class {
352
442
  type: "bot",
353
443
  guildName,
354
444
  platform: session.platform || "unknown",
355
- isDirect: session.isDirect
445
+ quote: quoteInfo,
446
+ isDirect: !!isDirect,
447
+ sending: true
448
+ // 标记为正在发送
356
449
  };
357
450
  await this.fileManager.addMessageToFile(messageInfo);
358
451
  const messageEvent = {
@@ -369,26 +462,14 @@ var MessageHandler = class {
369
462
  guildName,
370
463
  channelType: session.event?.channel?.type || session.type || 0,
371
464
  elements: this.utils.cleanBase64Content(session.event?.message?.elements),
372
- isDirect: session.isDirect,
465
+ quote: quoteInfo,
466
+ isDirect: !!isDirect,
467
+ sending: true,
373
468
  bot: {
374
469
  avatar: session.bot.user?.avatar,
375
470
  name: session.bot.user?.name
376
471
  }
377
472
  };
378
- const imageElements = session.event?.message?.elements?.filter(
379
- (element) => element.type === "img" || element.type === "image" || element.type === "mface"
380
- ) || [];
381
- this.logInfo("机器人发送消息 (before-send):", {
382
- selfId: session.selfId,
383
- channelId: messageEvent.channelId,
384
- originalChannelId: session.channelId,
385
- correctedChannelId: finalChannelId,
386
- content,
387
- platform: session.platform,
388
- imageCount: imageElements.length,
389
- imageUrls: imageElements.map((el) => el.attrs?.src || el.attrs?.url || el.attrs?.file)
390
- });
391
- this.correctChannelIds.delete(session.selfId);
392
473
  this.ctx.console.broadcast("chat-bot-message-event", messageEvent);
393
474
  } catch (error) {
394
475
  this.logger.error("广播机器人消息事件失败:", error);
@@ -574,19 +655,16 @@ var ApiHandlers = class {
574
655
  this.ctx.console.addListener("get-chat-data", async () => {
575
656
  try {
576
657
  const data = this.fileManager.readChatDataFromFile();
577
- const cleanedData = this.fileManager.cleanExcessMessages(data);
578
- this.logInfo("获取聊天数据:", {
579
- 机器人数量: Object.keys(cleanedData.bots).length,
580
- 频道数量: Object.keys(cleanedData.channels).reduce((total, botId) => total + Object.keys(cleanedData.channels[botId] || {}).length, 0),
581
- 消息频道数: Object.keys(cleanedData.messages).length,
582
- 总消息数: Object.values(cleanedData.messages).reduce((total, msgs) => total + msgs.length, 0)
583
- });
658
+ this.logInfo("获取基础聊天数据");
584
659
  return {
585
660
  success: true,
586
661
  data: {
587
- ...cleanedData,
588
- pinnedBots: cleanedData.pinnedBots,
589
- pinnedChannels: cleanedData.pinnedChannels
662
+ bots: data.bots || {},
663
+ channels: data.channels || {},
664
+ pinnedBots: data.pinnedBots || [],
665
+ pinnedChannels: data.pinnedChannels || [],
666
+ // 不返回 messages,由前端按需拉取
667
+ messages: {}
590
668
  }
591
669
  };
592
670
  } catch (error) {
@@ -705,10 +783,14 @@ var ApiHandlers = class {
705
783
  this.ctx.console.addListener("send-message", async (data) => {
706
784
  try {
707
785
  this.logInfo("收到发送消息请求:", data);
708
- const bot = this.ctx.bots.find((bot2) => bot2.selfId === data.selfId);
786
+ const bot = this.ctx.bots.find((bot2) => bot2.selfId === data.selfId || bot2.user?.id === data.selfId);
709
787
  if (!bot) {
710
- this.logger.error("未找到机器人:", data.selfId);
711
- return { success: false, error: "未找到指定的机器人" };
788
+ this.logger.error("未找到机器人:", data.selfId, "当前可用机器人:", this.ctx.bots.map((b) => b.selfId));
789
+ return { success: false, error: `未找到机器人 ${data.selfId},请检查机器人是否在线` };
790
+ }
791
+ if (bot.status !== import_koishi.Universal.Status.ONLINE) {
792
+ this.logger.error("机器人离线:", data.selfId, "状态:", bot.status);
793
+ return { success: false, error: `机器人 ${data.selfId} 当前离线` };
712
794
  }
713
795
  let messageContent = data.content;
714
796
  if (data.images && data.images.length > 0) {
@@ -731,31 +813,23 @@ var ApiHandlers = class {
731
813
  this.logInfo("消息发送成功:", result);
732
814
  const messageId = Array.isArray(result) ? result[0] : result;
733
815
  if (messageId) {
734
- const bot2 = this.ctx.bots.find((b) => b.selfId === data.selfId);
735
- const botMessageEvent = {
736
- type: "bot-message-sent",
737
- selfId: data.selfId,
738
- platform: bot2?.platform || "unknown",
739
- channelId: data.channelId,
740
- messageId,
741
- content: messageContent,
742
- userId: data.selfId,
743
- username: bot2?.user?.name || `Bot-${data.selfId}`,
744
- avatar: bot2?.user?.avatar,
745
- timestamp: Date.now(),
746
- guildName: "",
747
- // 这个信息在前端会补充
748
- channelType: 0,
749
- // 这个信息在前端会补充
750
- elements: [],
751
- // 这个信息在前端会补充
752
- isDirect: false
753
- // 这个信息在前端会补充
754
- };
755
- this.ctx.console.broadcast("bot-message-sent-event", botMessageEvent);
816
+ const chatData = this.fileManager.readChatDataFromFile();
817
+ const channelKey = `${data.selfId}:${data.channelId}`;
818
+ const messages = chatData.messages[channelKey] || [];
819
+ const msg = [...messages].reverse().find((m) => m.type === "bot" && m.sending);
820
+ if (msg) {
821
+ msg.realId = messageId;
822
+ msg.sending = false;
823
+ this.fileManager.writeChatDataToFile(chatData);
824
+ this.ctx.console.broadcast("bot-message-updated", {
825
+ channelKey,
826
+ tempId: msg.id,
827
+ realId: messageId
828
+ });
829
+ }
756
830
  }
757
831
  return {
758
- success: true,
832
+ success: !!messageId,
759
833
  messageId,
760
834
  tempImageIds: data.images?.map((img) => img.tempId) || []
761
835
  };
@@ -912,7 +986,7 @@ var ApiHandlers = class {
912
986
  config: {
913
987
  maxMessagesPerChannel: this.config.maxMessagesPerChannel,
914
988
  keepMessagesOnClear: this.config.keepMessagesOnClear,
915
- keepTempImages: this.config.keepTempImages,
989
+ maxPersistImages: this.config.maxPersistImages,
916
990
  loggerinfo: this.config.loggerinfo,
917
991
  blockedPlatforms: this.config.blockedPlatforms || [],
918
992
  clearIndexedDBOnStart: this.config.clearIndexedDBOnStart
@@ -923,6 +997,64 @@ var ApiHandlers = class {
923
997
  return { success: false, error: error?.message || String(error) };
924
998
  }
925
999
  });
1000
+ this.ctx.console.addListener("get-user-info", async (data) => {
1001
+ try {
1002
+ const bot = this.ctx.bots.find((b) => b.selfId === data.selfId);
1003
+ if (!bot) return { success: false, error: "机器人不存在" };
1004
+ if (!bot.getUser || typeof bot.getUser !== "function") {
1005
+ return { success: false, error: "此平台不支持查看用户信息" };
1006
+ }
1007
+ const user = await bot.getUser(data.userId, data.guildId);
1008
+ if (user) {
1009
+ if (user.avatar) {
1010
+ user.avatar = await this.messageHandler.downloadAndCacheMedia(user.avatar, "avatar");
1011
+ }
1012
+ const chatData = this.fileManager.readChatDataFromFile();
1013
+ let changed = false;
1014
+ const botChannels = chatData.channels[data.selfId] || {};
1015
+ const possibleChannelIds = [
1016
+ data.userId,
1017
+ `private:${data.userId}`,
1018
+ `direct:${data.userId}`
1019
+ ];
1020
+ for (const channelId of possibleChannelIds) {
1021
+ const channel = botChannels[channelId];
1022
+ if (channel && channel.isDirect) {
1023
+ const newName = `私聊(${user.name})`;
1024
+ if (channel.name !== newName) {
1025
+ channel.name = newName;
1026
+ changed = true;
1027
+ this.logInfo("更新私聊频道名称:", { channelId, oldName: channel.name, newName });
1028
+ }
1029
+ }
1030
+ }
1031
+ const channelKeyPrefix = `${data.selfId}:`;
1032
+ for (const [key, messages] of Object.entries(chatData.messages)) {
1033
+ if (key.startsWith(channelKeyPrefix)) {
1034
+ messages.forEach((msg) => {
1035
+ if (msg.userId === data.userId) {
1036
+ if (user.name && msg.username !== user.name) {
1037
+ msg.username = user.name;
1038
+ changed = true;
1039
+ }
1040
+ if (user.avatar && msg.avatar !== user.avatar) {
1041
+ msg.avatar = user.avatar;
1042
+ changed = true;
1043
+ }
1044
+ }
1045
+ });
1046
+ }
1047
+ }
1048
+ if (changed) {
1049
+ this.fileManager.writeChatDataToFile(chatData);
1050
+ this.ctx.console.broadcast("chat-data-updated", {});
1051
+ }
1052
+ }
1053
+ return { success: true, data: user };
1054
+ } catch (error) {
1055
+ return { success: false, error: error?.message || "获取用户信息失败" };
1056
+ }
1057
+ });
926
1058
  this.ctx.console.addListener("debug-get-raw-data", async () => {
927
1059
  try {
928
1060
  const data = this.fileManager.readChatDataFromFile();
@@ -979,61 +1111,32 @@ var ApiHandlers = class {
979
1111
  // 设置定时清理临时文件
980
1112
  setupTempFileCleanup() {
981
1113
  setInterval(() => {
982
- this.cleanupTempImagesByCount();
1114
+ this.cleanupMediaCache();
983
1115
  }, 5 * 60 * 1e3);
984
1116
  }
985
- // 基于数量清理临时图片(保留最新的N张)
986
- async cleanupTempImagesByCount() {
987
- try {
988
- const tempDir = this.ctx.baseDir + "/data/chat-patch/temp";
989
- if (!require("fs").existsSync(tempDir)) {
990
- return;
991
- }
992
- const now = Date.now();
993
- const protectionTime = 30 * 1e3;
994
- const files = require("fs").readdirSync(tempDir).filter((file) => file.startsWith("temp_")).map((file) => {
995
- const filePath = `${tempDir}/${file}`;
996
- try {
997
- const stats = require("fs").statSync(filePath);
998
- const fileAge = now - stats.mtime.getTime();
999
- return {
1000
- name: file,
1001
- path: filePath,
1002
- mtime: stats.mtime.getTime(),
1003
- age: fileAge,
1004
- protected: fileAge < protectionTime
1005
- // 是否在保护期内
1006
- };
1007
- } catch (error) {
1008
- return null;
1009
- }
1010
- }).filter((file) => file !== null).sort((a, b) => b.mtime - a.mtime);
1011
- const keepCount = this.config.keepTempImages;
1012
- let cleanedCount = 0;
1013
- let protectedCount = 0;
1014
- const protectedFiles = files.filter((file) => file.protected);
1015
- const deletableFiles = files.filter((file) => !file.protected);
1016
- protectedCount = protectedFiles.length;
1017
- if (deletableFiles.length > keepCount) {
1018
- const filesToDelete = deletableFiles.slice(keepCount);
1019
- for (const file of filesToDelete) {
1117
+ // 统一清理媒体缓存
1118
+ async cleanupMediaCache() {
1119
+ const baseDir = this.ctx.baseDir + "/data/chat-patch/persist-media";
1120
+ if (!require("node:fs").existsSync(baseDir)) return;
1121
+ const cleanupDir = /* @__PURE__ */ __name((dirName, limit) => {
1122
+ const dirPath = require("node:path").join(baseDir, dirName);
1123
+ if (!require("node:fs").existsSync(dirPath)) return;
1124
+ const files = require("node:fs").readdirSync(dirPath).map((file) => {
1125
+ const filePath = require("node:path").join(dirPath, file);
1126
+ const stats = require("node:fs").statSync(filePath);
1127
+ return { name: file, path: filePath, mtime: stats.mtimeMs };
1128
+ }).sort((a, b) => b.mtime - a.mtime);
1129
+ if (files.length > limit) {
1130
+ files.slice(limit).forEach((f) => {
1020
1131
  try {
1021
- if (require("fs").existsSync(file.path)) {
1022
- require("fs").unlinkSync(file.path);
1023
- cleanedCount++;
1024
- this.logInfo("清理多余临时图片:", file.path);
1025
- }
1026
- } catch (fileError) {
1027
- this.logger.warn("删除临时文件失败:", { file: file.name, error: fileError });
1132
+ require("node:fs").unlinkSync(f.path);
1133
+ } catch {
1028
1134
  }
1029
- }
1030
- }
1031
- if (cleanedCount > 0 || protectedCount > 0) {
1032
- this.logInfo(`基于数量清理完成,保留最新 ${keepCount} 张图片,清理了 ${cleanedCount} 张多余图片,保护了 ${protectedCount} 张新上传图片`);
1135
+ });
1033
1136
  }
1034
- } catch (error) {
1035
- this.logger.warn("基于数量清理临时文件失败:", error);
1036
- }
1137
+ }, "cleanupDir");
1138
+ cleanupDir("images", 100);
1139
+ cleanupDir("media", 20);
1037
1140
  }
1038
1141
  logInfo(...args) {
1039
1142
  if (this.config.loggerinfo) {
@@ -1046,10 +1149,9 @@ var ApiHandlers = class {
1046
1149
  var import_koishi2 = require("koishi");
1047
1150
  var Config = import_koishi2.Schema.intersect([
1048
1151
  import_koishi2.Schema.object({
1049
- maxMessagesPerChannel: import_koishi2.Schema.number().default(500).description("每个群组最大保存消息数量").min(50).max(1500),
1050
- keepMessagesOnClear: import_koishi2.Schema.number().default(50).description("手动清理历史记录时保留的消息数量").min(0).max(1e3),
1051
- keepTempImages: import_koishi2.Schema.number().default(50).description("发送消息保留的临时图片数量(最新的N张)").min(10).max(200),
1052
- maxPersistImages: import_koishi2.Schema.number().default(100).description("持久化存储的机器人发送图片数量").min(10).max(500),
1152
+ maxMessagesPerChannel: import_koishi2.Schema.number().default(500).description("每个群组最大保存消息数量").min(50).max(1500).step(1),
1153
+ keepMessagesOnClear: import_koishi2.Schema.number().default(50).description("手动清理历史记录时保留的消息数量").min(0).max(1e3).step(1),
1154
+ maxPersistImages: import_koishi2.Schema.number().default(100).description("持久化存储的图片缓存数量").min(10).max(500).step(1),
1053
1155
  blockedPlatforms: import_koishi2.Schema.array(import_koishi2.Schema.object({
1054
1156
  platformName: import_koishi2.Schema.string().description("平台名称或关键词"),
1055
1157
  exactMatch: import_koishi2.Schema.boolean().default(false).description("完全匹配?如果关闭,包含关键词即屏蔽").default(true)
@@ -0,0 +1,21 @@
1
+ import { Context, Session } from 'koishi';
2
+ import { FileManager } from './file-manager';
3
+ import { Config } from './config';
4
+ export declare class MessageHandler {
5
+ private ctx;
6
+ private config;
7
+ private fileManager;
8
+ private logger;
9
+ private utils;
10
+ private correctChannelIds;
11
+ constructor(ctx: Context, config: Config, fileManager: FileManager);
12
+ setCorrectChannelId(selfId: string, channelId: string): void;
13
+ getCorrectChannelId(selfId: string): string | undefined;
14
+ updateBotInfoToFile(session: Session): Promise<void>;
15
+ updateChannelInfoToFile(session: Session): Promise<string>;
16
+ downloadAndCacheMedia(url: string, type: 'image' | 'media' | 'avatar'): Promise<any>;
17
+ private processMediaElements;
18
+ broadcastMessageEvent(session: Session): Promise<void>;
19
+ broadcastBotMessageEvent(session: Session): Promise<void>;
20
+ private logInfo;
21
+ }