Fetch news from API and open in a new tab with responsive design and translation.
// ==UserScript==
// @name 新闻速递
// @namespace Violentmonkey Scripts
// @match *://*/*
// @grant GM_xmlhttpRequest
// @grant GM_openInTab
// @grant GM_registerMenuCommand
// @version 1.5
// @description Fetch news from API and open in a new tab with responsive design and translation.
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
const apiKey = 'dac6abc0634b4de08429b2580628dba8';
const apiUrl = `https://newsapi.org/v2/top-headlines?country=us&apiKey=${apiKey}`;
// Function to fetch and display news
function fetchAndDisplayNews() {
GM_xmlhttpRequest({
method: "GET",
url: apiUrl,
onload: function(response) {
if (response.status === 200) {
const data = JSON.parse(response.responseText);
if (data.articles && data.articles.length > 0) {
let newsContent = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新闻列表</title>
<style>
body { font-family: sans-serif; margin: 20px; }
h1 { text-align: center; }
ul { list-style: none; padding: 0; }
li { border: 1px solid #eee; padding: 15px; margin-bottom: 10px; border-radius: 5px; }
a { text-decoration: none; font-weight: bold; color: #333; }
p { color: #666; margin-top: 5px; }
a:hover { color: #0056b3; }
.translation { font-style: italic; color: #888; margin-top: 5px; }
@media (max-width: 600px) {
body { margin: 10px; }
li { padding: 10px; }
h1 {font-size: 1.5em;}
}
</style>
</head>
<body>
<h1>Latest News</h1>
<ul>
`;
const translatePromises = data.articles.map(async (article) => {
const translatedTitle = await translateText(article.title, 'en', 'zh-CN');
const translatedDescription = article.description ? await translateText(article.description, 'en', 'zh-CN') : 'No translation available.';
return { ...article, translatedTitle, translatedDescription };
});
Promise.all(translatePromises).then((translatedArticles) => {
translatedArticles.forEach(article => {
newsContent += `
<li>
<a href="${article.url}" target="_blank">${article.title}</a>
<p class="translation" style="color: green;">${article.translatedTitle}</p>
<p>${article.description || 'No description available.'}</p>
<p class="translation" style="color: green;">${article.translatedDescription}</p>
</li>
`;
});
newsContent += `
</ul>
</body>
</html>
`;
GM_openInTab(`data:text/html;charset=utf-8,${encodeURIComponent(newsContent)}`, { active: true });
});
} else {
alert('No news found.');
}
} else {
alert('Failed to fetch news. Status: ' + response.status);
}
},
onerror: function(error) {
console.error("Error fetching news:", error);
alert('An error occurred while fetching news.');
}
});
}
async function translateText(text, sourceLang, targetLang) {
if (!text) {
return '';
}
const encodedText = encodeURIComponent(text);
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sourceLang}&tl=${targetLang}&dt=t&q=${encodedText}`;
try {
const response = await fetch(url);
if (!response.ok) {
console.error("Translation API failed:", response.status);
return 'Translation failed.';
}
const data = await response.json();
return data[0][0][0];
} catch (error) {
console.error("Error during translation:", error);
return 'Translation failed.';
}
}
// Register the menu command
GM_registerMenuCommand("Fetch Latest News", fetchAndDisplayNews);
})();