BBC Article Summarizer

Automatically generates and displays AI-powered summaries for BBC articles

Size

8.1 KB

Version

1.1.3

Created

Nov 3, 2025

Updated

about 1 month ago

1// ==UserScript==
2// @name		BBC Article Summarizer
3// @description		Automatically generates and displays AI-powered summaries for BBC articles
4// @version		1.1.3
5// @match		https://*.bbc.com/*
6// @icon		https://static.files.bbci.co.uk/bbcdotcom/web/20251021-134202-667692b2c6-web-2.32.2-1/favicon.ico
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    // Debounce function to prevent multiple rapid calls
12    function debounce(func, wait) {
13        let timeout;
14        return function executedFunction(...args) {
15            const later = () => {
16                clearTimeout(timeout);
17                func(...args);
18            };
19            clearTimeout(timeout);
20            timeout = setTimeout(later, wait);
21        };
22    }
23
24    async function generateAndDisplaySummary() {
25        console.log('Starting article summary generation...');
26        
27        // Find the article element
28        const articleElement = document.querySelector('article');
29        if (!articleElement) {
30            console.error('Article element not found');
31            return;
32        }
33
34        // Check if summary already exists
35        if (document.getElementById('ai-article-summary')) {
36            console.log('Summary already exists');
37            return;
38        }
39
40        // Get article text
41        const articleText = articleElement.innerText;
42        if (!articleText || articleText.length < 100) {
43            console.error('Article text too short or not found');
44            return;
45        }
46
47        // Find the headline block to insert summary after it
48        const headlineBlock = document.querySelector('[data-component="headline-block"]');
49        const bylineBlock = document.querySelector('[data-component="byline-block"]');
50        
51        if (!headlineBlock || !bylineBlock) {
52            console.error('Could not find insertion point for summary');
53            return;
54        }
55
56        // Create summary container
57        const summaryContainer = document.createElement('div');
58        summaryContainer.id = 'ai-article-summary';
59        summaryContainer.className = 'sc-3b6b161a-0 dPVOKT'; // Match BBC's article block classes
60        summaryContainer.style.cssText = `
61            background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #d946ef 100%);
62            color: white;
63            padding: 32px;
64            margin: 24px auto;
65            border-radius: 16px;
66            box-shadow: 0 10px 40px rgba(99, 102, 241, 0.3), 0 4px 12px rgba(0, 0, 0, 0.1);
67            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
68            position: relative;
69            overflow: hidden;
70            max-width: 100%;
71            box-sizing: border-box;
72        `;
73
74        // Add loading state
75        summaryContainer.innerHTML = `
76            <div style="display: flex; align-items: center; gap: 16px;">
77                <div style="width: 32px; height: 32px; border: 4px solid rgba(255,255,255,0.2); border-top-color: white; border-radius: 50%; animation: spin 1s linear infinite;"></div>
78                <div>
79                    <h3 style="margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -0.5px;">AI Summary</h3>
80                    <p style="margin: 8px 0 0 0; font-size: 15px; opacity: 0.85;">Analyzing article and generating insights...</p>
81                </div>
82            </div>
83        `;
84
85        // Add spinner animation
86        const style = document.createElement('style');
87        style.textContent = `
88            @keyframes spin {
89                to { transform: rotate(360deg); }
90            }
91            #ai-article-summary::before {
92                content: '';
93                position: absolute;
94                top: 0;
95                left: 0;
96                right: 0;
97                bottom: 0;
98                background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 100%);
99                pointer-events: none;
100            }
101            #ai-article-summary ul li::marker {
102                color: rgba(255, 255, 255, 0.7);
103            }
104        `;
105        document.head.appendChild(style);
106
107        // Insert after byline block
108        bylineBlock.parentNode.insertBefore(summaryContainer, bylineBlock.nextSibling);
109
110        try {
111            console.log('Calling AI to generate summary...');
112            
113            // Generate summary using AI
114            const summary = await RM.aiCall(
115                `Please provide a very brief 2-3 sentence summary of this BBC article. Be concise and focus only on the most important finding:\n\n${articleText}`,
116                {
117                    type: 'json_schema',
118                    json_schema: {
119                        name: 'article_summary',
120                        schema: {
121                            type: 'object',
122                            properties: {
123                                summary: { 
124                                    type: 'string',
125                                    description: 'A brief 2-3 sentence summary of the article'
126                                },
127                                keyPoints: {
128                                    type: 'array',
129                                    items: { type: 'string' },
130                                    description: '3 key points from the article',
131                                    minItems: 3,
132                                    maxItems: 3
133                                }
134                            },
135                            required: ['summary', 'keyPoints']
136                        }
137                    }
138                }
139            );
140
141            console.log('Summary generated successfully:', summary);
142
143            // Display the summary
144            const keyPointsHTML = summary.keyPoints.map(point => 
145                `<li style="margin: 10px 0; padding-left: 8px; line-height: 1.5;">${point}</li>`
146            ).join('');
147
148            summaryContainer.innerHTML = `
149                <div style="position: relative; z-index: 1;">
150                    <h3 style="margin: 0 0 16px 0; font-size: 24px; font-weight: 700; display: flex; align-items: center; gap: 10px; letter-spacing: -0.5px;">
151                        <span style="font-size: 28px; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));"></span> 
152                        <span>AI Summary</span>
153                    </h3>
154                    <p style="margin: 0 0 20px 0; font-size: 17px; line-height: 1.7; opacity: 0.95; font-weight: 400;">
155                        ${summary.summary}
156                    </p>
157                    <div style="border-top: 2px solid rgba(255,255,255,0.25); padding-top: 20px; margin-top: 4px;">
158                        <h4 style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600; opacity: 0.95; letter-spacing: -0.3px;">Key Points:</h4>
159                        <ul style="margin: 0; padding-left: 24px; font-size: 15px; line-height: 1.6; opacity: 0.92;">
160                            ${keyPointsHTML}
161                        </ul>
162                    </div>
163                </div>
164            `;
165
166        } catch (error) {
167            console.error('Error generating summary:', error);
168            summaryContainer.innerHTML = `
169                <div style="position: relative; z-index: 1;">
170                    <h3 style="margin: 0 0 12px 0; font-size: 22px; font-weight: 700; display: flex; align-items: center; gap: 10px;">
171                        <span style="font-size: 24px;">⚠️</span> AI Summary
172                    </h3>
173                    <p style="margin: 0; font-size: 15px; opacity: 0.9; line-height: 1.6;">
174                        Unable to generate summary at this time. Please try refreshing the page.
175                    </p>
176                </div>
177            `;
178        }
179    }
180
181    // Initialize when page is ready
182    function init() {
183        console.log('BBC Article Summarizer initialized');
184        
185        // Wait for article to be fully loaded
186        if (document.readyState === 'loading') {
187            document.addEventListener('DOMContentLoaded', generateAndDisplaySummary);
188        } else {
189            // DOM already loaded
190            setTimeout(generateAndDisplaySummary, 1000);
191        }
192    }
193
194    init();
195})();
BBC Article Summarizer | Robomonkey