Google News Display

Display news on Google's homepage

Ekde 2023/11/12. Vidu La ĝisdata versio.

// ==UserScript==
// @name         Google News Display
// @description  Display news on Google's homepage
// @version      1.1
// @match        https://www.google.com/
// @match        https://www.google.com/webhp*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @namespace https://greasyfork.org/users/916589
// ==/UserScript==

(function () {
    // Fetch user's country code using ipapi.co
    async function getUserCountryCode() {
        try {
            const response = await fetch('https://ipapi.co/json');
            if (response.ok) {
                const data = await response.json();
                return data.country_code.toLowerCase();
            } else {
                console.error('Error fetching user country code:', response.statusText);
                // Return a default country code in case of an error
                return 'us';
            }
        } catch (error) {
            console.error('Error fetching user country code:', error);
            // Return a default country code in case of an error
            return 'us';
        }
    }

    // Get the user's country code
    getUserCountryCode().then((userCountryCode) => {
        // Fetch news data based on the user's country code
        const apiUrl = `https://personal-toolkit.genarunchisacoa.repl.co/news/alt?country=${userCountryCode}`;

        // Display loading text
        displayLoadingText();

        GM_xmlhttpRequest({
            method: 'GET',
            url: apiUrl,
            headers: {
                'User-Agent': 'Mozilla/5.0 (compatible; Greasemonkey; UserScript)',
                Accept: 'application/json',
            },
            onload: function (response) {
                if (response.status === 200) {
                    const newsData = JSON.parse(response.responseText);
                    // Display news once loaded
                    displayNews(newsData, userCountryCode);
                } else {
                    console.error('Error fetching news:', response.statusText);
                    // Display error message
                    displayErrorText('Error fetching news.');
                }
            },
            onerror: function (error) {
                console.error('Error fetching news:', error);
                // Display error message
                displayErrorText('Error fetching news.');
            },
        });
    });

    // Function to display loading text within the news container
    function displayLoadingText() {
        const newsContainer = document.createElement('div');
        newsContainer.classList.add('news-container');

        const loadingText = document.createElement('div');
        loadingText.textContent = 'Loading news...';
        loadingText.classList.add('loading-text');

        newsContainer.appendChild(loadingText);

        // Find the specified div on the Google homepage
        const targetDiv = document.querySelector('.FPdoLc.lJ9FBc');
        if (targetDiv) {
            // Insert the news container at the end
            targetDiv.appendChild(newsContainer);
        } else {
            console.error('Target div not found.');
        }
    }

    // Function to display error text within the news container
    function displayErrorText(errorMessage) {
        const newsContainer = document.querySelector('.news-container');
        if (newsContainer) {
            const errorText = document.createElement('div');
            errorText.textContent = errorMessage;
            errorText.classList.add('error-text');

            newsContainer.innerHTML = ''; // Clear loading text
            newsContainer.appendChild(errorText);
        } else {
            console.error('News container not found.');
        }
    }

// Function to get the country name from the country code using Navigator API
function getCountryNameFromCode(countryCode) {
    try {
        const countryName = new Intl.DisplayNames(['en'], { type: 'region' }).of(countryCode.toUpperCase());
        return countryName;
    } catch (error) {
        console.error('Error getting country name:', error);
        // Return the country code if an error occurs
        return countryCode;
    }
}

// Function to display news titles with links in grid items and insert them at the end of the specified div
function displayNews(newsData, userCountryCode) {
    const newsContainer = document.querySelector('.news-container');
    if (newsContainer) {
        // Clear loading text
        newsContainer.innerHTML = '';

        // Add heading for the news based on the user's country
        const userCountryHeading = document.createElement('h3');
        userCountryHeading.textContent = `News in ${getCountryNameFromCode(userCountryCode)}\n`;
        userCountryHeading.style.color = 'white';
        newsContainer.appendChild(userCountryHeading);

        // Iterate through each news item and create a grid item for the title with a link
        newsData.results.forEach((item) => {
            const newsItem = document.createElement('a');
            newsItem.classList.add('grid-item');
            newsItem.href = item.link;
            newsItem.target = '_blank'; // Open link in a new tab

            const newsTitle = document.createElement('div');
            newsTitle.textContent = item.title;
            newsTitle.classList.add('title-text');

            const newsDescription = document.createElement('div');
            newsDescription.classList.add('description-text');
            newsDescription.style.display = 'none'; // Hide description by default

            // Extract the first paragraph of the description and cut off at 160 characters
            const firstParagraph = item.description.split('\n\n')[0].substring(0, 160);

            // Add three dots if the description was truncated
            newsDescription.textContent =
                firstParagraph.length < item.description.length ? `${firstParagraph}...` : firstParagraph;

            // You might want to add additional styling or processing for each news title

            newsItem.appendChild(newsTitle);
            newsItem.appendChild(newsDescription);

            // Add event listener for hover
            newsItem.addEventListener('mouseenter', () => {
                // Display description on hover
                newsTitle.style.display = 'none';
                newsDescription.style.display = 'block';
            });

            newsItem.addEventListener('mouseleave', () => {
                // Hide description on leave
                newsTitle.style.display = 'block';
                newsDescription.style.display = 'none';
            });

            newsContainer.appendChild(newsItem);
        });
    } else {
        console.error('News container not found.');
    }
}

    // Add styles for grid items, news container, loading text, and error text
    GM_addStyle(`
        .news-container {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 20px;
            max-height: 220%; /* Adjust the max-height as needed */
            overflow-y: auto; /* Add a scroll if needed */
            margin-top: 20px; /* Adjust styling as needed */
            text-align: center; /* Center the text in the container */
            border: 1px solid #ddd; /* Add a border to the news container */
            padding: 10px; /* Add padding to the news container */
            background-color: #2d2c38;
        }

        .grid-item {
            border: 1px solid #ddd;
            padding: 10px;
            text-align: center;
            display: flex;
            align-items: center; /* Center the text vertically */
            justify-content: center; /* Center the text horizontally */
            text-decoration: none; /* Remove default link underline */
            color: white; /* Set link color */
            background-color: #2d2c38;
        }

        .grid-item:hover {
            background-color: #494857; /* Add a subtle background color on hover */
            transition: background-color 0.3s ease; /* Smooth transition for background color */
        }

        .loading-text, .error-text {
            font-size: 18px;
            font-weight: bold;
            color: white;
        }

        .error-text {
            color: red;
        }
    `);
})();