您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Generate a summary of any webpage or selected text using a local instance of g4f
当前为
// ==UserScript== // @name GPT4Free Page Summarizer (Local Free API) // @namespace http://tampermonkey.net/ // @version 1.3 // @description Generate a summary of any webpage or selected text using a local instance of g4f // @author SH3LL // @match *://*/* // @grant GM.xmlHttpRequest // ==/UserScript== function getPageText() { return document.body.innerText; } function getSelectedText() { return window.getSelection().toString(); } function summarizePage(textToSummarize, language, maxLines, callback) { const apiUrl = 'http://localhost:1337/v1/chat/completions'; const prompt = `Summarize the following text in ${language} in max ${maxLines} lines, in a clear, concise and text organised in paragraphs. Don't add any other sentence like "Here is the summary", write directly the summary itself. Here is the text: ${textToSummarize}`; const data = { messages: [{ role: 'user', content: prompt }], model: 'DeepSeek-V3', provider: 'Blackbox' }; GM.xmlHttpRequest({ method: 'POST', url: apiUrl, headers: { 'Content-Type': 'application/json' }, data: JSON.stringify(data), onload: function(response) { if (response.status >= 200 && response.status < 300) { try { const jsonResponse = JSON.parse(response.responseText); if (jsonResponse.choices && jsonResponse.choices[0].message && jsonResponse.choices[0].message.content) { callback(null, jsonResponse.choices[0].message.content, response.status); } else { callback('Unexpected format of the API response.', null, response.status); } } catch (error) { callback('Error parsing the API response: ' + error, null, response.status); } } else { callback('Error in the API call: ' + response.status + ' ' + response.statusText, null, response.status); } }, onerror: function(error) { callback('Network error during the API call: ' + error, null, null); } }); } (function() { 'use strict'; const languageNames = new Intl.DisplayNames(['it'], { type: 'language' }); const browserLanguage = navigator.language; const selectedLanguage = languageNames.of(browserLanguage); // Create a container for the Shadow DOM const shadowHost = document.createElement('div'); document.body.appendChild(shadowHost); const shadowRoot = shadowHost.attachShadow({ mode: 'open' }); // Create the sidebar within the Shadow DOM const sidebar = document.createElement('div'); sidebar.style.position = 'fixed'; sidebar.style.right = '-300px'; sidebar.style.top = '0'; sidebar.style.width = '300px'; sidebar.style.height = '100vh'; sidebar.style.backgroundColor = '#000000'; sidebar.style.color = '#ffffff'; sidebar.style.padding = '20px'; sidebar.style.zIndex = '999999'; // Increased to ensure it's above all elements sidebar.style.fontFamily = 'Arial, sans-serif'; sidebar.style.boxSizing = 'border-box'; sidebar.style.display = 'flex'; sidebar.style.flexDirection = 'column'; sidebar.style.gap = '10px'; sidebar.style.transition = 'right 0.3s ease'; shadowRoot.appendChild(sidebar); // Create the button to show/hide the sidebar const toggleButton = document.createElement('button'); toggleButton.textContent = '>'; toggleButton.style.position = 'fixed'; toggleButton.style.right = '0'; toggleButton.style.top = '20px'; toggleButton.style.backgroundColor = '#FFC107'; // Mustard yellow toggleButton.style.color = '#000000'; // White text toggleButton.style.border = 'none'; toggleButton.style.padding = '10px'; toggleButton.style.cursor = 'pointer'; toggleButton.style.zIndex = '1000000'; // Higher than sidebar toggleButton.style.fontSize = '14px'; toggleButton.style.transition = 'right 0.3s ease'; shadowRoot.appendChild(toggleButton); // Create the container for the button and selector const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.gap = '10px'; buttonContainer.style.alignItems = 'center'; sidebar.appendChild(buttonContainer); // Create the summarize button const summarizeButton = document.createElement('button'); summarizeButton.textContent = 'Summarize'; summarizeButton.style.backgroundColor = '#333333'; summarizeButton.style.color = '#ffffff'; summarizeButton.style.border = 'none'; summarizeButton.style.padding = '10px 20px'; summarizeButton.style.cursor = 'pointer'; summarizeButton.style.fontSize = '14px'; summarizeButton.style.flex = '1'; summarizeButton.style.transition = 'background-color 0.3s'; summarizeButton.onmouseover = () => summarizeButton.style.backgroundColor = '#4d4d4d'; summarizeButton.onmouseout = () => summarizeButton.style.backgroundColor = '#333333'; buttonContainer.appendChild(summarizeButton); // Create the line number selector const linesSelector = document.createElement('select'); linesSelector.style.backgroundColor = '#333333'; linesSelector.style.color = '#ffffff'; linesSelector.style.border = 'none'; linesSelector.style.padding = '10px'; linesSelector.style.fontSize = '14px'; linesSelector.style.cursor = 'pointer'; const lineOptions = [5, 10, 15, 20, 25, 30, 50, 100]; lineOptions.forEach(lines => { const option = document.createElement('option'); option.value = lines; option.textContent = `${lines} lines`; if (lines === 5) option.selected = true; linesSelector.appendChild(option); }); buttonContainer.appendChild(linesSelector); // Create the API status display with detected language const statusDisplay = document.createElement('div'); statusDisplay.style.fontSize = '12px'; statusDisplay.style.color = '#888888'; statusDisplay.textContent = `Status: Idle | Lang: ${selectedLanguage}`; sidebar.appendChild(statusDisplay); // Create the summary container const summaryContainer = document.createElement('div'); summaryContainer.style.fontSize = '14px'; summaryContainer.style.lineHeight = '1.5'; summaryContainer.style.display = 'none'; summaryContainer.style.overflowY = 'auto'; summaryContainer.style.maxHeight = 'calc(100vh - 130px)'; sidebar.appendChild(summaryContainer); // Variable to track if text is selected let isTextSelected = false; // Function to update the button text based on text selection function updateButtonText() { const selectedText = getSelectedText(); if (selectedText) { summarizeButton.textContent = `Summarize [${selectedText.substring(0, 2).trim().replace(/^\n+/, '').trim()}..]`; summarizeButton.style.fontSize = "14px"; isTextSelected = true; } else { summarizeButton.textContent = 'Summarize'; summarizeButton.style.fontSize = "14px"; isTextSelected = false; } } // Listen for text selection changes on the document document.addEventListener('mouseup', updateButtonText); document.addEventListener('mousedown', () => { setTimeout(updateButtonText, 100); }); // Handle sidebar visibility let isSidebarVisible = false; toggleButton.addEventListener('click', function() { if (isSidebarVisible) { sidebar.style.right = '-300px'; toggleButton.style.right = '0'; toggleButton.textContent = '>'; } else { sidebar.style.right = '0'; toggleButton.style.right = '300px'; toggleButton.textContent = '<'; } isSidebarVisible = !isSidebarVisible; }); // Listener for the summarize button summarizeButton.addEventListener('click', function() { summarizeButton.disabled = true; summarizeButton.textContent = 'Loading...'; statusDisplay.textContent = `Status: Requesting... | Lang: ${selectedLanguage}`; summaryContainer.style.display = 'none'; let textToSummarize = ''; if (isTextSelected) { textToSummarize = getSelectedText(); } else { textToSummarize = getPageText(); } const maxLines = parseInt(linesSelector.value, 10); summarizePage(textToSummarize, selectedLanguage, maxLines, function(error, summary, statusCode) { summarizeButton.disabled = false; updateButtonText(); if (error) { summaryContainer.textContent = 'Error: ' + error; summaryContainer.style.color = '#ff4444'; statusDisplay.textContent = `Status: Failed${statusCode ? ` (${statusCode})` : ''} | Lang: ${selectedLanguage}`; statusDisplay.style.color = '#ff4444'; } else { summaryContainer.textContent = summary; summaryContainer.style.color = '#ffffff'; statusDisplay.textContent = `Status: Success (${statusCode}) | Lang: ${selectedLanguage}`; statusDisplay.style.color = '#00ff00'; } summaryContainer.style.display = 'block'; }); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址