AI Page Assistant

Умный ИИ помощник для анализа контента любой страницы

Size

18.1 KB

Version

1.0.1

Created

Mar 17, 2026

Updated

about 1 month ago

1// ==UserScript==
2// @name		AI Page Assistant
3// @description		Умный ИИ помощник для анализа контента любой страницы
4// @version		1.0.1
5// @match		*://*/*
6// ==/UserScript==
7(function() {
8    'use strict';
9
10    // Debounce function for performance
11    function debounce(func, wait) {
12        let timeout;
13        return function executedFunction(...args) {
14            const later = () => {
15                clearTimeout(timeout);
16                func(...args);
17            };
18            clearTimeout(timeout);
19            timeout = setTimeout(later, wait);
20        };
21    }
22
23    // Collect all page content
24    function collectPageContent() {
25        console.log('Collecting page content...');
26        
27        // Get main text content
28        const bodyText = document.body.innerText || '';
29        
30        // Get page title
31        const title = document.title || '';
32        
33        // Get meta description
34        const metaDescription = document.querySelector('meta[name="description"]')?.content || '';
35        
36        // Combine all content
37        const fullContent = `
38Заголовок страницы: ${title}
39
40Описание: ${metaDescription}
41
42Содержимое страницы:
43${bodyText}
44        `.trim();
45        
46        console.log('Content collected, length:', fullContent.length);
47        return fullContent;
48    }
49
50    // Create chat UI
51    function createChatUI() {
52        console.log('Creating chat UI...');
53        
54        // Add styles
55        const styles = `
56            #ai-chat-button {
57                position: fixed;
58                bottom: 20px;
59                left: 20px;
60                width: 56px;
61                height: 56px;
62                border-radius: 50%;
63                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
64                border: none;
65                cursor: pointer;
66                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
67                z-index: 999999;
68                display: flex;
69                align-items: center;
70                justify-content: center;
71                transition: all 0.3s ease;
72            }
73            
74            #ai-chat-button:hover {
75                transform: scale(1.1);
76                box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
77            }
78            
79            #ai-chat-button svg {
80                width: 28px;
81                height: 28px;
82                fill: white;
83            }
84            
85            #ai-chat-container {
86                position: fixed;
87                bottom: 90px;
88                left: 20px;
89                width: 380px;
90                height: 550px;
91                background: white;
92                border-radius: 16px;
93                box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
94                z-index: 999998;
95                display: none;
96                flex-direction: column;
97                overflow: hidden;
98                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
99            }
100            
101            #ai-chat-container.open {
102                display: flex;
103                animation: slideUp 0.3s ease;
104            }
105            
106            @keyframes slideUp {
107                from {
108                    opacity: 0;
109                    transform: translateY(20px);
110                }
111                to {
112                    opacity: 1;
113                    transform: translateY(0);
114                }
115            }
116            
117            #ai-chat-header {
118                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
119                color: white;
120                padding: 20px;
121                font-weight: 600;
122                font-size: 18px;
123                display: flex;
124                align-items: center;
125                justify-content: space-between;
126            }
127            
128            #ai-chat-close {
129                background: none;
130                border: none;
131                color: white;
132                font-size: 24px;
133                cursor: pointer;
134                padding: 0;
135                width: 30px;
136                height: 30px;
137                display: flex;
138                align-items: center;
139                justify-content: center;
140                border-radius: 50%;
141                transition: background 0.2s;
142            }
143            
144            #ai-chat-close:hover {
145                background: rgba(255, 255, 255, 0.2);
146            }
147            
148            #ai-chat-messages {
149                flex: 1;
150                overflow-y: auto;
151                padding: 20px;
152                background: #f8f9fa;
153            }
154            
155            .ai-message {
156                margin-bottom: 16px;
157                display: flex;
158                gap: 10px;
159                animation: fadeIn 0.3s ease;
160            }
161            
162            @keyframes fadeIn {
163                from {
164                    opacity: 0;
165                    transform: translateY(10px);
166                }
167                to {
168                    opacity: 1;
169                    transform: translateY(0);
170                }
171            }
172            
173            .ai-message.user {
174                flex-direction: row-reverse;
175            }
176            
177            .ai-message-avatar {
178                width: 32px;
179                height: 32px;
180                border-radius: 50%;
181                display: flex;
182                align-items: center;
183                justify-content: center;
184                font-size: 18px;
185                flex-shrink: 0;
186            }
187            
188            .ai-message.user .ai-message-avatar {
189                background: #667eea;
190            }
191            
192            .ai-message.assistant .ai-message-avatar {
193                background: #764ba2;
194            }
195            
196            .ai-message-content {
197                max-width: 75%;
198                padding: 12px 16px;
199                border-radius: 12px;
200                line-height: 1.5;
201                font-size: 14px;
202            }
203            
204            .ai-message.user .ai-message-content {
205                background: #667eea;
206                color: white;
207                border-bottom-right-radius: 4px;
208            }
209            
210            .ai-message.assistant .ai-message-content {
211                background: white;
212                color: #333;
213                border-bottom-left-radius: 4px;
214                box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
215            }
216            
217            #ai-chat-input-container {
218                padding: 16px;
219                background: white;
220                border-top: 1px solid #e9ecef;
221                display: flex;
222                gap: 10px;
223            }
224            
225            #ai-chat-input {
226                flex: 1;
227                border: 2px solid #e9ecef;
228                border-radius: 24px;
229                padding: 12px 16px;
230                font-size: 14px;
231                outline: none;
232                transition: border-color 0.2s;
233                font-family: inherit;
234            }
235            
236            #ai-chat-input:focus {
237                border-color: #667eea;
238            }
239            
240            #ai-chat-send {
241                width: 44px;
242                height: 44px;
243                border-radius: 50%;
244                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
245                border: none;
246                cursor: pointer;
247                display: flex;
248                align-items: center;
249                justify-content: center;
250                transition: all 0.2s;
251                flex-shrink: 0;
252            }
253            
254            #ai-chat-send:hover:not(:disabled) {
255                transform: scale(1.05);
256                box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
257            }
258            
259            #ai-chat-send:disabled {
260                opacity: 0.5;
261                cursor: not-allowed;
262            }
263            
264            #ai-chat-send svg {
265                width: 20px;
266                height: 20px;
267                fill: white;
268            }
269            
270            .ai-typing-indicator {
271                display: flex;
272                gap: 4px;
273                padding: 12px 16px;
274            }
275            
276            .ai-typing-dot {
277                width: 8px;
278                height: 8px;
279                border-radius: 50%;
280                background: #999;
281                animation: typing 1.4s infinite;
282            }
283            
284            .ai-typing-dot:nth-child(2) {
285                animation-delay: 0.2s;
286            }
287            
288            .ai-typing-dot:nth-child(3) {
289                animation-delay: 0.4s;
290            }
291            
292            @keyframes typing {
293                0%, 60%, 100% {
294                    transform: translateY(0);
295                    opacity: 0.7;
296                }
297                30% {
298                    transform: translateY(-10px);
299                    opacity: 1;
300                }
301            }
302            
303            #ai-chat-messages::-webkit-scrollbar {
304                width: 6px;
305            }
306            
307            #ai-chat-messages::-webkit-scrollbar-track {
308                background: transparent;
309            }
310            
311            #ai-chat-messages::-webkit-scrollbar-thumb {
312                background: #cbd5e0;
313                border-radius: 3px;
314            }
315            
316            #ai-chat-messages::-webkit-scrollbar-thumb:hover {
317                background: #a0aec0;
318            }
319        `;
320        
321        TM_addStyle(styles);
322        
323        // Create button
324        const button = document.createElement('button');
325        button.id = 'ai-chat-button';
326        button.innerHTML = `
327            <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
328                <path d="M12 2C6.48 2 2 6.48 2 12c0 1.54.36 3 .97 4.29L2 22l5.71-.97C9 21.64 10.46 22 12 22c5.52 0 10-4.48 10-10S17.52 2 12 2zm0 18c-1.38 0-2.68-.31-3.86-.85l-.28-.14-2.9.49.49-2.9-.14-.28C4.31 14.68 4 13.38 4 12c0-4.41 3.59-8 8-8s8 3.59 8 8-3.59 8-8 8z"/>
329                <circle cx="9" cy="12" r="1"/>
330                <circle cx="12" cy="12" r="1"/>
331                <circle cx="15" cy="12" r="1"/>
332            </svg>
333        `;
334        
335        // Create chat container
336        const container = document.createElement('div');
337        container.id = 'ai-chat-container';
338        container.innerHTML = `
339            <div id="ai-chat-header">
340                <span>🤖 AI Помощник</span>
341                <button id="ai-chat-close">×</button>
342            </div>
343            <div id="ai-chat-messages">
344                <div class="ai-message assistant">
345                    <div class="ai-message-avatar">🤖</div>
346                    <div class="ai-message-content">
347                        Привет! Я проанализировал эту страницу и готов ответить на ваши вопросы о её содержимом. Спрашивайте что угодно!
348                    </div>
349                </div>
350            </div>
351            <div id="ai-chat-input-container">
352                <input type="text" id="ai-chat-input" placeholder="Задайте вопрос о странице...">
353                <button id="ai-chat-send">
354                    <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
355                        <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
356                    </svg>
357                </button>
358            </div>
359        `;
360        
361        document.body.appendChild(button);
362        document.body.appendChild(container);
363        
364        console.log('Chat UI created');
365        
366        return { button, container };
367    }
368
369    // Add message to chat
370    function addMessage(role, content) {
371        const messagesContainer = document.getElementById('ai-chat-messages');
372        const messageDiv = document.createElement('div');
373        messageDiv.className = `ai-message ${role}`;
374        
375        const avatar = role === 'user' ? '👤' : '🤖';
376        
377        messageDiv.innerHTML = `
378            <div class="ai-message-avatar">${avatar}</div>
379            <div class="ai-message-content">${content}</div>
380        `;
381        
382        messagesContainer.appendChild(messageDiv);
383        messagesContainer.scrollTop = messagesContainer.scrollHeight;
384        
385        console.log(`Message added: ${role}`);
386    }
387
388    // Show typing indicator
389    function showTypingIndicator() {
390        const messagesContainer = document.getElementById('ai-chat-messages');
391        const typingDiv = document.createElement('div');
392        typingDiv.className = 'ai-message assistant';
393        typingDiv.id = 'ai-typing-indicator';
394        typingDiv.innerHTML = `
395            <div class="ai-message-avatar">🤖</div>
396            <div class="ai-message-content">
397                <div class="ai-typing-indicator">
398                    <div class="ai-typing-dot"></div>
399                    <div class="ai-typing-dot"></div>
400                    <div class="ai-typing-dot"></div>
401                </div>
402            </div>
403        `;
404        messagesContainer.appendChild(typingDiv);
405        messagesContainer.scrollTop = messagesContainer.scrollHeight;
406    }
407
408    // Hide typing indicator
409    function hideTypingIndicator() {
410        const typingIndicator = document.getElementById('ai-typing-indicator');
411        if (typingIndicator) {
412            typingIndicator.remove();
413        }
414    }
415
416    // Handle sending message
417    async function handleSendMessage() {
418        const input = document.getElementById('ai-chat-input');
419        const sendButton = document.getElementById('ai-chat-send');
420        const question = input.value.trim();
421        
422        if (!question) return;
423        
424        console.log('Sending message:', question);
425        
426        // Add user message
427        addMessage('user', question);
428        input.value = '';
429        
430        // Disable input
431        input.disabled = true;
432        sendButton.disabled = true;
433        
434        // Show typing indicator
435        showTypingIndicator();
436        
437        try {
438            // Collect page content
439            const pageContent = collectPageContent();
440            
441            // Create prompt for AI
442            const prompt = `Ты умный помощник, который анализирует содержимое веб-страниц. Вот содержимое текущей страницы:
443
444${pageContent.substring(0, 15000)}
445
446Пользователь задал вопрос: ${question}
447
448Ответь на вопрос пользователя на основе содержимого страницы. Будь кратким, точным и полезным. Отвечай на том же языке, на котором задан вопрос.`;
449
450            console.log('Calling AI...');
451            
452            // Call AI
453            const response = await RM.aiCall(prompt);
454            
455            console.log('AI response received');
456            
457            // Hide typing indicator
458            hideTypingIndicator();
459            
460            // Add AI response
461            addMessage('assistant', response);
462            
463            // Save chat history
464            await saveChatHistory();
465            
466        } catch (error) {
467            console.error('Error calling AI:', error);
468            hideTypingIndicator();
469            addMessage('assistant', 'Извините, произошла ошибка при обработке вашего запроса. Попробуйте еще раз.');
470        } finally {
471            // Re-enable input
472            input.disabled = false;
473            sendButton.disabled = false;
474            input.focus();
475        }
476    }
477
478    // Save chat history
479    async function saveChatHistory() {
480        const messagesContainer = document.getElementById('ai-chat-messages');
481        const messages = Array.from(messagesContainer.querySelectorAll('.ai-message')).map(msg => ({
482            role: msg.classList.contains('user') ? 'user' : 'assistant',
483            content: msg.querySelector('.ai-message-content').textContent
484        }));
485        
486        await GM.setValue('ai_chat_history_' + window.location.href, JSON.stringify(messages));
487        console.log('Chat history saved');
488    }
489
490    // Load chat history
491    async function loadChatHistory() {
492        try {
493            const historyJson = await GM.getValue('ai_chat_history_' + window.location.href);
494            if (historyJson) {
495                const messages = JSON.parse(historyJson);
496                const messagesContainer = document.getElementById('ai-chat-messages');
497                messagesContainer.innerHTML = '';
498                
499                messages.forEach(msg => {
500                    addMessage(msg.role, msg.content);
501                });
502                
503                console.log('Chat history loaded');
504            }
505        } catch (error) {
506            console.error('Error loading chat history:', error);
507        }
508    }
509
510    // Initialize
511    async function init() {
512        console.log('AI Page Assistant initializing...');
513        
514        // Wait for body to be ready
515        if (document.body) {
516            setupChat();
517        } else {
518            TM_runBody(setupChat);
519        }
520    }
521
522    function setupChat() {
523        const { button, container } = createChatUI();
524        
525        // Toggle chat
526        button.addEventListener('click', async () => {
527            const isOpen = container.classList.contains('open');
528            if (isOpen) {
529                container.classList.remove('open');
530            } else {
531                container.classList.add('open');
532                await loadChatHistory();
533                document.getElementById('ai-chat-input').focus();
534            }
535        });
536        
537        // Close chat
538        document.getElementById('ai-chat-close').addEventListener('click', () => {
539            container.classList.remove('open');
540        });
541        
542        // Send message on button click
543        document.getElementById('ai-chat-send').addEventListener('click', handleSendMessage);
544        
545        // Send message on Enter key
546        document.getElementById('ai-chat-input').addEventListener('keypress', (e) => {
547            if (e.key === 'Enter') {
548                handleSendMessage();
549            }
550        });
551        
552        console.log('AI Page Assistant ready!');
553    }
554
555    // Start the extension
556    init();
557})();