ChuSyThang21
Member
Do nhu cầu tập đọc báo nên mình nhờ mấy con bot nó làm cho cái này.
Khi ấn ctrl i sẽ tiến hành phân tích và tóm tắt. Nhu cầu của mình là kiến thức liên quan đến kinh tế. nếu mọi người muốn bám sát nhu cầu về ngành nghề hay lĩnh vực cần lọc thông tin thì có thể custom lại theo ý của bản thân trong prompt. Hiện mình đang dùng ở mức "detail", chi tiết nhất. Các thím có thể ném đoạn prompt lên 1 con ai nào đó, rồi bảo "cho tôi 1 prompt như vậy với lĩnh vực xxx, yyy"
Ngoài phân tích bài, nó sẽ đưa thêm khái niệm, thuật ngữ các từ khóa, tài liệu mở rộng,... Tuy nhiên, nó vẫn là AI nên làm việc có thể thiếu xót.
Hiện mình đang dùng model Gemini thinking 0121 mới nhất của gemini.
Các thím lấy api key trong ai studio nhé, hàng free, chất lượng cũng ổn.
Còn 1 vài chỗ chủ yếu liên quan đến hiển thị nhưng mình bó tay rồi, không biết code mà bọn AI đoạn này cũng bị ngu nên ko lmj được.
Khi ấn ctrl i sẽ tiến hành phân tích và tóm tắt. Nhu cầu của mình là kiến thức liên quan đến kinh tế. nếu mọi người muốn bám sát nhu cầu về ngành nghề hay lĩnh vực cần lọc thông tin thì có thể custom lại theo ý của bản thân trong prompt. Hiện mình đang dùng ở mức "detail", chi tiết nhất. Các thím có thể ném đoạn prompt lên 1 con ai nào đó, rồi bảo "cho tôi 1 prompt như vậy với lĩnh vực xxx, yyy"
Ngoài phân tích bài, nó sẽ đưa thêm khái niệm, thuật ngữ các từ khóa, tài liệu mở rộng,... Tuy nhiên, nó vẫn là AI nên làm việc có thể thiếu xót.
Hiện mình đang dùng model Gemini thinking 0121 mới nhất của gemini.
Các thím lấy api key trong ai studio nhé, hàng free, chất lượng cũng ổn.
Còn 1 vài chỗ chủ yếu liên quan đến hiển thị nhưng mình bó tay rồi, không biết code mà bọn AI đoạn này cũng bị ngu nên ko lmj được.
Mã:
//
==UserScript==
// @name AI Studio Content Summarizer prove (Simplified - Ctrl+I Trigger)
// @namespace http://tampermonkey.net/
// @version 3.13-simplified
// @description Summarize webpage content using Google AI Studio API with Ctrl+I trigger. Giao diện được đơn giản hóa: nền trắng, chữ đen, cỡ chữ 14; tiêu đề cỡ 15, màu xanh đậm.
// @author Your Name
// @match *://*/*
// @grant GM_xmlhttpRequest
// @connect ai.google.dev
// @grant GM_addStyle
// ==/UserScript==
(function () {
'use strict';
// CHỈNH SỬA: Cài đặt CSS đơn giản, không có bóng đổ hay bo tròn, nền trắng & chữ đen, cỡ chữ 14; tiêu đề cỡ 15, màu xanh đậm.
GM_addStyle(`
.draggable {
cursor: move;
}
/* CHỈNH SỬA: Đơn giản hóa style cho thuật ngữ: chữ đen, in đậm, bỏ gạch chân */
.term {
color: black;
font-weight: bold;
cursor: pointer;
}
/* CHỈNH SỬA: Style cho các quan điểm được đơn giản hóa (chữ đen, in nghiêng, in đậm) */
.perspective {
color: black;
font-style: italic;
font-weight: bold;
}
/* CHỈNH SỬA: Loading indicator với nền trắng, chữ đen, không bo tròn, viền đơn giản */
#loading-indicator {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
padding: 10px 20px;
background-color: #fff;
color: #000;
border: 1px solid #ccc;
z-index: 10002;
display: none;
}
/* CHỈNH SỬA: Copy success message cũng được đơn giản hóa */
#copy-success-message {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
padding: 10px 20px;
background-color: #fff;
color: #000;
border: 1px solid #ccc;
z-index: 10002;
display: none;
}
/* CHỈNH SỬA: Popup tóm tắt với nền trắng, chữ đen, cỡ chữ 14, bỏ bóng đổ và bo tròn */
#summaryPopup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
padding: 20px;
width: 75vw;
max-width: none;
height: auto;
max-height: 85vh;
overflow-y: auto;
z-index: 10000;
border: 1px solid #ccc;
box-sizing: border-box;
font-family: Quicksand SemiBold, sans-serif;
font-size: 14px;
display: flex;
flex-direction: column;
color: black;
}
/* CHỈNH SỬA: Nút đóng popup được đơn giản hóa */
#summaryPopup .close-button {
position: absolute;
top: 10px;
right: 10px;
z-index: 1001;
padding: 8px 16px;
background-color: #ff4444;
color: #fff;
border: none;
cursor: pointer;
font-size: 14px;
}
/* CHỈNH SỬA: Nội dung tóm tắt giữ nguyên, hiển thị văn bản đơn giản */
#summaryPopup .summary-content {
overflow-y: auto;
max-height: 500px;
color: #000;
padding-right: 15px;
}
/* CHỈNH SỬA: Tiêu đề trong nội dung tóm tắt (ví dụ: "Phân tích và Tóm tắt") dùng cỡ 15px, màu xanh đậm */
#summaryPopup .summary-content h4 {
font-size: 15px;
color: #00008B;
margin-bottom: 5px;
}
/* CHỈNH SỬA: Panel thuật ngữ đơn giản, nền trắng, chữ đen, cỡ chữ 14 */
#termsPanel {
position: absolute;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
border: 1px solid #ccc;
padding: 20px;
z-index: 10001;
overflow-y: auto;
max-height: 85vh; /* Thêm max-height */
box-sizing: border-box;
font-family: Quicksand SemiBold, sans-serif;
font-size: 14px;
color: black;
display: flex;
flex-direction: column;
align-items: flex-start;
}
/* CHỈNH SỬA: Tiêu đề trong panel thuật ngữ (ví dụ: "Thuật ngữ và Khái niệm") dùng cỡ 15px, màu xanh đậm */
#termsPanel h3 {
margin-bottom: 7px;
font-size: 15px;
color: #00008B;
}
/* CHỈNH SỬA: Tiêu đề cho các phần quan điểm và tài liệu tham khảo bên trong panel thuật ngữ */
#termsPanel .perspective-section h4.perspective,
#termsPanel .resource-section h4.resource {
font-size: 15px;
color: #00008B;
}
/* CHỈNH SỬA: Định dạng đoạn văn trong panel thuật ngữ */
#termsPanel p {
margin-bottom: 8px;
line-height: 1.25;
text-align: justify;
}
#termsPanel p > b {
font-weight: bold;
display: block;
margin-bottom: 4px;
}
/* CHỈNH SỬA: Nút đóng panel thuật ngữ */
#termsPanel .close-button {
position: absolute;
top: 10px;
right: 10px;
z-index: 1002;
padding: 6px 12px;
background-color: #ff4444;
color: #fff;
border: none;
cursor: pointer;
font-size: 14px;
}
/* CHỈNH SỬA: Container cho các nút bên popup (không thay đổi) */
#summaryPopup > div:last-child {
z-index: 10003;
position: relative;
}
`);
// Các hàm chức năng còn lại giữ nguyên
function showLoadingIndicator() {
document.getElementById('loading-indicator').style.display = 'block';
}
function hideLoadingIndicator() {
document.getElementById('loading-indicator').style.display = 'none';
}
function showCopySuccessMessage() {
const messageDiv = document.getElementById('copy-success-message');
messageDiv.style.display = 'block';
setTimeout(() => {
messageDiv.style.display = 'none';
}, 2000);
}
function extractMainContent() {
const content = document.body.innerText.trim();
return content;
}
async function summarizeAndTranslate(content) {
let promptPrefix = `You are an expert analyst and translator with a background in international business. Analyze the following content and provide a comprehensive, insightful, and analytically deep conclusion in Vietnamese. Your analysis should go beyond simple summarization, aiming to extract maximum knowledge and understanding from the text. Present this as if you are a professional academic analyst deeply examining the article.\n\n`;
let formatInstructions = ``;
if (currentSummaryFormat === 'combined') {
formatInstructions = `Structure your analysis with an overview, followed by detailed sections for each main point, and conclude with a discussion of broader implications or applications. First, list the main points or ideas discussed in the article in separate sections, where each section is a bullet point, put inside a <b> tag to emphasize it. After that, for each bullet point, provide further detailed explanations, making connections, and drawing logical conclusions from all aspects discussed.`;
} else if (currentSummaryFormat === 'bullet_points') {
formatInstructions = `List only the main points or ideas discussed in the article as bullet points, put each bullet point inside a <b> tag to emphasize it. Be concise and precise but ensure to capture the core arguments.`;
} else if (currentSummaryFormat === 'paragraph') {
formatInstructions = `Provide a summary in paragraph form, capturing all main ideas and essential details in a flowing, natural style. Ensure the paragraph reflects a deep and analytical understanding of the content.`;
}
let lengthInstructions = ``;
if (currentSummaryLength === 'short') {
lengthInstructions = `The analysis should be concise, focusing on the most critical insights and arguments, approximately 30-40% of the original text length.`;
} else if (currentSummaryLength === 'medium') {
lengthInstructions = `The analysis should be moderately detailed, ensuring every significant point and keyword is fully represented, approximately 60-80% of the original text length.`;
} else if (currentSummaryLength === 'detailed') {
lengthInstructions = `Cover all major points, subpoints, and supporting arguments in depth, even exceeding the original length if needed to ensure comprehensive analysis. Aim for up to 90-110% of the original text length if necessary to ensure comprehensive coverage of all details.`;
}
const analysisInstructions = `\n\nIn addition to the detailed analysis and summary:\n\n1. **Knowledge Extraction and Critical Evaluation:** Extract key insights, arguments, evidence, and implications from the content. Provide a critical evaluation of the content, including strengths, weaknesses, and potential implications. Relate the content to relevant concepts in international business, finance, or economics, providing context where applicable. Include specific examples or illustrations from the content to clarify complex points. Assume the reader has a background in international business and highlight connections to global trade, finance, or economic policies.\n\n2. **Terminology and Concepts:** Identify 3-5 key terms or concepts that are crucial for understanding the content in the fields of finance, economics, and philosophy. For each term, provide a concise explanation in Vietnamese. Format each term and its explanation as follows: "[Term: term_name]Explanation: term_explanation[/Term]".\n\n3. **Perspective and School of Thought Analysis:** Identify any perspectives or schools of thought that are explicitly or implicitly mentioned or related to the content. For each perspective, provide a detailed and context-aware analysis in Vietnamese, focusing on:\n a) Relevance: Explain why this perspective is relevant to the content of the article and its core arguments.\n b) Key Tenets: Describe the core ideas or principles of this perspective as they are applied or reflected in the article, with specific examples if possible.\n c) Contextual Nuance: Analyze how the perspective is specifically nuanced or adapted within the context of the presented information, highlighting any specific interpretations or modifications within the article's arguments.\n Format each perspective as follows: "[Perspective: perspective_name]Analysis: perspective_analysis[/Perspective]". If no perspectives are identified, just output nothing for this section.\n\n4. **Further Exploration:** Suggest 2-3 additional resources or readings (books, articles, websites, etc.) for deeper exploration of the key concepts discussed in the content. List these resources with a brief explanation of their relevance. Format each resource as: "[Resource: resource_name]Description: resource_description[/Resource]". If no resources are suggested, just output nothing for this section.\n`;
const prompt = `${promptPrefix} ${formatInstructions} ${lengthInstructions} ${analysisInstructions} Ensure the writing style is formal, academic, and analytically rigorous, suitable for a professional analysis in international business. Write as if it was written by an expert human analyst. \n\nContent:\n${content}`;
showLoadingIndicator();
try {
GM_xmlhttpRequest({
method: 'POST',
url: `${API_URL}?key=${API_KEY}`,
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
contents: [
{
parts: [
{
text: prompt,
},
],
},
],
}),
onload: function (response) {
hideLoadingIndicator();
try {
if (response.status === 200) {
const result = JSON.parse(response.responseText);
if (result.candidates && result.candidates.length > 0) {
const summaryResponse = result.candidates[0].content.parts[0].text;
displaySummary(summaryResponse);
} else if (result.error) {
console.error('API Error:', result.error);
showError('Lỗi API: ' + result.error.message + ' (Mã lỗi: ' + result.error.code + '). Vui lòng thử lại sau.');
} else {
console.warn('No conclusion generated:', result);
showError('Không tạo được tóm tắt. Vui lòng thử lại.');
}
} else {
console.error('HTTP Error:', response.status, response.statusText, response);
showError('Lỗi HTTP: ' + response.status + ' - ' + response.statusText + '. Vui lòng kiểm tra kết nối mạng và thử lại.');
}
} catch (error) {
console.error('Error parsing API response:', error, response.responseText);
showError('Lỗi xử lý phản hồi từ API. Vui lòng thử lại.');
}
},
onerror: function (error) {
hideLoadingIndicator();
console.error('Error summarizing content (GM_xmlhttpRequest error):', error);
showError('Lỗi khi tóm tắt nội dung. Vui lòng thử lại.');
},
});
} catch (error) {
hideLoadingIndicator();
console.error('Error during API request (try/catch error):', error);
showError('Lỗi trong quá trình gửi yêu cầu đến API. Vui lòng thử lại.');
}
}
function displaySummary(summaryResponse) {
let summaryDiv = document.getElementById('summaryPopup');
if (summaryDiv) {
summaryDiv.remove();
}
summaryDiv = document.createElement('div');
summaryDiv.id = 'summaryPopup';
summaryDiv.classList.add('draggable');
const savedPosition = localStorage.getItem('summaryPopupPosition');
if (savedPosition) {
const pos = JSON.parse(savedPosition);
summaryDiv.style.top = pos.top + 'px';
summaryDiv.style.left = pos.left + 'px';
} else {
summaryDiv.style.top = '50%';
summaryDiv.style.left = '50%';
summaryDiv.style.transform = 'translate(-50%, -50%)';
}
// Các style cho summaryDiv được điều khiển bởi CSS trong GM_addStyle
let summaryText = summaryResponse;
let formattedSummary = "";
const termRegex = /\[Term:([^\]]*)\]Explanation:([^\[]*)\[\/Term\]/g;
let terms = {};
let formattedTerms = "";
summaryText = summaryText.replace(termRegex, (match, termName, termExplanation) => {
const termId = termName.trim().replace(/\s+/g, '_').toLowerCase();
terms[termId] = termExplanation.trim();
formattedTerms += `<p><b>${termName.trim()}:</b> ${termExplanation.trim()}</p>`;
return `<span class="term">${termName.trim()}</span>`;
});
if (currentSummaryFormat === 'combined' || currentSummaryFormat === 'bullet_points') {
const cleanedSummary = summaryText.replace(/(\*\*)(.*?)\1/g, '<b>$2</b>');
formattedSummary = cleanedSummary.split('\n').map(line => {
if (line.startsWith('<b>')) {
return `<h4>${line}</h4>`;
} else if (currentSummaryFormat === 'combined') {
return `<p style="margin-left: 20px; margin-bottom: 10px; text-align: justify;">${line}</p>`;
} else {
return '';
}
}).join('');
} else if (currentSummaryFormat === 'paragraph') {
formattedSummary = summaryText.split('\n').map(line => {
return `<p style="margin-bottom: 10px; text-align: justify;">${line}</p>`;
}).join('');
}
const perspectiveRegex = /\[Perspective:([^\]]*)\]Analysis:([^\[]*)\[\/Perspective\]/g;
formattedSummary = formattedSummary.replace(perspectiveRegex, (match, perspectiveName, perspectiveAnalysis) => {
return `<div class="perspective-section"><h4 class="perspective">Quan điểm: ${perspectiveName.trim()}</h4><p style="margin-left: 10px; margin-bottom: 10px; text-align: justify; font-style: italic;">${perspectiveAnalysis.trim()}</p></div>`;
});
const resourceRegex = /\[Resource:([^\]]*)\]Description:([^\[]*)\[\/Resource\]/g;
formattedSummary = formattedSummary.replace(resourceRegex, (match, resourceName, resourceDescription) => {
return `<div class="resource-section"><h4 class="resource">Tài liệu tham khảo: ${resourceName.trim()}</h4><p style="margin-left: 10px; margin-bottom: 10px; text-align: justify;">${resourceDescription.trim()}</p></div>`;
});
const summarySection = document.createElement('div');
summarySection.innerHTML = `<h3>Phân tích và Tóm tắt</h3><div class="summary-content">${formattedSummary}</div>`;
summaryDiv.appendChild(summarySection);
const termsSection = document.createElement('div');
termsSection.id = 'termsSection';
termsSection.style.marginTop = '10px';
const expandButton = document.createElement('button');
expandButton.innerText = 'Mở rộng Thuật ngữ và Khái niệm';
expandButton.style.padding = '8px 16px';
expandButton.style.backgroundColor = '#007bff';
expandButton.style.color = '#fff';
expandButton.style.border = 'none';
expandButton.style.cursor = 'pointer';
expandButton.onclick = () => {
const termsPanel = document.createElement('div');
termsPanel.id = 'termsPanel';
termsPanel.style.position = 'absolute';
termsPanel.style.top = '0';
termsPanel.style.left = '0';
// Các style còn lại được quản lý bởi CSS
const termsContent = document.createElement('div');
termsContent.innerHTML = `<h3>Thuật ngữ và Khái niệm</h3><div>${formattedTerms}</div>`;
termsPanel.appendChild(termsContent);
const closeButton = document.createElement('button');
closeButton.innerText = 'Đóng lại';
closeButton.className = 'close-button';
closeButton.onclick = () => termsPanel.remove();
termsPanel.appendChild(closeButton);
summaryDiv.appendChild(termsPanel);
};
termsSection.appendChild(expandButton);
summaryDiv.appendChild(termsSection);
const buttonsContainer = document.createElement('div');
buttonsContainer.style.marginTop = '10px';
buttonsContainer.style.display = 'flex';
buttonsContainer.style.gap = '10px';
summaryDiv.appendChild(buttonsContainer);
const copyButton = document.createElement('button');
copyButton.innerText = 'Sao chép';
copyButton.style.padding = '8px 16px';
copyButton.style.backgroundColor = '#007bff';
copyButton.style.color = '#fff';
copyButton.style.border = 'none';
copyButton.style.cursor = 'pointer';
copyButton.onclick = () => {
navigator.clipboard.writeText(summaryResponse);
showCopySuccessMessage();
};
buttonsContainer.appendChild(copyButton);
const closeButton = document.createElement('button');
closeButton.innerText = 'Đóng';
closeButton.style.padding = '8px 16px';
closeButton.style.backgroundColor = '#ff4444';
closeButton.style.color = '#fff';
closeButton.style.border = 'none';
closeButton.style.cursor = 'pointer';
closeButton.onclick = () => summaryDiv.remove();
buttonsContainer.appendChild(closeButton);
makeDraggable(summaryDiv);
document.body.appendChild(summaryDiv);
}
function showError(message) {
const errorDiv = document.createElement('div');
errorDiv.style.position = 'fixed';
errorDiv.style.bottom = '20px';
errorDiv.style.right = '20px';
errorDiv.style.backgroundColor = '#fff';
errorDiv.style.border = '1px solid #ff4444';
errorDiv.style.padding = '20px';
errorDiv.style.zIndex = '10000';
errorDiv.style.maxWidth = '400px';
errorDiv.style.fontFamily = 'Quicksand SemiBold, sans-serif';
errorDiv.innerHTML = `<h3 style="margin-top: 0; color: #ff4444;">Lỗi</h3><p style="color: #000;">${message}</p>`;
const closeButton = document.createElement('button');
closeButton.innerText = 'Đóng';
closeButton.style.marginTop = '10px';
closeButton.style.padding = '8px 16px';
closeButton.style.backgroundColor = '#ff4444';
closeButton.style.color = '#fff';
closeButton.style.border = 'none';
closeButton.style.cursor = 'pointer';
closeButton.onclick = () => errorDiv.remove();
errorDiv.appendChild(closeButton);
document.body.appendChild(errorDiv);
}
function makeDraggable(element) {
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
element.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
element.style.top = (element.offsetTop - pos2) + "px";
element.style.left = (element.offsetLeft - pos1) + "px";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
localStorage.setItem('summaryPopupPosition', JSON.stringify({ top: element.offsetTop, left: element.offsetLeft }));
}
}
function main() {
const loadingIndicator = document.createElement('div');
loadingIndicator.id = 'loading-indicator';
loadingIndicator.innerText = 'Đang tải tóm tắt...';
document.body.appendChild(loadingIndicator);
const copySuccessMessage = document.createElement('div');
copySuccessMessage.id = 'copy-success-message';
copySuccessMessage.innerText = 'Đã sao chép!';
document.body.appendChild(copySuccessMessage);
document.addEventListener('keydown', function(event) {
if (event.ctrlKey && (event.key === 'i' || event.key === 'I')) {
event.preventDefault();
const content = extractMainContent();
summarizeAndTranslate(content);
}
});
}
const API_KEY = 'THAY API KEY VÀO ĐÂY';
const API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-thinking-exp-01-21:generateContent';
const summaryLengthOptions = {
'short': 'Ngắn gọn',
'medium': 'Vừa phải',
'detailed': 'Chi tiết'
};
let currentSummaryLength = 'detailed';
const summaryFormatOptions = {
'combined': 'Kết hợp (Ý chính + Giải thích)',
'bullet_points': 'Chỉ Ý chính (Bullet points)',
'paragraph': 'Đoạn văn'
};
let currentSummaryFormat = 'combined';
main();
})();

