const { sequelize } = require('./config/database'); const { Context, Vocab, Sentences } = require('./models'); // ─── helper: xác định slot image từ tên file/URL ──────────────────────────── function resolveImageSlot(imageUrl) { if (!imageUrl) return null; const filename = imageUrl.split('/').pop().split('?')[0]; const parts = filename.split('_'); for (const part of parts) { const key = part.toLowerCase(); if (key === 'square') return 'image_square'; if (key === 'small') return 'image_small'; if (key === 'normal') return 'image_normal'; } return null; } async function run() { try { await sequelize.authenticate(); console.log('✅ Database connected\n'); const contexts = await Context.findAll({ where: { status: 5 } }); console.log(`📦 Tìm thấy ${contexts.length} Context(s) có status = 5\n`); if (contexts.length === 0) { console.log('Không có gì để xử lý.'); process.exit(0); } let updatedVocab = 0; let updatedSentences = 0; let skipped = 0; for (const ctx of contexts) { const imageUrl = ctx.image; const slot = resolveImageSlot(imageUrl); if (!imageUrl || !slot) { console.warn(` ⚠️ [BỎ QUA] ID ${ctx.uuid}: Không xác định được ảnh/slot`); skipped++; continue; } let targetEntity = null; let entityType = ''; // Xử lý Vocab if (ctx.type === 'vocabulary') { // Ưu tiên tìm bản ghi đang active targetEntity = await Vocab.findOne({ where: { text: ctx.title, is_active: true } }); // Nếu không có bản ghi active, mới tìm bản ghi bất kỳ if (!targetEntity) targetEntity = await Vocab.findOne({ where: { text: ctx.title } }); entityType = 'Vocab'; } else { // Xử lý Sentence (ưu tiên active) targetEntity = await Sentences.findOne({ where: { text: ctx.context, is_active: true } }); if (!targetEntity) targetEntity = await Sentences.findOne({ where: { text: ctx.context } }); if (!targetEntity) { targetEntity = await Sentences.findOne({ where: { text: ctx.title, is_active: true } }); if (!targetEntity) targetEntity = await Sentences.findOne({ where: { text: ctx.title } }); } entityType = 'Sentence'; } if (targetEntity) { // 1. Cập nhật ảnh (Ghi đè - để mảng chỉ có 1 ảnh) await targetEntity.update({ [slot]: [imageUrl] }); // 2. Kiểm tra và sửa reference_id nếu lệch const correctId = targetEntity.vocab_id || targetEntity.id; const updates = { status: 6 }; if (ctx.reference_id !== correctId) { updates.reference_id = correctId; } await ctx.update(updates); if (entityType === 'Vocab') updatedVocab++; else updatedSentences++; console.log(` ✅ [${entityType}] "${ctx.title}" -> ${slot} (Đã ghi đè)`); } else { console.warn(` ❌ [KHÔNG THẤY] "${ctx.title}" (Type: ${ctx.type})`); skipped++; } } console.log('\n─────────────────────────────────────'); console.log(`📊 Kết quả:`); console.log(` ✅ Cập nhật Vocab : ${updatedVocab}`); console.log(` ✅ Cập nhật Sentences: ${updatedSentences}`); console.log(` ⚠️ Bỏ qua : ${skipped}`); console.log('─────────────────────────────────────'); process.exit(0); } catch (error) { console.error('❌ Lỗi:', error.message); process.exit(1); } } run();