apix/scripts/merge_habu_prompts.mjs
KV-Pix Bot 6bf9f6e39c
Some checks failed
CI / build (18.x) (push) Has been cancelled
CI / build (20.x) (push) Has been cancelled
release: v2.5.0 - UI enhancements, pagination, and security
2026-01-16 22:08:26 +07:00

108 lines
3.4 KiB
JavaScript

import fs from 'fs/promises';
import path from 'path';
const DATA_FILE = path.join(process.cwd(), 'data', 'prompts.json');
const HABU_FILE = path.join(process.cwd(), 'data', 'habu_prompts.json');
async function mergePrompts() {
console.log("Reading files...");
let existingCache = { prompts: [], last_updated: null, categories: {}, total_count: 0, sources: [] };
try {
const data = await fs.readFile(DATA_FILE, 'utf-8');
existingCache = JSON.parse(data);
} catch (e) {
console.log("No existing prompts found or error reading.");
}
let habuRaw = [];
try {
const habuData = await fs.readFile(HABU_FILE, 'utf-8');
habuRaw = JSON.parse(habuData);
} catch (e) {
console.error("Error reading habu_prompts.json", e);
return;
}
console.log(`Found ${existingCache.prompts.length} existing prompts and ${habuRaw.length} Habu prompts.`);
// Map Habu to Prompt type
const habuPrompts = habuRaw.map(p => ({
id: 0,
title: p.name || 'Untitled Habu Prompt',
prompt: p.prompt,
category: 'Habu',
category_type: 'style',
description: p.prompt ? (p.prompt.substring(0, 150) + (p.prompt.length > 150 ? '...' : '')) : '',
images: p.imageUrl ? [p.imageUrl] : [],
author: 'Habu',
source: 'habu',
source_url: `https://taoanhez.com/#/prompt-library/${p.id}`,
createdAt: p.createdAt ? new Date(p.createdAt).getTime() : Date.now(),
useCount: 0
}));
// Merge Logic
// Preserving existing logic: dedupe by source_url
const existingMap = new Map();
const finalPrompts = [];
let addedCount = 0;
const now = Date.now();
existingCache.prompts.forEach(p => {
if (p.source_url) {
existingMap.set(p.source_url, p);
} else {
// Keep manually added prompts without source_url
finalPrompts.push(p);
}
});
habuPrompts.forEach(newP => {
const existing = existingMap.get(newP.source_url);
if (existing) {
finalPrompts.push({
...newP,
id: existing.id,
images: existing.images, // Keep existing images if modified? Or sync? Logic in service was keeping existing images.
createdAt: existing.createdAt,
useCount: existing.useCount,
lastUsedAt: existing.lastUsedAt
});
existingMap.delete(newP.source_url);
} else {
addedCount++;
finalPrompts.push({
...newP,
createdAt: now,
useCount: 0
});
}
});
// Add remaining existing
existingMap.forEach(p => finalPrompts.push(p));
// Re-ID
finalPrompts.forEach((p, i) => p.id = i + 1);
// Update Meta
const categories = {
"style": Array.from(new Set(finalPrompts.map(p => p.category)))
};
const newCache = {
last_updated: new Date(now).toISOString(),
lastSync: now,
categories,
total_count: finalPrompts.length,
sources: Array.from(new Set(finalPrompts.map(p => p.source))),
prompts: finalPrompts
};
await fs.writeFile(DATA_FILE, JSON.stringify(newCache, null, 2), 'utf-8');
console.log(`Merge complete. Total: ${finalPrompts.length}, Added: ${addedCount}`);
}
mergePrompts().catch(console.error);