Jump to content

User:Polygnotus/Scripts/Surveys.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <nowiki>
// Wikipedia QuickSurveys Tracker for common.js
// Fetches surveys and displays them on your userpage

(function() {
    'use strict';

    // Configuration
    const QUICKSURVEYS_URL = 'https://en.wikipedia.org/w/load.php?modules=ext.quicksurveys.lib&debug=true';
    const MEDIAWICK_BASE_URL = 'https://en.wikipedia.org/wiki/MediaWiki:';

    // Track processed pages to prevent duplicates
    let processedPages = new Set();

    // Normalize coverage to a percentage string.
    // The MediaWiki QuickSurveys code treats coverage as a fraction in [0, 1]
    // (see `const control = 1 - survey.coverage` in lib.js), but some surveys
    // in the live data are misconfigured with values > 1 (e.g. 100).
    // Treat anything > 1 as already a percentage to avoid nonsense like 10000%.
    function formatCoveragePercent(coverage) {
        if (typeof coverage !== 'number' || isNaN(coverage)) {
            return 'unknown';
        }
        const percent = coverage > 1 ? coverage : coverage * 100;
        return percent.toFixed(1);
    }

    // Function to extract survey data from the loaded module
    function extractSurveyData(moduleText) {
        try {
            // Look for the surveyData.json content in the module
            const jsonStart = moduleText.indexOf('"resources/ext.quicksurveys.lib/surveyData.json":');
            if (jsonStart === -1) {
                console.log('No survey data found in module');
                return [];
            }

            // Find the start of the array
            const arrayStart = moduleText.indexOf('[', jsonStart);
            if (arrayStart === -1) {
                console.log('No array found in survey data');
                return [];
            }

            // Find the matching closing bracket
            let bracketCount = 0;
            let arrayEnd = arrayStart;
            for (let i = arrayStart; i < moduleText.length; i++) {
                if (moduleText[i] === '[') bracketCount++;
                if (moduleText[i] === ']') bracketCount--;
                if (bracketCount === 0) {
                    arrayEnd = i + 1;
                    break;
                }
            }

            let jsonString = moduleText.substring(arrayStart, arrayEnd);
            console.log('Extracted JSON length:', jsonString.length);
            console.log('JSON preview:', jsonString.substring(0, 300) + '...');

            const surveyData = JSON.parse(jsonString);
            console.log('Found survey data:', surveyData);

            const activeSurveys = [];

            surveyData.forEach(survey => {
                if (survey.name && survey.coverage >= 0) { // Show all surveys (including 0% coverage)
                    const surveyInfo = {
                        name: survey.name,
                        coverage: survey.coverage,
                        type: survey.type || 'unknown',
                        links: []
                    };

                    // Check for direct link property
                    if (survey.link) {
                        surveyInfo.links.push({
                            type: 'main',
                            key: survey.link,
                            url: MEDIAWICK_BASE_URL + formatLinkKey(survey.link)
                        });
                    }

                    // Check questions for links
                    if (survey.questions && Array.isArray(survey.questions)) {
                        survey.questions.forEach(question => {
                            if (question.link) {
                                surveyInfo.links.push({
                                    type: 'question',
                                    key: question.link,
                                    url: MEDIAWICK_BASE_URL + formatLinkKey(question.link)
                                });
                            }
                        });
                    }

                    activeSurveys.push(surveyInfo);
                }
            });

            return activeSurveys;
        } catch (error) {
            console.error('Error parsing survey data:', error);
            return [];
        }
    }

    // Format link key for MediaWiki URL (capitalize only the first letter)
    function formatLinkKey(key) {
        return key.charAt(0).toUpperCase() + key.slice(1);
    }

    // Display survey information in console/notification instead of updating userpage
    function displaySurveyInfo(surveys) {
        if (surveys.length === 0) {
            console.log('No surveys found in the QuickSurveys module');
            mw.notify('No surveys found in QuickSurveys module', { type: 'info' });
            return;
        }

        console.log('=== Wikipedia QuickSurveys ===');
        console.log(`Found ${surveys.length} survey(s):`);

        let notificationText = `Found ${surveys.length} survey(s): `;

        surveys.forEach((survey, index) => {
            console.log(`\n${index + 1}. ${survey.name}`);
            console.log(`   Type: ${survey.type}`);
            console.log(`   Coverage: ${formatCoveragePercent(survey.coverage)}%`);

            if (survey.links.length > 0) {
                console.log('   MediaWiki Links:');
                survey.links.forEach(link => {
                    console.log(`     - ${link.key}: ${link.url}`);
                });
            }

            notificationText += survey.name;
            if (index < surveys.length - 1) notificationText += ', ';
        });

        mw.notify(notificationText, { type: 'success', autoHide: false });
        console.log('\n=== End of QuickSurveys ===');
    }

    // Main function to fetch and process surveys (for manual checking)
    function fetchAndProcessSurveys() {
        console.log('Fetching QuickSurveys data...');

        fetch(QUICKSURVEYS_URL)
            .then(response => response.text())
            .then(moduleText => {
                console.log('Successfully fetched module data');
                const surveys = extractSurveyData(moduleText);
                console.log('Extracted surveys:', surveys);

                displaySurveyInfo(surveys);
            })
            .catch(error => {
                console.error('Error fetching survey data:', error);
                mw.notify('Error fetching QuickSurveys data: ' + error.message, { type: 'error' });
            });
    }

    // Generate survey display when viewing userpage
    function generateSurveyDisplay() {
        const currentPage = mw.config.get('wgPageName');
        const username = mw.config.get('wgUserName');
        const pageKey = `${currentPage}-${Date.now()}`;

        // Check if we've already processed this page recently (within 1 second)
        const now = Date.now();
        const recentProcessing = Array.from(processedPages).find(entry => {
            const [page, timestamp] = entry.split('-');
            return page === currentPage && (now - parseInt(timestamp)) < 1000;
        });

        if (recentProcessing) {
            console.log('Survey display recently processed, skipping...');
            return;
        }

        // Prevent duplicate execution by checking for existing elements
        if ($('#quicksurveys-display-box').length > 0) {
            console.log('Survey display already exists, skipping...');
            return;
        }

        // Add to processed pages
        processedPages.add(`${currentPage}-${now}`);

        // Clean up old entries (keep only last 10)
        if (processedPages.size > 10) {
            const sortedEntries = Array.from(processedPages).sort();
            processedPages = new Set(sortedEntries.slice(-10));
        }

        console.log('Generating survey display for userpage...');

        fetch(QUICKSURVEYS_URL)
            .then(response => response.text())
            .then(moduleText => {
                const surveys = extractSurveyData(moduleText);
                if (surveys.length === 0) {
                    return;
                }

                // Double-check that the element doesn't exist (race condition protection)
                if ($('#quicksurveys-display-box').length > 0) {
                    console.log('Survey display was created while fetching, skipping...');
                    return;
                }

                // Create a display box on the userpage
                const $surveyBox = $('<div>')
                    .attr('id', 'quicksurveys-display-box')
                    .css({
                        'border': '1px solid #a2a9b1',
                        'background-color': '#f8f9fa',
                        'padding': '10px',
                        'margin': '10px 0',
                        'border-radius': '3px'
                    })
                    .html('<strong>Wikipedia QuickSurveys</strong><br>');

                surveys.forEach(survey => {
                    $surveyBox.append(`<div style="margin: 5px 0;">
                        <strong>${survey.name}</strong> (${survey.type}, ${formatCoveragePercent(survey.coverage)}% coverage)
                    </div>`);

                    if (survey.links.length > 0) {
                        survey.links.forEach(link => {
                            $surveyBox.append(`<div style="margin-left: 15px; font-size: 0.9em;">
                                → <a href="${link.url}" target="_blank">${link.key}</a>
                            </div>`);
                        });
                    }
                });

                // Insert at the top of mw-content-text
                const $content = $('#mw-content-text');
                $content.prepend($surveyBox);
            })
            .catch(error => {
                console.error('Error fetching survey data for display:', error);
            });
    }

    // Add to window for manual execution
    window.updateQuickSurveys = fetchAndProcessSurveys;

    // Auto-run when on your userpage
    mw.hook('wikipage.content').add(function() {
        const currentPage = mw.config.get('wgPageName');
        const username = mw.config.get('wgUserName');

        if (username && currentPage === `User:${username}`) {
            // Use setTimeout to ensure DOM is ready and avoid race conditions
            setTimeout(() => {
                // Auto-generate survey display on userpage
                generateSurveyDisplay();
            }, 100); // Small delay to ensure DOM is ready
        }
    });

    console.log('QuickSurveys tracker loaded. Use window.updateQuickSurveys() to manually check, or visit your userpage to see surveys displayed automatically.');
})();
// </nowiki>