Is it Down? (Updated)

Pulls from TrackerStatus API and displays status on supported trackers

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Is it Down? (Updated)
// @version      0.6.2
// @namespace    https://trackerstatus.info/
// @description  Pulls from TrackerStatus API and displays status on supported trackers
// @match        https://redacted.sh/*
// @match        https://orpheus.network/*
// @match        https://passthepopcorn.me/*
// @match        https://broadcasthe.net/*
// @match        https://gazellegames.net/*
// @match        https://alpharatio.cc/*
// @match        https://anthelion.me/*
// @match        https://nebulance.io/*
// @grant        GM.xmlHttpRequest
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const Settings = {
        showIfStable: false,
        checkInterval: 120000, // check every 2 mins by default
        apiEndpoints: {
            'redacted.sh': 'https://red.trackerstatus.info/api/all/',
            'orpheus.network': 'https://ops.trackerstatus.info/api/all/',
            'passthepopcorn.me': 'https://ptp.trackerstatus.info/api/all/',
            'broadcasthe.net': 'https://btn.trackerstatus.info/api/all/',
            'gazellegames.net': 'https://ggn.trackerstatus.info/api/all/',
            'alpharatio.cc': 'https://ar.trackerstatus.info/api/all/',
            'anthelion.me': 'https://ant.trackerstatus.info/api/all/',
            'nebulance.io': 'https://nbl.trackerstatus.info/api/all/'
        }
    };

    const styles = `
        .tracker-status {
            position: fixed;
            z-index: 9999;
            box-sizing: border-box;
            width: 100%;
            display: none;
            padding: 0.2rem;
            bottom: 0;
            left: 0;
            font-size: 14px;
            text-align: center;
        }
        .tracker-status--stable { background-color: #056B00; }
        .tracker-status--offline { background-color: #A00E0E; }
        .tracker-status--unstable { background-color: #FFA500; }
        .tracker-status--both { background-color: #FF4B33; }
        .tracker-status__message {
            color: white;
            font-weight: bold;
            margin: 0;
            padding-right: 30px;
        }
        .tracker-status__link {
            color: white;
            text-decoration: underline;
        }
        .tracker-status__close {
            position: absolute;
            right: 10px;
            top: 50%;
            transform: translateY(-50%);
            color: white;
            font-size: 20px;
            cursor: pointer;
            border: none;
            background: none;
            padding: 0;
            width: 20px;
            height: 20px;
            line-height: 20px;
            text-align: center;
        }
        .tracker-status__close:hover {
            opacity: 0.8;
        }
        body {
            transition: margin-bottom 0.3s ease;
        }
    `;

    function createStatusElement() {
        const trackerStatus = document.createElement('div');
        trackerStatus.className = 'tracker-status';

        const message = document.createElement('p');
        message.className = 'tracker-status__message';

        const closeButton = document.createElement('button');
        closeButton.className = 'tracker-status__close';
        closeButton.innerHTML = '×';
        closeButton.title = 'Close';

        trackerStatus.appendChild(message);
        trackerStatus.appendChild(closeButton);
        document.body.append(trackerStatus);

        return { trackerStatus, closeButton };
    }

    function updateMarginBottom(trackerStatus) {
        const statusHeight = trackerStatus.offsetHeight;
        document.body.style.marginBottom = trackerStatus.style.display !== 'none' ? `${statusHeight}px` : '0';
    }

    function updateStatus(trackerStatus) {
        const currentDomain = window.location.hostname;
        const apiUrl = Settings.apiEndpoints[currentDomain];

        if (!apiUrl) {
            console.error('No API endpoint found for the current domain');
            return;
        }

        const infoUrl = apiUrl.replace('/api/all/', '');

        GM.xmlHttpRequest({
            method: 'GET',
            url: apiUrl,
            onload: function(response) {
                const messageElement = trackerStatus.querySelector('.tracker-status__message');

                if (response.status >= 200 && response.status < 400) {
                    let services;
                    try {
                        services = JSON.parse(response.responseText);
                    } catch (e) {
                        console.error('Failed to parse API response:', e);
                        trackerStatus.className = 'tracker-status tracker-status--offline';
                        messageElement.innerHTML = 'Error parsing tracker status.';
                        trackerStatus.style.display = 'block';
                        updateMarginBottom(trackerStatus);
                        return;
                    }

                    const entries = Object.entries(services);
                    const downServices = entries.filter(service => service[1].Status === '0');
                    const unstableServices = entries.filter(service => service[1].Status === '2');

                    let isStable = false;
                    if (downServices.length > 0 && unstableServices.length > 0) {
                        trackerStatus.className = 'tracker-status tracker-status--both';
                        messageElement.innerHTML = `The following services are currently offline or unstable: ${downServices.concat(unstableServices).map(service => service[0]).join(', ')}. <a class="tracker-status__link" href="${infoUrl}">More info</a>`;
                    } else if (downServices.length > 0) {
                        trackerStatus.className = 'tracker-status tracker-status--offline';
                        messageElement.innerHTML = `The following services are currently offline: ${downServices.map(service => service[0]).join(', ')}. <a class="tracker-status__link" href="${infoUrl}">More info</a>`;
                    } else if (unstableServices.length > 0) {
                        trackerStatus.className = 'tracker-status tracker-status--unstable';
                        messageElement.innerHTML = `The following services are unstable: ${unstableServices.map(service => service[0]).join(', ')}. <a class="tracker-status__link" href="${infoUrl}">More info</a>`;
                    } else {
                        isStable = true;
                        trackerStatus.className = 'tracker-status tracker-status--stable';
                        messageElement.textContent = 'All systems operational.';
                        trackerStatus.style.display = Settings.showIfStable ? 'block' : 'none';
                    }

                    if (!isStable && trackerStatus.style.display !== 'block') {
                        trackerStatus.style.display = 'block';
                    }
                } else {
                    console.error('Error fetching tracker status');
                    trackerStatus.className = 'tracker-status tracker-status--offline';
                    messageElement.innerHTML = 'Error fetching tracker status.';
                    trackerStatus.style.display = 'block';
                }

                updateMarginBottom(trackerStatus);
            },
            onerror: function(error) {
                console.error('Error fetching tracker status:', error);
                const messageElement = trackerStatus.querySelector('.tracker-status__message');
                trackerStatus.className = 'tracker-status tracker-status--offline';
                messageElement.innerHTML = 'Error fetching tracker status.';
                trackerStatus.style.display = 'block';

                updateMarginBottom(trackerStatus);
            }
        });
    }

    const styleElement = document.createElement('style');
    styleElement.textContent = styles;
    document.head.appendChild(styleElement);

    const { trackerStatus, closeButton } = createStatusElement();
    updateStatus(trackerStatus);
    const intervalId = setInterval(() => updateStatus(trackerStatus), Settings.checkInterval);

    closeButton.addEventListener('click', () => {
        trackerStatus.style.display = 'none';
        updateMarginBottom(trackerStatus);
        clearInterval(intervalId);
    });

    window.addEventListener('resize', () => {
        updateMarginBottom(trackerStatus);
    });
})();