Perplexity Chat Summarizer

Tổng kết nhanh nội dung cuộc trò chuyện và tạo danh mục tiêu đề câu hỏi trên Perplexity.ai

Size

9.3 KB

Version

1.0.1

Created

Mar 27, 2026

Updated

19 days ago

1// ==UserScript==
2// @name		Perplexity Chat Summarizer
3// @description		Tổng kết nhanh nội dung cuộc trò chuyện và tạo danh mục tiêu đề câu hỏi trên Perplexity.ai
4// @version		1.0.1
5// @match		https://*.perplexity.ai/*
6// @icon		https://www.perplexity.ai/favicon.svg
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    // Hàm tạo sidebar cho danh mục câu hỏi
12    function createSidebar() {
13        // Tạo phần tử sidebar
14        const sidebar = document.createElement('div');
15        sidebar.id = 'perplexity-summary-sidebar';
16        sidebar.style.cssText = `
17            position: fixed;
18            right: 0;
19            top: 0;
20            width: 300px;
21            height: 100vh;
22            background-color: #f5f5f5;
23            border-left: 1px solid #ddd;
24            padding: 20px;
25            overflow-y: auto;
26            z-index: 10000;
27            transform: translateX(0);
28            transition: transform 0.3s ease;
29        `;
30        
31        // Thêm tiêu đề cho sidebar
32        const title = document.createElement('h2');
33        title.textContent = 'Danh mục câu hỏi';
34        title.style.cssText = `
35            margin-top: 0;
36            padding-bottom: 10px;
37            border-bottom: 1px solid #ddd;
38            display: flex;
39            justify-content: space-between;
40            align-items: center;
41        `;
42        
43        // Thêm nút đóng sidebar
44        const closeBtn = document.createElement('button');
45        closeBtn.textContent = '×';
46        closeBtn.style.cssText = `
47            background: none;
48            border: none;
49            font-size: 24px;
50            cursor: pointer;
51            color: #999;
52        `;
53        closeBtn.addEventListener('click', () => {
54            sidebar.style.transform = 'translateX(100%)';
55        });
56        title.appendChild(closeBtn);
57        sidebar.appendChild(title);
58        
59        // Tạo container cho danh sách câu hỏi
60        const listContainer = document.createElement('div');
61        listContainer.id = 'question-list-container';
62        sidebar.appendChild(listContainer);
63        
64        // Thêm sidebar vào body
65        document.body.appendChild(sidebar);
66        
67        return sidebar;
68    }
69
70    // Hàm trích xuất câu hỏi từ trang
71    function extractQuestions() {
72        try {
73            // Tìm tất cả các phần tử chứa câu hỏi trên trang Perplexity.ai
74            // Dựa trên cấu trúc DOM điển hình của Perplexity.ai
75            const questionElements = document.querySelectorAll('[data-testid="question"], .question-text, [class*="question"], h2, h3');
76            
77            const questions = [];
78            
79            // Nếu không tìm thấy phần tử câu hỏi cụ thể, tìm trong các tiêu đề
80            if (questionElements.length > 0) {
81                questionElements.forEach((element, index) => {
82                    const text = element.textContent.trim();
83                    // Chỉ thêm các tiêu đề không rỗng và có độ dài phù hợp
84                    if (text && text.length > 10 && text.length < 200) {
85                        questions.push({
86                            id: index + 1,
87                            title: text,
88                            element: element
89                        });
90                    }
91                });
92            } else {
93                // Nếu không tìm thấy phần tử câu hỏi, tạo dữ liệu mẫu
94                const sampleQuestions = [
95                    { id: 1, title: 'Cách sử dụng Perplexity.ai hiệu quả?', element: null },
96                    { id: 2, title: 'Perplexity.ai có những tính năng nổi bật nào?', element: null },
97                    { id: 3, title: 'So sánh Perplexity.ai với các công cụ AI khác', element: null }
98                ];
99                return sampleQuestions;
100            }
101            
102            // Loại bỏ các câu hỏi trùng lặp
103            const uniqueQuestions = questions.filter((question, index, self) =>
104                index === self.findIndex(q => q.title === question.title)
105            );
106            
107            return uniqueQuestions.slice(0, 10); // Giới hạn tối đa 10 câu hỏi
108        } catch (error) {
109            console.error('Lỗi khi trích xuất câu hỏi:', error);
110            // Trả về dữ liệu mẫu nếu có lỗi
111            return [
112                { id: 1, title: 'Cách sử dụng Perplexity.ai hiệu quả?', element: null },
113                { id: 2, title: 'Perplexity.ai có những tính năng nổi bật nào?', element: null },
114                { id: 3, title: 'So sánh Perplexity.ai với các công cụ AI khác', element: null }
115            ];
116        }
117    }
118
119    // Hàm tạo tóm tắt nội dung câu trả lời
120    function summarizeAnswer(answerElement) {
121        try {
122            // Nếu có phần tử câu trả lời, trích xuất nội dung văn bản
123            if (answerElement) {
124                const text = answerElement.textContent.trim();
125                // Tạo tóm tắt đơn giản bằng cách lấy một số câu đầu tiên
126                const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0);
127                const summary = sentences.slice(0, 3).join('. ') + '.';
128                return summary;
129            } else {
130                // Nếu không có phần tử câu trả lời, tạo tóm tắt mẫu
131                return 'Đây là tóm tắt nội dung câu trả lời cho câu hỏi. Nội dung sẽ bao gồm các điểm chính và thông tin quan trọng nhất.';
132            }
133        } catch (error) {
134            console.error('Lỗi khi tạo tóm tắt:', error);
135            return 'Không thể tạo tóm tắt cho nội dung này.';
136        }
137    }
138
139    // Hàm tạo danh sách câu hỏi trong sidebar
140    function populateQuestionList(questions) {
141        const container = document.getElementById('question-list-container');
142        if (!container) return;
143        
144        container.innerHTML = '';
145        
146        questions.forEach(question => {
147            const item = document.createElement('div');
148            item.className = 'question-item';
149            item.style.cssText = `
150                padding: 10px;
151                margin-bottom: 10px;
152                background-color: white;
153                border-radius: 5px;
154                cursor: pointer;
155                border: 1px solid #eee;
156                transition: all 0.2s ease;
157            `;
158            
159            // Tạo tiêu đề câu hỏi
160            const title = document.createElement('div');
161            title.className = 'question-title';
162            title.style.cssText = `
163                font-weight: bold;
164                margin-bottom: 5px;
165                color: #333;
166            `;
167            title.textContent = question.title;
168            
169            // Tạo tóm tắt câu trả lời
170            const summary = document.createElement('div');
171            summary.className = 'question-summary';
172            summary.style.cssText = `
173                font-size: 12px;
174                color: #666;
175                line-height: 1.4;
176            `;
177            summary.textContent = summarizeAnswer(question.element ? question.element.nextElementSibling : null);
178            
179            item.appendChild(title);
180            item.appendChild(summary);
181            
182            // Thêm sự kiện click để di chuyển đến đoạn hội thoại tương ứng
183            item.addEventListener('click', () => {
184                if (question.element) {
185                    // Cuộn đến phần tử câu hỏi
186                    question.element.scrollIntoView({ behavior: 'smooth', block: 'center' });
187                    
188                    // Thêm hiệu ứng highlight để làm nổi bật
189                    question.element.style.backgroundColor = '#ffff99';
190                    setTimeout(() => {
191                        question.element.style.backgroundColor = '';
192                    }, 2000);
193                }
194            });
195            
196            container.appendChild(item);
197        });
198    }
199
200    // Hàm khởi tạo extension
201    function init() {
202        // Đợi trang tải xong
203        if (document.readyState === 'loading') {
204            document.addEventListener('DOMContentLoaded', init);
205            return;
206        }
207        
208        // Tạo sidebar
209        const sidebar = createSidebar();
210        
211        // Trích xuất câu hỏi và tạo danh sách
212        const questions = extractQuestions();
213        populateQuestionList(questions);
214        
215        // Thêm nút để mở lại sidebar nếu đã đóng
216        const toggleBtn = document.createElement('button');
217        toggleBtn.textContent = '📋 Danh mục câu hỏi';
218        toggleBtn.style.cssText = `
219            position: fixed;
220            right: 10px;
221            top: 10px;
222            z-index: 9999;
223            background-color: #4a6cf7;
224            color: white;
225            border: none;
226            border-radius: 5px;
227            padding: 10px 15px;
228            cursor: pointer;
229            font-size: 14px;
230            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
231        `;
232        toggleBtn.addEventListener('click', () => {
233            sidebar.style.transform = 'translateX(0)';
234        });
235        document.body.appendChild(toggleBtn);
236    }
237
238    // Khởi chạy extension
239    init();
240})();