mioku-service-webui 4.4.4 → 4.4.5
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/database.ts +42 -0
- package/package.json +1 -1
- package/routes/ai.ts +27 -0
package/database.ts
CHANGED
|
@@ -5,6 +5,14 @@ import { CHAT_DATA_DIR, readJsonFile, writeJsonFile } from "./utils";
|
|
|
5
5
|
|
|
6
6
|
const DB_PATH = path.join(CHAT_DATA_DIR, "chat.db");
|
|
7
7
|
const SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
8
|
+
const STICKER_FILE_PATTERN = /\.(png|jpg|jpeg|gif|webp)$/i;
|
|
9
|
+
|
|
10
|
+
export interface StickerCatalogItem {
|
|
11
|
+
id: string;
|
|
12
|
+
character: string;
|
|
13
|
+
label: string;
|
|
14
|
+
url: string;
|
|
15
|
+
}
|
|
8
16
|
|
|
9
17
|
function openDb(): any {
|
|
10
18
|
if (!fs.existsSync(DB_PATH)) {
|
|
@@ -299,6 +307,40 @@ export function listMemeTree(): Record<string, Record<string, string[]>> {
|
|
|
299
307
|
return tree;
|
|
300
308
|
}
|
|
301
309
|
|
|
310
|
+
export function listStickerCatalog(): StickerCatalogItem[] {
|
|
311
|
+
const root = path.join(CHAT_DATA_DIR, "meme");
|
|
312
|
+
if (!fs.existsSync(root)) return [];
|
|
313
|
+
|
|
314
|
+
const items: StickerCatalogItem[] = [];
|
|
315
|
+
const visit = (dir: string, character: string) => {
|
|
316
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
317
|
+
const entryPath = path.join(dir, entry.name);
|
|
318
|
+
if (entry.isDirectory()) {
|
|
319
|
+
visit(entryPath, character);
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (!entry.isFile() || !STICKER_FILE_PATTERN.test(entry.name)) continue;
|
|
323
|
+
|
|
324
|
+
const id = path.relative(root, entryPath).split(path.sep).join("/");
|
|
325
|
+
const label = path
|
|
326
|
+
.basename(entry.name, path.extname(entry.name))
|
|
327
|
+
.replace(/[_-]+/g, " ")
|
|
328
|
+
.trim();
|
|
329
|
+
const url = `/meme/${id
|
|
330
|
+
.split("/")
|
|
331
|
+
.map((segment) => encodeURIComponent(segment))
|
|
332
|
+
.join("/")}`;
|
|
333
|
+
items.push({ id, character, label, url });
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
338
|
+
if (entry.isDirectory()) visit(path.join(root, entry.name), entry.name);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return items.sort((a, b) => a.id.localeCompare(b.id));
|
|
342
|
+
}
|
|
343
|
+
|
|
302
344
|
export function savePluginConfig(pluginName: string, fileName: string, value: any): void {
|
|
303
345
|
const filePath = path.join(process.cwd(), "config", pluginName, `${fileName}.json`);
|
|
304
346
|
writeJsonFile(filePath, value);
|
package/package.json
CHANGED
package/routes/ai.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import { logger } from "mioki";
|
|
3
3
|
import { getChatConfig, updateChatConfig } from "../system";
|
|
4
|
+
import { listStickerCatalog } from "../database";
|
|
4
5
|
import aiService from "mioku-service-ai";
|
|
5
6
|
import type { AIUsageRange } from "mioku-service-ai/usage/types";
|
|
6
7
|
|
|
@@ -96,6 +97,28 @@ function normalizePersonalizationConfig(input: any): any {
|
|
|
96
97
|
delete rawExpression.maxExpressions;
|
|
97
98
|
|
|
98
99
|
data.expression = rawExpression;
|
|
100
|
+
|
|
101
|
+
const rawEmoji =
|
|
102
|
+
data.emoji && typeof data.emoji === "object" && !Array.isArray(data.emoji)
|
|
103
|
+
? { ...data.emoji }
|
|
104
|
+
: {};
|
|
105
|
+
rawEmoji.enabled =
|
|
106
|
+
typeof rawEmoji.enabled === "boolean" ? rawEmoji.enabled : true;
|
|
107
|
+
rawEmoji.characters = Array.isArray(rawEmoji.characters)
|
|
108
|
+
? rawEmoji.characters
|
|
109
|
+
.map(String)
|
|
110
|
+
.map((value: string) => value.trim())
|
|
111
|
+
.filter(Boolean)
|
|
112
|
+
: [];
|
|
113
|
+
rawEmoji.stickers = Array.isArray(rawEmoji.stickers)
|
|
114
|
+
? rawEmoji.stickers
|
|
115
|
+
.map(String)
|
|
116
|
+
.map((value: string) => value.trim())
|
|
117
|
+
.filter(Boolean)
|
|
118
|
+
: [];
|
|
119
|
+
delete rawEmoji.useAISelection;
|
|
120
|
+
data.emoji = rawEmoji;
|
|
121
|
+
|
|
99
122
|
return data;
|
|
100
123
|
}
|
|
101
124
|
|
|
@@ -189,6 +212,10 @@ export function createAIRoutes() {
|
|
|
189
212
|
});
|
|
190
213
|
});
|
|
191
214
|
|
|
215
|
+
app.get("/stickers", (c) =>
|
|
216
|
+
c.json({ ok: true, data: listStickerCatalog() }),
|
|
217
|
+
);
|
|
218
|
+
|
|
192
219
|
app.get("/usage", (c) => {
|
|
193
220
|
if (!aiService?.api?.getUsageSummary) {
|
|
194
221
|
return c.json({ ok: false, error: "AI_USAGE_UNAVAILABLE" }, 503);
|