koishi-plugin-emojiluna-plus 0.0.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.
Files changed (49) hide show
  1. package/LICENSE +24 -0
  2. package/dist/index.js +10 -0
  3. package/dist/style.css +1 -0
  4. package/lib/adapters/autoCommands.d.ts +4 -0
  5. package/lib/adapters/autoCommands.js +111 -0
  6. package/lib/adapters/backend.d.ts +3 -0
  7. package/lib/adapters/backend.js +11 -0
  8. package/lib/adapters/chatlunaIntegration.d.ts +3 -0
  9. package/lib/adapters/chatlunaIntegration.js +48 -0
  10. package/lib/adapters/commands.d.ts +4 -0
  11. package/lib/adapters/commands.js +330 -0
  12. package/lib/adapters/consoleListeners.d.ts +3 -0
  13. package/lib/adapters/consoleListeners.js +168 -0
  14. package/lib/adapters/index.d.ts +2 -0
  15. package/lib/adapters/index.js +7 -0
  16. package/lib/adapters/render.d.ts +7 -0
  17. package/lib/adapters/render.js +35 -0
  18. package/lib/adapters/restApi.d.ts +3 -0
  19. package/lib/adapters/restApi.js +225 -0
  20. package/lib/collectors/autoCollector.d.ts +75 -0
  21. package/lib/collectors/autoCollector.js +728 -0
  22. package/lib/collectors/index.d.ts +1 -0
  23. package/lib/collectors/index.js +17 -0
  24. package/lib/config.d.ts +194 -0
  25. package/lib/config.js +369 -0
  26. package/lib/debug.d.ts +13 -0
  27. package/lib/debug.js +44 -0
  28. package/lib/image/imageProcessor.d.ts +20 -0
  29. package/lib/image/imageProcessor.js +243 -0
  30. package/lib/image/index.d.ts +1 -0
  31. package/lib/image/index.js +17 -0
  32. package/lib/index.d.ts +57 -0
  33. package/lib/index.js +40 -0
  34. package/lib/services/aiAnalyzer.d.ts +24 -0
  35. package/lib/services/aiAnalyzer.js +162 -0
  36. package/lib/services/emojiluna.d.ts +102 -0
  37. package/lib/services/emojiluna.js +910 -0
  38. package/lib/services/index.d.ts +2 -0
  39. package/lib/services/index.js +18 -0
  40. package/lib/storage/index.d.ts +1 -0
  41. package/lib/storage/index.js +17 -0
  42. package/lib/storage/uploadManager.d.ts +102 -0
  43. package/lib/storage/uploadManager.js +424 -0
  44. package/lib/types.d.ts +159 -0
  45. package/lib/types.js +69 -0
  46. package/lib/utils.d.ts +29 -0
  47. package/lib/utils.js +256 -0
  48. package/package.json +99 -0
  49. package/readme.md +174 -0
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .emoji-card[data-v-99429e6e]{position:relative;border-radius:8px;overflow:hidden;cursor:pointer;background:var(--k-color-surface-1);transition:all .2s ease;aspect-ratio:1}.emoji-card[data-v-99429e6e]:hover{transform:translateY(-2px);box-shadow:0 4px 12px #0000001a}.emoji-card.is-selectable[data-v-99429e6e]:hover{transform:none;box-shadow:none}.emoji-card.is-selected[data-v-99429e6e]{outline:3px solid var(--k-color-primary)}.emoji-image-container[data-v-99429e6e]{width:100%;height:100%;position:relative}.emoji-image[data-v-99429e6e]{width:100%;height:100%;object-fit:cover;display:block}.emoji-overlay[data-v-99429e6e]{position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(to bottom,#0000 50%,#000000b3);display:flex;flex-direction:column;justify-content:flex-end;padding:10px;opacity:0;transition:opacity .2s ease}.emoji-card:hover .emoji-overlay[data-v-99429e6e]{opacity:1}.overlay-actions[data-v-99429e6e]{position:absolute;top:8px;right:8px;display:flex;gap:8px}.overlay-info[data-v-99429e6e]{width:100%}.overlay-name[data-v-99429e6e]{color:#fff;font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;text-shadow:0 1px 2px rgba(0,0,0,.5)}.selection-indicator[data-v-99429e6e]{position:absolute;top:8px;right:8px;width:24px;height:24px;border-radius:50%;border:2px solid white;background-color:#0000004d;box-shadow:0 1px 3px #0003;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.emoji-card.is-selected .selection-indicator[data-v-99429e6e]{background-color:var(--k-color-primary);border-color:var(--k-color-primary)}.check-icon[data-v-99429e6e]{color:#fff;font-size:14px;font-weight:700}.status-indicator[data-v-99429e6e]{position:absolute;bottom:8px;right:8px;width:14px;height:14px;border-radius:50%;z-index:4;pointer-events:none;display:flex;align-items:center;justify-content:center}.status-indicator .status-backdrop[data-v-99429e6e]{position:absolute;width:100%;height:100%;border-radius:50%;background:#0000008c;top:0;left:0}.status-indicator .status-dot[data-v-99429e6e]{position:relative;width:8px;height:8px;border-radius:50%;border:1px solid white;box-sizing:border-box}.status-indicator[data-status=pending] .status-dot[data-v-99429e6e]{background-color:var(--status-pending-color, #ffc107);animation:status-breathing-99429e6e 2s infinite ease-in-out}.status-indicator[data-status=succeeded] .status-dot[data-v-99429e6e]{background-color:var(--status-success-color, #28a745)}.status-indicator[data-status=failed] .status-dot[data-v-99429e6e]{background-color:var(--status-error-color, #dc3545)}.status-indicator .status-symbol[data-v-99429e6e]{position:absolute;color:#fff;font-size:9px;font-weight:700;line-height:1}@keyframes status-breathing-99429e6e{0%{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.1)}to{opacity:1;transform:scale(1)}}@media (max-width: 768px){.selection-indicator[data-v-99429e6e]{width:20px;height:20px}}.dialog-content[data-v-54822f64]{padding:0 4px}.dialog-layout[data-v-54822f64]{display:flex;gap:24px}.preview-side[data-v-54822f64]{width:220px;flex-shrink:0;display:flex;flex-direction:column;gap:12px}.preview-card[data-v-54822f64]{width:100%;box-sizing:border-box;aspect-ratio:1;background:var(--k-color-surface-1);border:1px solid var(--k-color-divider);border-radius:12px;display:flex;align-items:center;justify-content:center;padding:16px;overflow:hidden}.preview-card img[data-v-54822f64]{max-width:100%;max-height:100%;object-fit:contain;transition:transform .3s ease;cursor:zoom-in}.preview-card:hover img[data-v-54822f64]{transform:scale(1.05)}.emoji-meta[data-v-54822f64]{display:flex;flex-direction:column;gap:4px;padding:0 4px}.meta-label[data-v-54822f64]{font-size:12px;color:var(--k-text-light);font-family:monospace}.meta-size[data-v-54822f64]{font-size:12px;color:var(--k-text-light);background:var(--k-color-surface-2);padding:2px 6px;border-radius:4px;align-self:flex-start}.form-side[data-v-54822f64]{flex:1;min-width:0;padding-top:4px}.form-group[data-v-54822f64]{margin-bottom:20px}.form-label[data-v-54822f64]{display:block;margin-bottom:8px;font-size:14px;color:var(--k-text-light);line-height:1.4}.dialog-footer[data-v-54822f64]{display:flex;justify-content:space-between;align-items:center;padding-top:10px}.footer-actions[data-v-54822f64]{display:flex;gap:12px}.dialog-content[data-v-7d42926d]{padding:0 4px}.mode-switcher[data-v-7d42926d]{display:flex;background:var(--k-color-surface-2);padding:4px;border-radius:12px;margin-bottom:24px;gap:4px}.mode-item[data-v-7d42926d]{flex:1;display:flex;align-items:center;justify-content:center;gap:8px;padding:10px;border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;color:var(--k-text-light);transition:all .3s cubic-bezier(.4,0,.2,1);border:1px solid transparent}.mode-item[data-v-7d42926d]:hover{color:var(--k-color-text);background:color-mix(in srgb,var(--k-color-surface-1),transparent 50%)}.mode-item.active[data-v-7d42926d]{background:var(--k-color-surface-1);color:var(--k-color-primary);box-shadow:0 2px 8px #00000014;font-weight:600;border-color:var(--k-color-border)}.mode-icon-wrapper[data-v-7d42926d]{display:flex;align-items:center;justify-content:center;font-size:18px}.upload-area-wrapper[data-v-7d42926d]{margin-bottom:24px}.custom-uploader[data-v-7d42926d] .el-upload--picture-card{width:100%;height:180px;border-radius:16px;border:2px dashed var(--k-color-divider);background:var(--k-color-surface-1);transition:all .3s cubic-bezier(.4,0,.2,1);overflow:hidden}.custom-uploader[data-v-7d42926d] .el-upload--picture-card:hover{border-color:var(--k-color-primary);background:color-mix(in srgb,var(--k-color-primary),transparent 96%)}.upload-trigger-content[data-v-7d42926d]{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;color:var(--k-text-light);width:100%;height:100%}.upload-icon-circle[data-v-7d42926d]{width:48px;height:48px;border-radius:50%;background:var(--k-color-surface-2);display:flex;align-items:center;justify-content:center;font-size:24px;color:var(--k-color-primary);transition:transform .3s ease}.custom-uploader[data-v-7d42926d] .el-upload--picture-card:hover .upload-icon-circle{transform:scale(1.1);background:var(--k-color-primary);color:#fff}.upload-text[data-v-7d42926d]{font-size:14px;font-weight:500}.form-grid[data-v-7d42926d]{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:24px}.form-group[data-v-7d42926d]{margin-bottom:20px}.form-label[data-v-7d42926d]{display:block;margin-bottom:8px;font-size:14px;font-weight:500;color:var(--k-text-light)}.form-label.required[data-v-7d42926d]:after{content:"*";color:var(--k-color-danger);margin-left:4px}.ai-switch-wrapper[data-v-7d42926d]{display:flex;justify-content:space-between;align-items:center;background:var(--k-color-surface-1);padding:12px 16px;border-radius:12px;border:1px solid var(--k-color-divider);transition:all .3s ease;margin-top:16px}.ai-switch-wrapper.active[data-v-7d42926d]{border-color:var(--k-color-primary);background:color-mix(in srgb,var(--k-color-primary),transparent 97%)}.ai-content[data-v-7d42926d]{display:flex;align-items:center;gap:12px}.ai-icon-box[data-v-7d42926d]{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#a855f7,#ec4899);display:flex;align-items:center;justify-content:center;color:#fff;font-size:16px;box-shadow:0 4px 12px #ec489933}.ai-text[data-v-7d42926d]{display:flex;flex-direction:column;gap:2px}.ai-title[data-v-7d42926d]{font-weight:600;font-size:13px;color:var(--k-color-text)}.ai-desc[data-v-7d42926d]{font-size:12px;color:var(--k-text-light);line-height:1.2}.url-preview-container[data-v-7d42926d]{width:100%;height:180px;border-radius:16px;background:var(--k-color-surface-1);border:2px dashed var(--k-color-divider);margin-bottom:24px;overflow:hidden;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.url-preview-container.has-image[data-v-7d42926d]{border-style:solid;border-color:var(--k-color-divider);background:transparent}.preview-image[data-v-7d42926d]{width:100%;height:100%;object-fit:contain;padding:12px}.preview-placeholder[data-v-7d42926d]{display:flex;flex-direction:column;align-items:center;gap:12px;color:var(--k-text-light)}.placeholder-icon[data-v-7d42926d]{width:48px;height:48px;border-radius:50%;background:var(--k-color-surface-2);display:flex;align-items:center;justify-content:center;font-size:24px}.dialog-footer[data-v-7d42926d]{display:flex;justify-content:flex-end;gap:12px;padding-top:10px}.fade-in[data-v-7d42926d]{animation:fadeIn-7d42926d .4s cubic-bezier(.4,0,.2,1)}@keyframes fadeIn-7d42926d{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.dialog-content[data-v-b6e95aac]{padding:0 4px}.form-group[data-v-b6e95aac]{margin-bottom:20px}.form-label[data-v-b6e95aac]{display:block;margin-bottom:8px;font-size:14px;font-weight:500;color:var(--k-text-light)}.form-label.required[data-v-b6e95aac]:after{content:"*";color:var(--k-color-danger);margin-left:4px}.form-hint[data-v-b6e95aac]{margin-top:6px;font-size:12px;color:var(--k-text-lighter)}.form-grid[data-v-b6e95aac]{display:grid;grid-template-columns:1fr;gap:20px;margin-bottom:20px}.scan-preview[data-v-b6e95aac]{background:var(--k-color-surface-1);border:1px solid var(--k-color-divider);border-radius:12px;padding:16px;margin-bottom:20px}.scan-header[data-v-b6e95aac]{display:flex;align-items:center;gap:8px;font-weight:600;color:var(--k-color-text);margin-bottom:12px}.subfolder-list[data-v-b6e95aac]{display:flex;flex-wrap:wrap;gap:6px}.scanning-indicator[data-v-b6e95aac]{display:flex;align-items:center;justify-content:center;gap:8px;padding:20px;color:var(--k-text-light)}.options-section[data-v-b6e95aac]{margin-bottom:20px}.option-switches[data-v-b6e95aac]{display:flex;flex-direction:column;gap:12px}.option-item[data-v-b6e95aac]{display:flex;justify-content:space-between;align-items:center;background:var(--k-color-surface-1);padding:10px 14px;border-radius:12px;border:1px solid var(--k-color-divider);transition:all .3s ease}.option-item.active[data-v-b6e95aac]{border-color:var(--k-color-primary);background:color-mix(in srgb,var(--k-color-primary),transparent 97%)}.option-item.ai-option.active[data-v-b6e95aac]{border-color:#a855f7;background:color-mix(in srgb,#a855f7,transparent 97%)}.option-content[data-v-b6e95aac]{display:flex;align-items:center;gap:12px}.option-icon[data-v-b6e95aac]{width:32px;height:32px;border-radius:8px;background:var(--k-color-surface-2);display:flex;align-items:center;justify-content:center;color:var(--k-color-primary);font-size:16px}.option-icon.ai-icon[data-v-b6e95aac]{background:linear-gradient(135deg,#a855f7,#ec4899);color:#fff}.option-text[data-v-b6e95aac]{display:flex;flex-direction:column;gap:2px}.option-title[data-v-b6e95aac]{font-weight:500;font-size:13px;color:var(--k-color-text)}.option-desc[data-v-b6e95aac]{font-size:12px;color:var(--k-text-light);line-height:1.2}.import-progress[data-v-b6e95aac]{margin-bottom:20px}.progress-text[data-v-b6e95aac]{text-align:center;margin-top:8px;font-size:13px;color:var(--k-text-light)}.import-result[data-v-b6e95aac]{background:var(--k-color-surface-1);border:1px solid var(--k-color-success);border-radius:12px;padding:16px;margin-bottom:20px}.import-result.has-errors[data-v-b6e95aac]{border-color:var(--k-color-warning)}.result-header[data-v-b6e95aac]{display:flex;align-items:center;gap:8px;font-weight:600;color:var(--k-color-success);margin-bottom:12px}.import-result.has-errors .result-header[data-v-b6e95aac],.error-icon[data-v-b6e95aac]{color:var(--k-color-warning)}.result-stats[data-v-b6e95aac]{display:flex;gap:24px;margin-bottom:12px}.result-stat[data-v-b6e95aac]{display:flex;flex-direction:column;gap:2px}.result-stat .stat-value[data-v-b6e95aac]{font-size:20px;font-weight:700}.result-stat.success .stat-value[data-v-b6e95aac]{color:var(--k-color-success)}.result-stat.warning .stat-value[data-v-b6e95aac]{color:var(--k-color-warning)}.result-stat.error .stat-value[data-v-b6e95aac]{color:var(--k-color-danger)}.result-stat .stat-label[data-v-b6e95aac]{font-size:12px;color:var(--k-text-light)}.error-list[data-v-b6e95aac]{background:color-mix(in srgb,var(--k-color-danger),transparent 94%);border-radius:8px;padding:12px;margin-top:12px}.error-item[data-v-b6e95aac]{font-size:12px;color:var(--k-color-danger);margin-bottom:4px}.error-item[data-v-b6e95aac]:last-child{margin-bottom:0}.error-more[data-v-b6e95aac]{font-size:12px;color:var(--k-text-light);margin-top:8px}.dialog-footer[data-v-b6e95aac]{display:flex;justify-content:flex-end;gap:12px;padding-top:10px}.ai-tasks-header[data-v-92bcc31c]{margin-bottom:10px}.task-emoji-img[data-v-92bcc31c]{width:32px;height:32px;object-fit:cover;border-radius:4px}.task-name[data-v-92bcc31c]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.error-text[data-v-92bcc31c]{color:var(--el-color-danger);font-size:.9em}.success-text[data-v-92bcc31c]{color:var(--el-color-success);font-size:.9em}.info-text[data-v-92bcc31c]{color:var(--el-text-color-secondary);font-size:.9em}.emoji-manager[data-v-971768de]{position:relative;min-height:100%}.toolbar-container[data-v-971768de]{position:sticky;top:0;z-index:5;background:var(--k-bg-light);background:var(--k-color-base);padding:12px 0;margin-bottom:12px;border-bottom:1px solid transparent}.toolbar-main[data-v-971768de]{display:flex;gap:12px;align-items:center}.search-section[data-v-971768de]{flex:1;max-width:400px}.search-input[data-v-971768de] .el-input__wrapper{border-radius:20px;background-color:var(--k-color-surface-1);box-shadow:none!important;border:1px solid var(--k-color-divider)}.search-input[data-v-971768de] .el-input__wrapper:hover,.search-input[data-v-971768de] .el-input__wrapper.is-focus{background-color:var(--k-color-surface-2)}.actions-section[data-v-971768de]{display:flex;gap:8px;align-items:center;margin-left:auto}.ai-status-tag[data-v-971768de]{margin-left:8px;cursor:pointer;height:32px;padding:0 12px}.ai-status-tag-content[data-v-971768de]{display:flex;align-items:center;gap:6px;font-weight:500}.ai-status-tag-counts[data-v-971768de]{display:flex;gap:8px;font-size:12px;opacity:.9}.ai-status-tag-counts .failed-count[data-v-971768de]{font-weight:700}.active-filters[data-v-971768de]{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}.emoji-grid-container[data-v-971768de]{padding-bottom:80px;min-height:200px}.emoji-grid[data-v-971768de]{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:12px;margin-bottom:20px;align-content:start}.pagination[data-v-971768de]{display:flex;justify-content:center;padding:20px 0}.floating-action-bar[data-v-971768de]{position:fixed;bottom:40px;left:50%;transform:translate(-50%);background:var(--k-color-base);border:1px solid var(--k-color-divider);border-radius:12px;padding:12px 24px;display:flex;align-items:center;gap:24px;box-shadow:0 4px 20px #00000026;z-index:100}.selection-count[data-v-971768de]{font-weight:600;color:var(--k-color-text)}.selection-actions[data-v-971768de]{display:flex;gap:12px}.slide-up-enter-active[data-v-971768de],.slide-up-leave-active[data-v-971768de]{transition:all .3s ease}.slide-up-enter-from[data-v-971768de],.slide-up-leave-to[data-v-971768de]{transform:translate(-50%,100%);opacity:0}.running-animation[data-v-971768de] .el-icon{animation:rotate-971768de 2s linear infinite;color:var(--el-color-primary)}@keyframes rotate-971768de{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preview-dialog[data-v-971768de] .el-dialog__body{padding-top:10px;padding-bottom:20px}.preview-layout[data-v-971768de]{display:flex;gap:24px}.preview-image-wrapper[data-v-971768de]{width:200px;flex-shrink:0;display:flex;flex-direction:column;gap:12px}.image-box[data-v-971768de]{width:100%;box-sizing:border-box;aspect-ratio:1;background:var(--k-color-surface-1);border:1px solid var(--k-color-divider);border-radius:16px;display:flex;align-items:center;justify-content:center;padding:16px;overflow:hidden}.preview-image[data-v-971768de]{max-width:100%;max-height:100%;object-fit:contain;transition:transform .3s ease;cursor:zoom-in}.image-box:hover .preview-image[data-v-971768de]{transform:scale(1.05)}.image-meta[data-v-971768de]{display:flex;gap:8px;flex-wrap:wrap}.meta-badge[data-v-971768de]{font-size:12px;color:var(--k-text-light);background:var(--k-color-surface-2);padding:2px 8px;border-radius:6px;font-family:monospace}.preview-details[data-v-971768de]{flex:1;min-width:0;display:flex;flex-direction:column;gap:20px;padding-top:4px}.detail-group[data-v-971768de]{display:flex;flex-direction:column;gap:8px}.detail-label[data-v-971768de]{font-size:12px;color:var(--k-text-light);font-weight:500}.detail-value[data-v-971768de]{font-size:14px;color:var(--k-color-text);line-height:1.5}.text-strong[data-v-971768de]{font-weight:600;font-size:16px}.tags-wrapper[data-v-971768de]{display:flex;flex-wrap:wrap;gap:8px}.tag-item[data-v-971768de]{margin:0!important}.link-box[data-v-971768de]{display:flex;align-items:center;justify-content:space-between;background:var(--k-color-surface-2);padding:8px 12px;border-radius:8px;cursor:pointer;transition:all .2s ease;border:1px solid transparent}.link-box[data-v-971768de]:hover{background:var(--k-color-surface-1);border-color:var(--k-color-primary)}.link-text[data-v-971768de]{font-family:monospace;font-size:12px;color:var(--k-text-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:12px}.copy-icon[data-v-971768de]{color:var(--k-text-light)}.copy-link-btn[data-v-971768de]{flex-shrink:0;padding:0 6px}.link-box:hover .copy-icon[data-v-971768de]{color:var(--k-color-primary)}.dialog-footer[data-v-971768de]{display:flex;justify-content:space-between;align-items:center;width:100%}.footer-left[data-v-971768de],.footer-right[data-v-971768de]{display:flex;gap:12px}.ai-btn[data-v-971768de]:hover{color:#ec4899}.ai-control-content[data-v-971768de]{display:flex;flex-direction:column;gap:16px}.ai-stats[data-v-971768de]{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}.stat-item[data-v-971768de]{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border:1px solid var(--k-color-divider);border-radius:8px;background:var(--k-color-surface-1)}.stat-label[data-v-971768de]{font-size:14px;color:var(--k-text-light)}.stat-value[data-v-971768de]{font-size:16px;color:var(--k-color-text);font-weight:500}.ai-config-form[data-v-971768de]{padding:12px;border:1px solid var(--k-color-divider);border-radius:8px;background:var(--k-color-surface-1)}.el-form-item[data-v-971768de]{margin-bottom:16px}@media (max-width: 768px){.emoji-grid[data-v-971768de]{grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:8px}.preview-layout[data-v-971768de]{flex-direction:column}.preview-image-wrapper[data-v-971768de]{width:100%;flex-direction:row;align-items:center}.image-box[data-v-971768de]{width:120px}}.emoji-grid-container[data-v-971768de]{position:relative;-webkit-user-select:none;user-select:none}.selection-box[data-v-971768de]{position:absolute;background-color:#409eff33;border:1px solid rgba(64,158,255,.6);z-index:1000;pointer-events:none}.tags-manager[data-v-7148289b]{min-height:100%}.toolbar-container[data-v-7148289b]{position:sticky;top:0;z-index:5;background:var(--k-color-base);padding:12px 0;margin-bottom:12px}.toolbar-main[data-v-7148289b]{display:flex;gap:12px;align-items:center}.search-section[data-v-7148289b]{flex:1;max-width:400px}.search-input[data-v-7148289b] .el-input__wrapper{border-radius:20px;background-color:var(--k-color-surface-1);box-shadow:none!important;border:1px solid transparent}.search-input[data-v-7148289b] .el-input__wrapper:hover,.search-input[data-v-7148289b] .el-input__wrapper.is-focus{background-color:var(--k-color-surface-2)}.actions-section[data-v-7148289b]{display:flex;gap:8px;align-items:center;margin-left:auto}.tags-grid[data-v-7148289b]{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:20px;padding-bottom:40px}.album-card[data-v-7148289b]{cursor:pointer;transition:transform .2s}.album-card[data-v-7148289b]:hover{transform:translateY(-4px)}.album-card.selected .album-cover[data-v-7148289b]{box-shadow:0 0 0 2px var(--k-color-primary),0 6px 12px #0000001f}.album-cover[data-v-7148289b]{width:100%;aspect-ratio:1;border-radius:12px;background-color:var(--k-color-surface-2);overflow:hidden;position:relative;box-shadow:0 4px 6px #0000000d;margin-bottom:8px;display:flex;align-items:center;justify-content:center}.cover-image[data-v-7148289b]{width:100%;height:100%;object-fit:cover}.cover-placeholder[data-v-7148289b]{color:var(--k-text-light)}.selection-badge[data-v-7148289b]{position:absolute;left:8px;top:8px;width:24px;height:24px;border-radius:50%;background:color-mix(in srgb,var(--k-color-base),transparent 8%);border:1px solid var(--k-color-divider);display:flex;align-items:center;justify-content:center;color:transparent;transition:all .2s ease}.album-card.selected .selection-badge[data-v-7148289b]{color:#fff;background:var(--k-color-primary);border-color:var(--k-color-primary)}.album-info[data-v-7148289b]{padding:0 4px}.album-name[data-v-7148289b]{font-weight:600;font-size:15px;color:var(--k-color-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:2px}.album-count[data-v-7148289b]{font-size:13px;color:var(--k-text-light)}.album-actions[data-v-7148289b]{position:absolute;top:8px;right:8px;opacity:0;transition:opacity .2s}.album-card:hover .album-actions[data-v-7148289b]{opacity:1}.action-btn[data-v-7148289b]{width:28px;height:28px;border-radius:50%;background-color:#ffffffe6;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 2px 4px #0000001a;color:var(--k-color-text)}.action-btn[data-v-7148289b]:hover{background-color:#fff;color:var(--k-color-primary)}.danger-item[data-v-7148289b]{color:var(--el-color-danger)}.no-data[data-v-7148289b]{margin-top:40px}.pagination[data-v-7148289b]{display:flex;justify-content:center;padding:20px 0}.floating-action-bar[data-v-7148289b]{position:fixed;bottom:24px;left:50%;transform:translate(-50%);background:var(--k-color-base);border:1px solid var(--k-color-divider);border-radius:12px;padding:12px 20px;display:flex;align-items:center;gap:20px;box-shadow:0 4px 20px #00000026;z-index:100}.selection-count[data-v-7148289b]{font-weight:600;color:var(--k-color-text)}.selection-actions[data-v-7148289b]{display:flex;gap:10px}.slide-up-enter-active[data-v-7148289b],.slide-up-leave-active[data-v-7148289b]{transition:all .3s ease}.slide-up-enter-from[data-v-7148289b],.slide-up-leave-to[data-v-7148289b]{transform:translate(-50%,100%);opacity:0}.categories-manager[data-v-e83bb91b]{min-height:100%}.toolbar-container[data-v-e83bb91b]{position:sticky;top:0;z-index:5;background:var(--k-color-base);padding:12px 0;margin-bottom:12px}.toolbar-main[data-v-e83bb91b]{display:flex;gap:12px;align-items:center}.search-section[data-v-e83bb91b]{flex:1;max-width:400px}.search-input[data-v-e83bb91b] .el-input__wrapper{border-radius:20px;background-color:var(--k-color-surface-1);box-shadow:none!important;border:1px solid transparent}.search-input[data-v-e83bb91b] .el-input__wrapper:hover,.search-input[data-v-e83bb91b] .el-input__wrapper.is-focus{background-color:var(--k-color-surface-2)}.actions-section[data-v-e83bb91b]{display:flex;gap:8px;align-items:center;margin-left:auto}.categories-grid[data-v-e83bb91b]{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:20px;padding-bottom:40px}.album-card[data-v-e83bb91b]{cursor:pointer;transition:transform .2s}.album-card[data-v-e83bb91b]:hover{transform:translateY(-4px)}.album-card.selected .album-cover[data-v-e83bb91b]{box-shadow:0 0 0 2px var(--k-color-primary),0 6px 12px #0000001f}.album-cover[data-v-e83bb91b]{width:100%;aspect-ratio:1;border-radius:12px;background-color:var(--k-color-surface-2);overflow:hidden;position:relative;box-shadow:0 4px 6px #0000000d;margin-bottom:8px;display:flex;align-items:center;justify-content:center}.cover-image[data-v-e83bb91b]{width:100%;height:100%;object-fit:cover}.cover-placeholder[data-v-e83bb91b]{color:var(--k-text-light)}.selection-badge[data-v-e83bb91b]{position:absolute;left:8px;top:8px;width:24px;height:24px;border-radius:50%;background:color-mix(in srgb,var(--k-color-base),transparent 8%);border:1px solid var(--k-color-divider);display:flex;align-items:center;justify-content:center;color:transparent;transition:all .2s ease}.album-card.selected .selection-badge[data-v-e83bb91b]{color:#fff;background:var(--k-color-primary);border-color:var(--k-color-primary)}.album-info[data-v-e83bb91b]{padding:0 4px}.album-name[data-v-e83bb91b]{font-weight:600;font-size:15px;color:var(--k-color-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:2px}.album-count[data-v-e83bb91b]{font-size:13px;color:var(--k-text-light)}.album-actions[data-v-e83bb91b]{position:absolute;top:8px;right:8px;opacity:0;transition:opacity .2s}.album-card:hover .album-actions[data-v-e83bb91b]{opacity:1}.action-btn[data-v-e83bb91b]{width:28px;height:28px;border-radius:50%;background-color:#ffffffe6;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 2px 4px #0000001a;color:var(--k-color-text)}.action-btn[data-v-e83bb91b]:hover{background-color:#fff;color:var(--k-color-primary)}.danger-item[data-v-e83bb91b]{color:var(--el-color-danger)}.no-data[data-v-e83bb91b]{margin-top:40px}.pagination[data-v-e83bb91b]{display:flex;justify-content:center;padding:20px 0}.floating-action-bar[data-v-e83bb91b]{position:fixed;bottom:24px;left:50%;transform:translate(-50%);background:var(--k-color-base);border:1px solid var(--k-color-divider);border-radius:12px;padding:12px 20px;display:flex;align-items:center;gap:20px;box-shadow:0 4px 20px #00000026;z-index:100}.selection-count[data-v-e83bb91b]{font-weight:600;color:var(--k-color-text)}.selection-actions[data-v-e83bb91b]{display:flex;gap:10px}.slide-up-enter-active[data-v-e83bb91b],.slide-up-leave-active[data-v-e83bb91b]{transition:all .3s ease}.slide-up-enter-from[data-v-e83bb91b],.slide-up-leave-to[data-v-e83bb91b]{transform:translate(-50%,100%);opacity:0}.selector-container[data-v-0f33e75c]{height:60vh;display:flex;flex-direction:column}.selector-toolbar[data-v-0f33e75c]{display:flex;gap:12px;margin-bottom:16px}.selector-grid[data-v-0f33e75c]{flex:1;overflow-y:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:12px;padding:4px;align-content:start;position:relative;-webkit-user-select:none;user-select:none}.selection-box[data-v-0f33e75c]{position:absolute;background-color:#409eff33;border:1px solid rgba(64,158,255,.6);z-index:1000;pointer-events:none}.selector-item[data-v-0f33e75c]{height:100px}.selector-pagination[data-v-0f33e75c]{display:flex;justify-content:center;padding-top:12px}.dialog-footer[data-v-0f33e75c]{display:flex;justify-content:space-between;align-items:center}.selection-info[data-v-0f33e75c]{font-weight:500;color:var(--k-color-primary)}.category-detail[data-v-e2b51de4]{min-height:100%}.detail-header[data-v-e2b51de4]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding:16px;background:var(--k-color-base);position:sticky;top:0;z-index:10}.header-left[data-v-e2b51de4]{display:flex;align-items:center;gap:16px}.header-title[data-v-e2b51de4]{display:flex;flex-direction:column}.title-text[data-v-e2b51de4]{margin:0;font-size:18px;font-weight:600;color:var(--k-color-text)}.subtitle-text[data-v-e2b51de4]{font-size:12px;color:var(--k-text-light)}.header-right[data-v-e2b51de4]{display:flex;gap:8px;align-items:center}.toolbar-container[data-v-e2b51de4]{padding:0 16px 16px;display:flex;gap:12px;align-items:center}.search-section[data-v-e2b51de4]{flex:1;max-width:400px}.search-input[data-v-e2b51de4] .el-input__wrapper{border-radius:20px;background-color:var(--k-color-surface-1);box-shadow:none!important;border:1px solid transparent}.search-input[data-v-e2b51de4] .el-input__wrapper:hover,.search-input[data-v-e2b51de4] .el-input__wrapper.is-focus{background-color:var(--k-color-surface-2)}.actions-section[data-v-e2b51de4]{display:flex;gap:8px;align-items:center;margin-left:auto}.emoji-grid-container[data-v-e2b51de4]{padding-bottom:80px;min-height:200px}.emoji-grid[data-v-e2b51de4]{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:12px;margin-bottom:20px;align-content:start}.pagination[data-v-e2b51de4]{display:flex;justify-content:center;padding:20px 0}.floating-action-bar[data-v-e2b51de4]{position:fixed;bottom:24px;left:50%;transform:translate(-50%);background:var(--k-color-base);border:1px solid var(--k-color-divider);border-radius:12px;padding:12px 24px;display:flex;align-items:center;gap:24px;box-shadow:0 4px 20px #00000026;z-index:100}.selection-count[data-v-e2b51de4]{font-weight:600;color:var(--k-color-text)}.selection-actions[data-v-e2b51de4]{display:flex;gap:12px}.slide-up-enter-active[data-v-e2b51de4],.slide-up-leave-active[data-v-e2b51de4]{transition:all .3s ease}.slide-up-enter-from[data-v-e2b51de4],.slide-up-leave-to[data-v-e2b51de4]{transform:translate(-50%,100%);opacity:0}.preview-content[data-v-e2b51de4]{display:flex;flex-direction:column;gap:20px}.preview-image-container[data-v-e2b51de4]{display:flex;justify-content:center;align-items:center;padding:20px;background:var(--k-color-surface-1);border-radius:6px;border:1px solid var(--k-border-color)}.preview-image[data-v-e2b51de4]{max-width:200px;max-height:200px;border-radius:4px;object-fit:contain;cursor:zoom-in}.preview-info[data-v-e2b51de4]{display:flex;flex-direction:column;gap:12px}.info-item[data-v-e2b51de4]{display:flex;align-items:flex-start;gap:8px}.info-label[data-v-e2b51de4]{font-weight:600;color:var(--k-text-normal);min-width:50px;flex-shrink:0}.info-value[data-v-e2b51de4]{flex:1;color:var(--k-text-light)}.tag-item[data-v-e2b51de4]{margin-right:6px;margin-bottom:4px}.link-input[data-v-e2b51de4]{flex:1}.dialog-footer[data-v-e2b51de4]{display:flex;gap:10px;justify-content:flex-end}@media (max-width: 768px){.emoji-grid[data-v-e2b51de4]{grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:8px}}.emoji-grid-container[data-v-e2b51de4]{position:relative;-webkit-user-select:none;user-select:none}.selection-box[data-v-e2b51de4]{position:absolute;background-color:#409eff33;border:1px solid rgba(64,158,255,.6);z-index:1000;pointer-events:none}.tag-detail[data-v-2beab8ff]{min-height:100%}.detail-header[data-v-2beab8ff]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding:16px;background:var(--k-color-base);position:sticky;top:0;z-index:10}.header-left[data-v-2beab8ff]{display:flex;align-items:center;gap:16px}.header-title[data-v-2beab8ff]{display:flex;flex-direction:column}.title-text[data-v-2beab8ff]{margin:0;font-size:18px;font-weight:600;color:var(--k-color-text)}.subtitle-text[data-v-2beab8ff]{font-size:12px;color:var(--k-text-light)}.header-right[data-v-2beab8ff]{display:flex;gap:8px;align-items:center}.toolbar-container[data-v-2beab8ff]{padding:0 16px 16px;display:flex;gap:12px;align-items:center}.search-section[data-v-2beab8ff]{flex:1;max-width:400px}.search-input[data-v-2beab8ff] .el-input__wrapper{border-radius:20px;background-color:var(--k-color-surface-1);box-shadow:none!important;border:1px solid transparent}.search-input[data-v-2beab8ff] .el-input__wrapper:hover,.search-input[data-v-2beab8ff] .el-input__wrapper.is-focus{background-color:var(--k-color-surface-2)}.actions-section[data-v-2beab8ff]{display:flex;gap:8px;align-items:center;margin-left:auto}.emoji-grid-container[data-v-2beab8ff]{padding-bottom:80px;min-height:200px}.emoji-grid[data-v-2beab8ff]{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:12px;margin-bottom:20px;align-content:start}.pagination[data-v-2beab8ff]{display:flex;justify-content:center;padding:20px 0}.floating-action-bar[data-v-2beab8ff]{position:fixed;bottom:24px;left:50%;transform:translate(-50%);background:var(--k-color-surface-1);border:1px solid var(--k-color-divider);border-radius:12px;padding:12px 24px;display:flex;align-items:center;gap:24px;box-shadow:0 4px 20px #00000026;z-index:100}.selection-count[data-v-2beab8ff]{font-weight:600;color:var(--k-color-text)}.selection-actions[data-v-2beab8ff]{display:flex;gap:12px}.slide-up-enter-active[data-v-2beab8ff],.slide-up-leave-active[data-v-2beab8ff]{transition:all .3s ease}.slide-up-enter-from[data-v-2beab8ff],.slide-up-leave-to[data-v-2beab8ff]{transform:translate(-50%,100%);opacity:0}.preview-content[data-v-2beab8ff]{display:flex;flex-direction:column;gap:20px}.preview-image-container[data-v-2beab8ff]{display:flex;justify-content:center;align-items:center;padding:20px;background:var(--k-color-surface-1);border-radius:6px;border:1px solid var(--k-border-color)}.preview-image[data-v-2beab8ff]{max-width:200px;max-height:200px;border-radius:4px;object-fit:contain;cursor:zoom-in}.preview-info[data-v-2beab8ff]{display:flex;flex-direction:column;gap:12px}.info-item[data-v-2beab8ff]{display:flex;align-items:flex-start;gap:8px}.info-label[data-v-2beab8ff]{font-weight:600;color:var(--k-text-normal);min-width:50px;flex-shrink:0}.info-value[data-v-2beab8ff]{flex:1;color:var(--k-text-light)}.tag-item[data-v-2beab8ff]{margin-right:6px;margin-bottom:4px}.dialog-footer[data-v-2beab8ff]{display:flex;gap:10px;justify-content:flex-end}@media (max-width: 768px){.emoji-grid[data-v-2beab8ff]{grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:8px}}.emoji-grid-container[data-v-2beab8ff]{position:relative;-webkit-user-select:none;user-select:none}.selection-box[data-v-2beab8ff]{position:absolute;background-color:#409eff33;border:1px solid rgba(64,158,255,.6);z-index:1000;pointer-events:none}.dashboard-container[data-v-08fd636d]{position:relative;height:100vh;background-color:var(--k-color-base);color:var(--k-color-text);overflow:hidden}.main-content[data-v-08fd636d]{height:100%;width:100%}.content-wrapper[data-v-08fd636d]{padding:24px 80px 24px 24px;max-width:1600px;margin:0 auto}.view-container[data-v-08fd636d]{min-height:500px}.side-nav[data-v-08fd636d]{position:fixed;right:24px;top:50%;transform:translateY(-50%);background:color-mix(in srgb,var(--k-color-surface-1),transparent 20%);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid var(--k-color-divider);border-radius:16px;padding:12px;z-index:100;box-shadow:0 4px 24px #00000014;transition:all .3s cubic-bezier(.4,0,.2,1);width:42px;overflow:hidden}.side-nav[data-v-08fd636d]:hover{width:180px}.nav-segment[data-v-08fd636d]{display:flex;flex-direction:column;gap:12px}.nav-item[data-v-08fd636d]{height:40px;border-radius:10px;display:flex;align-items:center;padding:0 8px;cursor:pointer;color:var(--k-text-light);transition:all .2s ease;white-space:nowrap;position:relative}.nav-item[data-v-08fd636d]:hover{background-color:var(--k-hover-bg);color:var(--k-color-text)}.nav-item.active[data-v-08fd636d]{background-color:var(--k-color-primary);color:#fff;box-shadow:0 2px 8px rgba(var(--k-color-primary-rgb),.3)}.nav-item .el-icon[data-v-08fd636d]{flex-shrink:0;margin:0 auto;transition:margin .3s ease}.side-nav:hover .nav-item .el-icon[data-v-08fd636d]{margin:0 12px 0 0}.nav-label[data-v-08fd636d]{opacity:0;transform:translate(10px);transition:all .3s ease;font-size:14px;font-weight:500}.side-nav:hover .nav-label[data-v-08fd636d]{opacity:1;transform:translate(0)}@media (max-width: 768px){.content-wrapper[data-v-08fd636d]{padding:16px 16px 80px}.side-nav[data-v-08fd636d]{top:auto;bottom:20px;right:50%;transform:translate(50%);width:auto;flex-direction:row;padding:8px 16px;border-radius:30px}.side-nav[data-v-08fd636d]:hover{width:auto}.nav-segment[data-v-08fd636d]{flex-direction:row;gap:20px}.nav-item[data-v-08fd636d]{padding:0;height:auto;background:transparent!important;box-shadow:none!important;color:var(--k-text-light)}.nav-item.active[data-v-08fd636d]{color:var(--k-color-primary)}.nav-label[data-v-08fd636d]{display:none}.nav-item .el-icon[data-v-08fd636d]{margin:0}}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.grid{display:grid}.inline{display:inline}.block{display:block}.hidden{display:none}.h2{height:.5rem}.flex{display:flex}.flex-shrink{flex-shrink:1}.flex-wrap{flex-wrap:wrap}.transform{transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.border{border-width:1px}.rounded{border-radius:.25rem}.px{padding-left:1rem;padding-right:1rem}.tab{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.text-shadow{--un-text-shadow:0 0 1px var(--un-text-shadow-color, rgb(0 0 0 / .2)),0 0 1px var(--un-text-shadow-color, rgb(1 0 5 / .1));text-shadow:var(--un-text-shadow)}.outline{outline-style:solid}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.ease,.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}
@@ -0,0 +1,4 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from '../config';
3
+ import { AutoCollector } from '../collectors';
4
+ export declare function registerAutoCollectCommands(ctx: Context, config: Config, autoCollector: AutoCollector): void;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerAutoCollectCommands = registerAutoCollectCommands;
4
+ const koishi_1 = require("koishi");
5
+ const render_1 = require("./render");
6
+ const RECENT_RECORDS = 6;
7
+ const DEBUG_LINES = 15;
8
+ function registerAutoCollectCommands(ctx, config, autoCollector) {
9
+ const emojiluna = ctx.emojiluna;
10
+ ctx.command('emojiluna.auto', '自动获取表情包')
11
+ .action(() => '可用子命令: status / probe / toggle / reset');
12
+ ctx.command('emojiluna.auto.status', '查看自动获取状态与拦截统计').action(() => formatStatus(config, autoCollector));
13
+ ctx.command('emojiluna.auto.probe', '逐闸门判定本条或引用消息中的图片')
14
+ .option('save', '-s 判定通过后实际入库')
15
+ .action(async ({ session, options }) => {
16
+ const images = pickImages(session);
17
+ if (!images.length) {
18
+ return '本条消息中没有图片。请发送“图片 + 本指令”,或引用一条带图片的消息再执行。';
19
+ }
20
+ const trace = await autoCollector.probe(session, !options.save, images);
21
+ return [
22
+ options.save
23
+ ? '自动获取判定(允许实际入库)'
24
+ : '自动获取判定(试运行,加 -s 才会入库)',
25
+ ...formatTrace(trace),
26
+ ].join('\n');
27
+ });
28
+ ctx.command('emojiluna.auto.toggle [state:string]', '临时开启或关闭自动获取(on/off/auto)').action((_, state) => {
29
+ const value = (state ?? '').toLowerCase();
30
+ if (['on', '开', 'true', '1'].includes(value)) {
31
+ autoCollector.setEnabled(true);
32
+ return '自动获取已临时开启(热重载或配置更新后回到配置值)';
33
+ }
34
+ if (['off', '关', 'false', '0'].includes(value)) {
35
+ autoCollector.setEnabled(false);
36
+ return '自动获取已临时关闭(热重载或配置更新后回到配置值)';
37
+ }
38
+ if (!value || ['auto', '配置'].includes(value)) {
39
+ autoCollector.setEnabled(null);
40
+ return `已恢复跟随配置:${config.autoCollect ? '开启' : '关闭'}`;
41
+ }
42
+ return '状态只能是 on / off / auto';
43
+ });
44
+ ctx.command('emojiluna.auto.reset', '清零统计与限流计数').action(() => {
45
+ autoCollector.resetCounters();
46
+ return '统计、限流计数与调试日志已清零';
47
+ });
48
+ ctx.command('emojiluna.debug', '查看调试日志')
49
+ .option('lines', '-l <lines:number> 显示行数', { fallback: DEBUG_LINES })
50
+ .action(({ options }) => {
51
+ if (!config.debug) {
52
+ return '调试日志未开启,请在配置项「调试配置」中打开 debug(或在控制台执行 emojiluna.debug 前先启用)。';
53
+ }
54
+ const limit = Math.max(1, Math.min(Number(options.lines) || DEBUG_LINES, config.logLimit));
55
+ const records = emojiluna.debug.recent(limit);
56
+ return records.length
57
+ ? `调试日志 (最近 ${records.length} 条):\n${records.map((line) => ` - ${(0, render_1.truncate)(line, 160)}`).join('\n')}`
58
+ : '调试日志为空(尚未有匹配的调试事件)';
59
+ });
60
+ }
61
+ function pickImages(session) {
62
+ const direct = koishi_1.h.select(session.elements ?? [], 'img');
63
+ if (direct.length)
64
+ return direct;
65
+ return koishi_1.h.select(session.quote?.elements ?? [], 'img');
66
+ }
67
+ function formatTrace(trace) {
68
+ return trace.map((step) => `${step.ok ? '[通过]' : '[拦截]'} ${step.gate}:${step.detail}`);
69
+ }
70
+ function formatStatus(config, autoCollector) {
71
+ const stats = autoCollector.stats();
72
+ const scope = config.groupScope === 'whitelist'
73
+ ? `群聊仅白名单(${config.whitelistGroups.length} 个)`
74
+ : config.groupScope === 'blacklist'
75
+ ? `群聊排除黑名单(${config.blacklistGroups.length} 个)`
76
+ : '群聊为所有群';
77
+ const lines = [
78
+ '自动获取状态',
79
+ `运行: ${stats.enabled ? '开启' : '关闭'}(配置 ${stats.configured ? '开启' : '关闭'})`,
80
+ `范围: ${scope} | 私聊 ${config.collectDirect ? '开启' : '关闭'}`,
81
+ `模式: ${stats.mode === 'instant' ? '出现即收集' : `窗口 ${config.frequencyWindow} 分钟内满 ${config.emojiFrequencyThreshold} 次`}`,
82
+ `条件: ${config.minEmojiSize}KB-${config.maxEmojiSize}MB${config.minEdgePixels ? ` | 短边≥${config.minEdgePixels}px` : ''} | 相似度阈值 ${config.similarityThreshold}`,
83
+ `取源: HTTP ${config.fetchTimeout}ms 超时 | 本地路径 ${config.allowLocalPaths ? '允许' : '禁止'}${config.localPathRoots.length ? `(限定 ${config.localPathRoots.length} 个目录)` : ''}`,
84
+ `AI: 类型过滤 ${config.enableImageTypeFilter ? `开启(超时 ${config.aiFilterTimeout}ms,兜底 ${config.aiFilterFallback})` : '关闭'} | 入库后分析 ${config.autoAnalyze ? '开启' : '关闭'}`,
85
+ `限流: 默认单会话 ${defaultHourLimit(config)}/小时、${defaultDayLimit(config)}/日 | 全局 ${config.globalDayLimit || '不限'}/日 | 库存上限 ${config.maxEmojiCount}`,
86
+ `统计: 收到 ${stats.seen} 张 | 成功 ${stats.collected} 张 | 队列 ${stats.queue}/${config.autoCollectQueueSize} | 处理中 ${stats.active} | 特征 ${stats.signatures}${stats.preloaded ? '' : '(预热中)'}`,
87
+ ];
88
+ const rejected = Object.entries(stats.rejected).sort((a, b) => b[1] - a[1]);
89
+ if (rejected.length) {
90
+ lines.push(`拦截: ${rejected.map(([gate, count]) => `${gate} ${count}`).join(' | ')}`);
91
+ }
92
+ if (stats.recent.length) {
93
+ lines.push('最近记录:');
94
+ for (const text of stats.recent.slice(-RECENT_RECORDS)) {
95
+ lines.push(` - ${(0, render_1.truncate)(text, 160)}`);
96
+ }
97
+ }
98
+ if (config.debug) {
99
+ lines.push(`提示: 调试日志已开启,使用 emojiluna.debug 查看最近 ${config.logLimit} 条。`);
100
+ }
101
+ return lines.join('\n');
102
+ }
103
+ function defaultHourLimit(config) {
104
+ return firstQuota(config)?.hourLimit ?? 20;
105
+ }
106
+ function defaultDayLimit(config) {
107
+ return firstQuota(config)?.dayLimit ?? 100;
108
+ }
109
+ function firstQuota(config) {
110
+ return Object.values(config.groupAutoCollectLimit ?? {})[0];
111
+ }
@@ -0,0 +1,3 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from '../config';
3
+ export declare function applyBackend(ctx: Context, config: Config): Promise<void>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyBackend = applyBackend;
4
+ const chatlunaIntegration_1 = require("./chatlunaIntegration");
5
+ const consoleListeners_1 = require("./consoleListeners");
6
+ const restApi_1 = require("./restApi");
7
+ async function applyBackend(ctx, config) {
8
+ (0, chatlunaIntegration_1.applyChatlunaIntegration)(ctx, config);
9
+ (0, consoleListeners_1.applyConsoleListeners)(ctx, config);
10
+ (0, restApi_1.applyRestApi)(ctx, config);
11
+ }
@@ -0,0 +1,3 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from '../config';
3
+ export declare function applyChatlunaIntegration(ctx: Context, config: Config): void;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyChatlunaIntegration = applyChatlunaIntegration;
4
+ function applyChatlunaIntegration(ctx, config) {
5
+ if (!config.injectVariables)
6
+ return;
7
+ if (!config.backendServer) {
8
+ ctx.emojiluna.debug.log('ai', '未启用后端服务器,表情包 URL 无法被模型访问,已跳过 {emojis} 变量注入');
9
+ return;
10
+ }
11
+ ctx.inject(['server', 'chatluna', 'emojiluna'], async (ctx) => {
12
+ const selfUrl = config.selfUrl || ctx.server.selfUrl || '';
13
+ const baseUrl = selfUrl + config.backendPath;
14
+ await ctx.emojiluna.ready;
15
+ const escapeMarkdown = (text) => text.replace(/([\[\]\(\)])/g, '\\$1');
16
+ const refreshPromptVariable = async () => {
17
+ try {
18
+ const emojis = await ctx.emojiluna.getEmojiList({
19
+ limit: config.injectVariablesLimit
20
+ });
21
+ if (!emojis.length) {
22
+ ctx.chatluna.promptRenderer.setVariable('emojis', '');
23
+ ctx.emojiluna.debug.log('ai', '变量注入:库内暂无表情包');
24
+ return;
25
+ }
26
+ const emojiList = emojis
27
+ .map((emoji) => {
28
+ const emojiUrl = `${baseUrl}/get/${encodeURIComponent(emoji.id)}`;
29
+ const tags = emoji.tags.join(', ');
30
+ return `- [${escapeMarkdown(emoji.name)}](${emojiUrl}) - 分类: ${emoji.category}, 标签: ${tags}`;
31
+ })
32
+ .join('\n');
33
+ const promptContent = config.injectVariablesPrompt.replace('{emojis}', emojiList);
34
+ ctx.chatluna.promptRenderer.setVariable('emojis', promptContent);
35
+ ctx.emojiluna.debug.log('ai', `变量注入:${emojis.length} 个表情包,${promptContent.length} 字符`);
36
+ }
37
+ catch (error) {
38
+ ctx.logger.warn(`刷新 emojiluna 变量失败: ${error.message}`);
39
+ }
40
+ };
41
+ await refreshPromptVariable();
42
+ ctx.setInterval(() => refreshPromptVariable(), 1000 * 60 * 5);
43
+ ctx.on('emojiluna/emoji-added', () => refreshPromptVariable());
44
+ ctx.on('emojiluna/emoji-updated', () => refreshPromptVariable());
45
+ ctx.on('emojiluna/emoji-deleted', () => refreshPromptVariable());
46
+ ctx.effect(() => () => ctx.chatluna.promptRenderer.removeVariable('emojis'));
47
+ });
48
+ }
@@ -0,0 +1,4 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from '../config';
3
+ import { AutoCollector } from '../collectors';
4
+ export declare function applyCommands(ctx: Context, config: Config, autoCollector: AutoCollector): void;
@@ -0,0 +1,330 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyCommands = applyCommands;
4
+ const koishi_1 = require("koishi");
5
+ const utils_1 = require("../utils");
6
+ const autoCommands_1 = require("./autoCommands");
7
+ const render_1 = require("./render");
8
+ const DEFAULT_LIST_LIMIT = 10;
9
+ const MAX_INLINE_IMAGES = 5;
10
+ const MAX_PAGE_SIZE = 50;
11
+ const TRIGGER_MATCH_MIN_LENGTH = 2;
12
+ function applyCommands(ctx, config, autoCollector) {
13
+ const emojiluna = ctx.emojiluna;
14
+ registerTriggerMiddleware(ctx, config);
15
+ registerLibraryCommands(ctx, config, emojiluna);
16
+ registerCategoryCommands(ctx, emojiluna);
17
+ registerTagCommands(ctx, emojiluna);
18
+ registerAiCommands(ctx, config, emojiluna);
19
+ (0, autoCommands_1.registerAutoCollectCommands)(ctx, config, autoCollector);
20
+ }
21
+ function registerTriggerMiddleware(ctx, config) {
22
+ ctx.middleware(async (session, next) => {
23
+ if (!config.triggerWithName)
24
+ return next();
25
+ const content = session.content.trim();
26
+ if (content.length < TRIGGER_MATCH_MIN_LENGTH)
27
+ return next();
28
+ const emoji = await ctx.emojiluna.getEmojiByName(content);
29
+ if (!emoji)
30
+ return next();
31
+ return next(async () => (0, render_1.emojiMessage)(ctx, config, emoji));
32
+ });
33
+ }
34
+ function registerLibraryCommands(ctx, config, emojiluna) {
35
+ ctx.command('emojiluna', '表情包管理');
36
+ ctx.command('emojiluna.get <name:string>', '获取指定表情包').action(async (_, name) => {
37
+ if (!name)
38
+ return '请输入表情包名称';
39
+ const emoji = await emojiluna.getEmojiByName(name);
40
+ if (!emoji)
41
+ return '表情包不存在';
42
+ return (0, render_1.emojiMessage)(ctx, config, emoji);
43
+ });
44
+ ctx.command('emojiluna.add <name:string>', '添加表情包')
45
+ .option('category', '-c <category:string> 指定分类')
46
+ .option('tags', '-t <tags:string> 添加标签,用逗号分隔')
47
+ .option('no-ai', '-n 禁用AI分析')
48
+ .action(async ({ session, options }, name) => {
49
+ if (!name)
50
+ return '请输入表情包名称';
51
+ try {
52
+ const result = await (0, utils_1.handleImageUpload)(session, '', async (imageData) => {
53
+ if (imageData.length === 0)
54
+ return '请上传图片';
55
+ const tags = splitList(options.tags);
56
+ const emoji = await emojiluna.addEmoji({ name, category: options.category, tags }, imageData[0], !options['no-ai']);
57
+ return [
58
+ `表情包 "${emoji.name}" 添加成功!ID: ${emoji.id}`,
59
+ `分类: ${emoji.category}`,
60
+ `标签: ${emoji.tags.join(', ') || '无'}`,
61
+ options['no-ai']
62
+ ? '未启用 AI 分析'
63
+ : '已加入 AI 分析队列,稍后自动更新名称与标签',
64
+ ].join('\n');
65
+ });
66
+ return result;
67
+ }
68
+ catch (error) {
69
+ return `添加失败: ${error.message}`;
70
+ }
71
+ });
72
+ ctx.command('emojiluna.list', '查看表情包列表')
73
+ .option('category', '-c <category:string> 按分类筛选')
74
+ .option('tags', '-t <tags:string> 按标签筛选,用逗号分隔')
75
+ .option('limit', '-l <limit:number> 限制显示数量', {
76
+ fallback: DEFAULT_LIST_LIMIT,
77
+ })
78
+ .option('offset', '-o <offset:number> 偏移量', { fallback: 0 })
79
+ .option('text', '-T 只显示文字,不内联图片')
80
+ .action(async ({ options }) => {
81
+ const { limit, offset } = normalizePage(options);
82
+ const emojis = await emojiluna.getEmojiList({
83
+ category: options.category,
84
+ tags: splitList(options.tags),
85
+ limit,
86
+ offset,
87
+ });
88
+ if (!emojis.length)
89
+ return '没有找到表情包';
90
+ return renderEmojiPage(ctx, config, {
91
+ title: `表情包列表 (${emojis.length}/${emojiluna.getEmojiCount()},第 ${offset + 1} 起)`,
92
+ emojis,
93
+ offset,
94
+ inlineImages: !options.text,
95
+ });
96
+ });
97
+ ctx.command('emojiluna.search <keyword:string>', '搜索表情包')
98
+ .option('limit', '-l <limit:number> 限制显示数量', {
99
+ fallback: DEFAULT_LIST_LIMIT,
100
+ })
101
+ .option('offset', '-o <offset:number> 偏移量', { fallback: 0 })
102
+ .option('text', '-T 只显示文字,不内联图片')
103
+ .action(async ({ options }, keyword) => {
104
+ if (!keyword)
105
+ return '请输入搜索关键词';
106
+ const { limit, offset } = normalizePage(options);
107
+ const matched = await emojiluna.searchEmoji(keyword);
108
+ if (!matched.length)
109
+ return `没有找到包含 "${keyword}" 的表情包`;
110
+ const emojis = matched.slice(offset, offset + limit);
111
+ return renderEmojiPage(ctx, config, {
112
+ title: `搜索结果 "${keyword}" (${matched.length} 个,显示 ${emojis.length} 个)`,
113
+ emojis,
114
+ offset,
115
+ inlineImages: !options.text,
116
+ });
117
+ });
118
+ ctx.command('emojiluna.delete <id:string>', '删除表情包').action(async (_, id) => {
119
+ if (!id)
120
+ return '请输入表情包ID';
121
+ const emoji = await emojiluna.getEmojiById(id);
122
+ if (!emoji)
123
+ return '表情包不存在';
124
+ const success = await emojiluna.deleteEmoji(id);
125
+ return success
126
+ ? `已删除表情包 "${emoji.name}"`
127
+ : '删除失败,请查看日志';
128
+ });
129
+ ctx.command('emojiluna.wipe', '删除所有表情包')
130
+ .option('yes', '-y 确认清空')
131
+ .action(async ({ options }) => {
132
+ const count = emojiluna.getEmojiCount();
133
+ if (!count)
134
+ return '表情包库已经是空的';
135
+ if (!options.yes) {
136
+ return [
137
+ `将删除全部 ${count} 个表情包,此操作不可撤销。`,
138
+ `确认请发送:emojiluna.wipe -y`,
139
+ ].join('\n');
140
+ }
141
+ const success = await emojiluna.deleteAllEmojis();
142
+ return success
143
+ ? `已删除 ${count} 个表情包`
144
+ : '部分表情包删除失败,请查看日志';
145
+ });
146
+ ctx.command('emojiluna.info', '查看插件信息').action(async () => {
147
+ const tags = await emojiluna.getAllTags();
148
+ const lines = [
149
+ '表情包管理插件信息:',
150
+ `表情包数量: ${emojiluna.getEmojiCount()}/${config.maxEmojiCount}`,
151
+ `分类数量: ${emojiluna.getCategoryCount()}`,
152
+ `标签数量: ${tags.length}`,
153
+ `存储目录: ${emojiluna.storageDir}`,
154
+ '',
155
+ 'AI功能:',
156
+ `自动分类: ${flag(config.autoCategorize)}`,
157
+ `自动分析: ${flag(config.autoAnalyze)}`,
158
+ `图片类型过滤: ${flag(config.enableImageTypeFilter)}`,
159
+ `使用模型: ${config.model || '未配置'}`,
160
+ `AI分析统计: ${JSON.stringify(emojiluna.getAiTaskStats())}`,
161
+ '',
162
+ '自动获取:',
163
+ `状态: ${flag(config.autoCollect)}`,
164
+ `范围: ${config.groupScope} / 私聊 ${flag(config.collectDirect)}`,
165
+ `模式: ${config.autoCollectMode} / 阈值 ${config.emojiFrequencyThreshold} 次每 ${config.frequencyWindow} 分钟`,
166
+ `调试日志: ${flag(config.debug)}(范围 ${config.debugOnly})`,
167
+ ];
168
+ return lines.join('\n');
169
+ });
170
+ }
171
+ function registerCategoryCommands(ctx, emojiluna) {
172
+ ctx.command('emojiluna.category', '分类管理');
173
+ ctx.command('emojiluna.category.add <name:string>', '添加分类')
174
+ .option('description', '-d <description:string> 分类描述')
175
+ .action(async ({ options }, name) => {
176
+ if (!name)
177
+ return '请输入分类名称';
178
+ try {
179
+ const category = await emojiluna.addCategory(name, options.description);
180
+ return `分类 "${category.name}" 已就绪!ID: ${category.id}`;
181
+ }
182
+ catch (error) {
183
+ return `添加分类失败: ${error.message}`;
184
+ }
185
+ });
186
+ ctx.command('emojiluna.category.list', '查看所有分类')
187
+ .option('limit', '-l <limit:number> 限制显示数量', { fallback: 30 })
188
+ .option('offset', '-o <offset:number> 偏移量', { fallback: 0 })
189
+ .action(async ({ options }) => {
190
+ const page = await emojiluna.getCategoriesPage({
191
+ limit: Math.max(1, Number(options.limit) || 30),
192
+ offset: Math.max(0, Number(options.offset) || 0),
193
+ });
194
+ if (!page.items.length)
195
+ return '没有分类';
196
+ const lines = page.items.map((category) => `${category.name} (${category.id}) 数量 ${category.emojiCount} 描述 ${category.description || '无'}`);
197
+ return `分类列表 (${page.items.length}/${page.total}):\n${lines.join('\n')}`;
198
+ });
199
+ ctx.command('emojiluna.category.delete <id:string>', '删除分类')
200
+ .option('with-emojis', '-e 同时删除分类下的表情包')
201
+ .action(async ({ options }, id) => {
202
+ if (!id)
203
+ return '请输入分类ID';
204
+ try {
205
+ const success = await emojiluna.deleteCategory(id, Boolean(options['with-emojis']));
206
+ return success ? '分类删除成功' : '分类不存在';
207
+ }
208
+ catch (error) {
209
+ return `删除分类失败: ${error.message}`;
210
+ }
211
+ });
212
+ ctx.command('emojiluna.category.update <id:string> <category:string>', '更新表情包分类').action(async (_, id, category) => {
213
+ if (!id)
214
+ return '请输入表情包ID';
215
+ if (!category)
216
+ return '请输入分类名称';
217
+ const success = await emojiluna.updateEmojiCategory(id, category);
218
+ return success ? '分类更新成功' : '表情包不存在或分类名为空';
219
+ });
220
+ ctx.command('emojiluna.category.cleanup', '清理空分类').action(async () => {
221
+ const removed = await emojiluna.cleanupEmptyCategories();
222
+ return `已清理 ${removed} 个空分类`;
223
+ });
224
+ }
225
+ function registerTagCommands(ctx, emojiluna) {
226
+ ctx.command('emojiluna.tags', '标签管理');
227
+ ctx.command('emojiluna.tags.list', '查看所有标签')
228
+ .option('keyword', '-k <keyword:string> 按名称筛选')
229
+ .option('limit', '-l <limit:number> 限制显示数量', { fallback: 30 })
230
+ .option('offset', '-o <offset:number> 偏移量', { fallback: 0 })
231
+ .action(async ({ options }) => {
232
+ const page = await emojiluna.getTagsPage({
233
+ keyword: options.keyword,
234
+ limit: Math.max(1, Number(options.limit) || 30),
235
+ offset: Math.max(0, Number(options.offset) || 0),
236
+ });
237
+ if (!page.items.length)
238
+ return '没有标签';
239
+ const lines = page.items.map((tag) => `${tag.name} (${tag.usage})`);
240
+ return `标签列表 (${page.items.length}/${page.total}):\n${lines.join(', ')}`;
241
+ });
242
+ ctx.command('emojiluna.tags.update <id:string> <tags:string>', '更新表情包标签').action(async (_, id, tags) => {
243
+ if (!id)
244
+ return '请输入表情包ID';
245
+ if (!tags)
246
+ return '请输入标签,用逗号分隔';
247
+ const success = await emojiluna.updateEmojiTags(id, splitList(tags));
248
+ return success ? '标签更新成功' : '表情包不存在';
249
+ });
250
+ ctx.command('emojiluna.tags.cleanup', '清理空标签').action(async () => {
251
+ const removed = await emojiluna.cleanupEmptyTags();
252
+ return `已清理 ${removed} 个空标签`;
253
+ });
254
+ }
255
+ function registerAiCommands(ctx, config, emojiluna) {
256
+ ctx.command('emojiluna.ai', 'AI功能');
257
+ ctx.command('emojiluna.ai.categorize', '批量AI分类现有表情包').action(async ({ session }) => {
258
+ if (!config.autoCategorize)
259
+ return 'AI分类功能未启用';
260
+ if (!emojiluna.aiAnalyzer.hasModel) {
261
+ return '未配置或未加载 AI 模型,请先在配置中选择模型';
262
+ }
263
+ await session.send('开始批量AI分类,请稍候...');
264
+ const result = await emojiluna.categorizeExistingEmojis();
265
+ return `批量分类完成!\n成功: ${result.success} 个\n失败: ${result.failed} 个`;
266
+ });
267
+ ctx.command('emojiluna.ai.analyze <id:string>', 'AI分析表情包').action(async ({ session }, id) => {
268
+ if (!config.autoAnalyze)
269
+ return 'AI分析功能未启用';
270
+ const emoji = await emojiluna.getEmojiById(id);
271
+ if (!emoji)
272
+ return '表情包不存在';
273
+ const imageBuffer = await emojiluna.readEmojiBuffer(emoji);
274
+ if (!imageBuffer)
275
+ return '表情包文件读取失败,请查看日志';
276
+ await session.send('正在AI分析,请稍候...');
277
+ const result = await emojiluna.analyzeEmoji(imageBuffer.toString('base64'));
278
+ if (!result)
279
+ return 'AI分析失败,请检查模型配置或开启 debug 查看日志';
280
+ const lines = [
281
+ 'AI分析结果:',
282
+ '',
283
+ `建议名称: ${result.name}`,
284
+ `建议分类: ${result.category}`,
285
+ `建议标签: ${result.tags?.join(', ') || '无'}`,
286
+ `描述: ${result.description}`,
287
+ ];
288
+ if (result.newCategory) {
289
+ lines.push('', `建议新分类: ${result.newCategory}`);
290
+ }
291
+ return lines.join('\n');
292
+ });
293
+ ctx.command('emojiluna.ai.retry', '重试失败的AI分析任务').action(async () => {
294
+ const count = await emojiluna.retryFailedTasks();
295
+ return count ? `已重新排队 ${count} 个任务` : '没有失败的分析任务';
296
+ });
297
+ }
298
+ function normalizePage(options) {
299
+ const limit = Math.min(MAX_PAGE_SIZE, Math.max(1, Number(options.limit) || DEFAULT_LIST_LIMIT));
300
+ const offset = Math.max(0, Number(options.offset) || 0);
301
+ return { limit, offset };
302
+ }
303
+ function splitList(value) {
304
+ if (!value)
305
+ return [];
306
+ return value
307
+ .split(',')
308
+ .map((item) => item.trim())
309
+ .filter(Boolean);
310
+ }
311
+ function flag(enabled) {
312
+ return enabled ? '启用' : '禁用';
313
+ }
314
+ async function renderEmojiPage(ctx, config, options) {
315
+ const children = [koishi_1.h.text(`${options.title}\n`)];
316
+ for (const [index, emoji] of options.emojis.entries()) {
317
+ children.push(koishi_1.h.text(`\n${options.offset + index + 1}. ${(0, render_1.emojiText)(emoji)} ${(0, utils_1.formatFileSize)(emoji.size)}`));
318
+ if (options.inlineImages && index < MAX_INLINE_IMAGES) {
319
+ children.push(koishi_1.h.text('\n'), await (0, render_1.emojiMessage)(ctx, config, emoji));
320
+ }
321
+ else {
322
+ const url = (0, render_1.emojiUrl)(ctx, config, emoji);
323
+ children.push(koishi_1.h.text(url ? `\n${url}` : '\n(加 -T 只看文字可减小消息体积)'));
324
+ }
325
+ }
326
+ if (options.emojis.length >= MAX_PAGE_SIZE) {
327
+ children.push(koishi_1.h.text(`\n仅显示前 ${MAX_PAGE_SIZE} 个,可用 -o ${options.offset + MAX_PAGE_SIZE} 翻页`));
328
+ }
329
+ return (0, koishi_1.h)('message', {}, children);
330
+ }
@@ -0,0 +1,3 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from '../config';
3
+ export declare function applyConsoleListeners(ctx: Context, config: Config): void;