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.
- package/LICENSE +24 -0
- package/dist/index.js +10 -0
- package/dist/style.css +1 -0
- package/lib/adapters/autoCommands.d.ts +4 -0
- package/lib/adapters/autoCommands.js +111 -0
- package/lib/adapters/backend.d.ts +3 -0
- package/lib/adapters/backend.js +11 -0
- package/lib/adapters/chatlunaIntegration.d.ts +3 -0
- package/lib/adapters/chatlunaIntegration.js +48 -0
- package/lib/adapters/commands.d.ts +4 -0
- package/lib/adapters/commands.js +330 -0
- package/lib/adapters/consoleListeners.d.ts +3 -0
- package/lib/adapters/consoleListeners.js +168 -0
- package/lib/adapters/index.d.ts +2 -0
- package/lib/adapters/index.js +7 -0
- package/lib/adapters/render.d.ts +7 -0
- package/lib/adapters/render.js +35 -0
- package/lib/adapters/restApi.d.ts +3 -0
- package/lib/adapters/restApi.js +225 -0
- package/lib/collectors/autoCollector.d.ts +75 -0
- package/lib/collectors/autoCollector.js +728 -0
- package/lib/collectors/index.d.ts +1 -0
- package/lib/collectors/index.js +17 -0
- package/lib/config.d.ts +194 -0
- package/lib/config.js +369 -0
- package/lib/debug.d.ts +13 -0
- package/lib/debug.js +44 -0
- package/lib/image/imageProcessor.d.ts +20 -0
- package/lib/image/imageProcessor.js +243 -0
- package/lib/image/index.d.ts +1 -0
- package/lib/image/index.js +17 -0
- package/lib/index.d.ts +57 -0
- package/lib/index.js +40 -0
- package/lib/services/aiAnalyzer.d.ts +24 -0
- package/lib/services/aiAnalyzer.js +162 -0
- package/lib/services/emojiluna.d.ts +102 -0
- package/lib/services/emojiluna.js +910 -0
- package/lib/services/index.d.ts +2 -0
- package/lib/services/index.js +18 -0
- package/lib/storage/index.d.ts +1 -0
- package/lib/storage/index.js +17 -0
- package/lib/storage/uploadManager.d.ts +102 -0
- package/lib/storage/uploadManager.js +424 -0
- package/lib/types.d.ts +159 -0
- package/lib/types.js +69 -0
- package/lib/utils.d.ts +29 -0
- package/lib/utils.js +256 -0
- package/package.json +99 -0
- 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,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,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,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,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
|
+
}
|