import PocketBase from 'pocketbase'; const PB_URL = 'http://127.0.0.1:8090'; const pb = new PocketBase(PB_URL); interface Post { id: string; title: string; content: string; slug: string; category: string; draft: boolean; } interface AnalysisResult { title: string; slug: string; category: string; hasClaim: boolean; hasTakeaway: boolean; hasPronouns: boolean; hasProof: boolean; h2Issues: string[]; problems: string[]; } function analyzePost(post: Post): AnalysisResult { const result: AnalysisResult = { title: post.title, slug: post.slug, category: post.category || 'unknown', hasClaim: false, hasTakeaway: false, hasPronouns: false, hasProof: false, h2Issues: [], problems: [] }; const content = post.content || ''; // Check for Claim patterns directly in content (including HTML) // Look for new first paragraph that starts with Claim-like content // Check first 1500 chars to catch posts where Claim may have been inserted const claimPatterns = [ { pattern: /За\s+\d+/i, name: 'За год' }, { pattern: /В\s+\d+\s+(год|месяц)/i, name: 'В год/месяц' }, { pattern: /\d+%/i, name: 'Процент' }, { pattern: /Вы можете/i, name: 'Вы можете' }, ]; const prefix = content.substring(0, 3000); result.hasClaim = claimPatterns.some(p => p.pattern.test(prefix)); // Proof: contains numbers const numberPatterns = [/\d+%/g, /\d+\s+(лет|месяцев|дней|тысяч|рублей)/gi]; result.hasProof = numberPatterns.some(p => p.test(content)); // Pronouns check const pronouns = /\b(мы|наш|наша|наши|их|он|она|оно|этот|эта|эти)\b/gi; result.hasPronouns = pronouns.test(content); // Takeaway check const takeawayPatterns = [ /что\s+делать/i, /обращайтесь/i, /позвоните/i, /закажите/i, /получите/i, /напишите/i, /свяжитесь/i ]; result.hasTakeaway = takeawayPatterns.some(p => p.test(content)); // H2 analysis - check all H2s in content const h2Matches = content.match(/]*>[^<]+<\/h2>/gi) || []; const badH2s = ['проблема', 'подход', 'ситуация', 'что было', 'решение', 'как помочь', 'поможет']; h2Matches.forEach(h2 => { const h2Text = h2.toLowerCase(); if (badH2s.some(b => h2Text.includes(b))) { result.h2Issues.push(h2.replace(/<[^>]+>/g, '')); } }); // Collect problems if (!result.hasClaim) result.problems.push('Нет Claim в первом абзаце'); if (!result.hasTakeaway) result.problems.push('Нет Takeaway'); if (result.hasPronouns) result.problems.push('Есть местоимения'); if (!result.hasProof) result.problems.push('Нет конкретных цифр'); if (result.h2Issues.length > 0) result.problems.push(`Размытые H2: ${result.h2Issues.join(', ')}`); return result; } async function main() { console.log('📊 Анализ постов блога по методологии Answer Unit\n'); console.log('='.repeat(60)); try { const postsResult = await pb.collection('posts').getList(1, 500); const posts = postsResult.items as unknown as Post[]; console.log(`Найдено постов: ${posts.length}\n`); // Filter for non-draft posts const activePosts = posts.filter(p => !p.draft); console.log(`Опубликованных постов: ${activePosts.length}\n`); const results = activePosts.map(analyzePost); // Stats const withClaim = results.filter(r => r.hasClaim).length; const withTakeaway = results.filter(r => r.hasTakeaway).length; const withPronouns = results.filter(r => r.hasPronouns).length; const withProof = results.filter(r => r.hasProof).length; const withH2Issues = results.filter(r => r.h2Issues.length > 0).length; const problemCount = results.filter(r => r.problems.length > 0).length; const n = activePosts.length; console.log('📈 ОБЩАЯ СТАТИСТИКА:'); console.log('-'.repeat(40)); console.log(` ✓ Есть Claim: ${withClaim}/${n} (${n > 0 ? Math.round(withClaim/n*100) : 0}%)`); console.log(` ✓ Есть Takeaway: ${withTakeaway}/${n} (${n > 0 ? Math.round(withTakeaway/n*100) : 0}%)`); console.log(` ✗ Есть местоимения: ${withPronouns}/${n} (${n > 0 ? Math.round(withPronouns/n*100) : 0}%)`); console.log(` ✓ Есть Proof (цифры): ${withProof}/${n} (${n > 0 ? Math.round(withProof/n*100) : 0}%)`); console.log(` ✗ Проблемы с H2: ${withH2Issues}/${n}`); console.log(` ⚠️ Постов с проблемами: ${problemCount}/${n}\n`); // Problem posts const problemPosts = results.filter(r => r.problems.length > 0); if (problemPosts.length > 0) { console.log('❌ ПОСТЫ С ПРОБЛЕМАМИ:'); console.log('-'.repeat(40)); problemPosts.forEach((r, i) => { console.log(`\n${i+1}. ${r.title}`); console.log(` slug: ${r.slug}`); console.log(` category: ${r.category}`); r.problems.forEach(p => console.log(` - ${p}`)); }); } // Good posts const goodPosts = results.filter(r => r.problems.length === 0); if (goodPosts.length > 0) { console.log('\n\n✅ ПОСТЫ БЕЗ ПРОБЛЕМ:'); console.log('-'.repeat(40)); goodPosts.forEach(r => { console.log(` • ${r.title}`); }); } } catch (error) { console.error('Ошибка:', error); } } main();