Medium Member Bypass

Modern Medium GUI with multiple bypass services.

Version au 16/12/2024. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey 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 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         Medium Member Bypass
// @author       UniverseDev
// @license      GPL-3.0-or-later
// @namespace    http://tampermonkey.net/
// @version      12.9
// @description  Modern Medium GUI with multiple bypass services.
// @match        *://*.medium.com/*
// @match        https://freedium.cfd/*
// @match        https://readmedium.com/*
// @match        https://md.vern.cc/*
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(() => {
    'use strict';

    const config = {
        bypassUrls: {
            freedium: 'https://freedium.cfd',
            readmedium: 'https://readmedium.com',
            libmedium: 'https://md.vern.cc/',
        },
        currentBypass: GM_getValue('currentBypass', 'freedium'),
        memberOnlyDivSelector: 'p.bf.b.bg.z.bk',
        autoRedirectDelay: GM_getValue('redirectDelay', 5000),
        autoRedirectEnabled: GM_getValue('autoRedirect', true),
        darkModeEnabled: GM_getValue('darkModeEnabled', false),
        isBypassSession: GM_getValue('isBypassSession', false),
    };

    const injectStyles = () => {
        const style = document.createElement('style');
        style.textContent = `
            .medium-settings {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                width: 360px;
                background-color: var(--background-color, white);
                box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
                border-radius: 16px;
                font-family: 'Arial', sans-serif;
                z-index: 10000;
                padding: 20px;
                display: none;
                color: var(--text-color, #333);
                cursor: grab;
            }
            .medium-settings.dark {
                --background-color: #333;
                --text-color: white;
            }
            .medium-settings-header {
                font-size: 22px;
                font-weight: bold;
                margin-bottom: 20px;
                text-align: center;
            }
            .medium-settings-toggle {
                margin: 15px 0;
                display: flex;
                justify-content: space-between;
                align-items: center;
            }
            .medium-settings-input {
                margin-left: 10px;
                width: 70px;
                padding: 6px;
                text-align: center;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
            .medium-settings-button {
                background-color: var(--button-bg-color, #1a8917);
                color: var(--button-text-color, white);
                border: none;
                padding: 8px 14px;
                border-radius: 20px;
                cursor: pointer;
                font-weight: bold;
                transition: background-color 0.3s;
            }
            .medium-settings-button:hover {
                background-color: #155c11;
            }
            .medium-notification {
                position: fixed;
                bottom: 20px;
                right: 20px;
                background-color: #1a8917;
                color: white;
                padding: 15px;
                border-radius: 20px;
                box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
                font-family: 'Arial', sans-serif;
                z-index: 10000;
                opacity: 0;
                transform: translateY(20px);
                transition: all 0.3s ease;
            }
            .medium-notification.show {
                opacity: 1;
                transform: translateY(0);
            }
        `;
        document.head.appendChild(style);
    };

    const stealthNotification = (message) => {
        const notification = document.createElement('div');
        notification.className = 'medium-notification';
        notification.textContent = message;
        document.body.appendChild(notification);

        setTimeout(() => notification.classList.add('show'), 50);
        setTimeout(() => {
            notification.classList.remove('show');
            setTimeout(() => notification.remove(), 300);
        }, 3000);
    };

    const showMediumSettings = () => {
        let existingPanel = document.querySelector('.medium-settings');
        if (existingPanel) {
            existingPanel.style.display = 'block';
            return;
        }

        const settingsContainer = document.createElement('div');
        settingsContainer.className = `medium-settings ${config.darkModeEnabled ? 'dark' : ''}`;

        settingsContainer.innerHTML = `
            <div class="medium-settings-header">Medium Settings</div>
            <div class="medium-settings-toggle">
                <span>Auto-Redirect</span>
                <button class="medium-settings-button" id="toggleRedirect">${config.autoRedirectEnabled ? 'ON' : 'OFF'}</button>
            </div>
            <div class="medium-settings-toggle">
                <span>Redirect Delay (ms)</span>
                <input type="number" class="medium-settings-input" id="redirectDelay" value="${config.autoRedirectDelay}" />
            </div>
            <div class="medium-settings-toggle">
                <span>Dark Mode</span>
                <button class="medium-settings-button" id="toggleDarkMode">${config.darkModeEnabled ? 'ON' : 'OFF'}</button>
            </div>
            <div class="medium-settings-toggle">
                <span>Bypass Service</span>
                <select id="bypassSelector" class="medium-settings-input">
                    ${Object.keys(config.bypassUrls).map((key) => `
                        <option value="${key}" ${config.currentBypass === key ? 'selected' : ''}>${key}</option>
                    `).join('')}
                </select>
            </div>
            <div class="medium-settings-toggle">
                <button class="medium-settings-button" id="bypassNow">Bypass Now</button>
            </div>
            <div class="medium-settings-toggle">
                <button class="medium-settings-button" id="resetDefaults">Reset to Default</button>
            </div>
            <div class="medium-settings-toggle">
                <button class="medium-settings-button" id="saveSettings">Save</button>
                <button class="medium-settings-button" id="closeSettings">Close</button>
            </div>
        `;

        document.body.appendChild(settingsContainer);

        let isDragging = false;
        let startX, startY;

        settingsContainer.addEventListener('mousedown', (e) => {
            isDragging = true;
            startX = e.clientX - settingsContainer.offsetLeft;
            startY = e.clientY - settingsContainer.offsetTop;
            settingsContainer.style.cursor = 'grabbing';
        });

        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            settingsContainer.style.left = `${e.clientX - startX}px`;
            settingsContainer.style.top = `${e.clientY - startY}px`;
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
            settingsContainer.style.cursor = 'grab';
        });

        settingsContainer.querySelector('#toggleRedirect').addEventListener('click', () => {
            config.autoRedirectEnabled = !config.autoRedirectEnabled;
            GM_setValue('autoRedirect', config.autoRedirectEnabled);
            settingsContainer.querySelector('#toggleRedirect').textContent = config.autoRedirectEnabled ? 'ON' : 'OFF';
            stealthNotification('Auto-Redirect toggled');
        });

        settingsContainer.querySelector('#toggleDarkMode').addEventListener('click', () => {
            config.darkModeEnabled = !config.darkModeEnabled;
            GM_setValue('darkModeEnabled', config.darkModeEnabled);
            settingsContainer.classList.toggle('dark', config.darkModeEnabled);
            settingsContainer.querySelector('#toggleDarkMode').textContent = config.darkModeEnabled ? 'ON' : 'OFF';
            stealthNotification('Dark Mode toggled');
        });

        settingsContainer.querySelector('#bypassSelector').addEventListener('change', (e) => {
            config.currentBypass = e.target.value;
            GM_setValue('currentBypass', config.currentBypass);
            stealthNotification(`Bypass service set to ${config.currentBypass}`);
        });

        settingsContainer.querySelector('#bypassNow').addEventListener('click', () => {
            window.location.href = config.bypassUrls[config.currentBypass] + window.location.pathname;
        });

        settingsContainer.querySelector('#resetDefaults').addEventListener('click', () => {
            config.autoRedirectDelay = 5000;
            config.autoRedirectEnabled = true;
            config.darkModeEnabled = false;
            config.currentBypass = 'freedium';

            GM_setValue('redirectDelay', config.autoRedirectDelay);
            GM_setValue('autoRedirect', config.autoRedirectEnabled);
            GM_setValue('darkModeEnabled', config.darkModeEnabled);
            GM_setValue('currentBypass', config.currentBypass);

            settingsContainer.querySelector('#redirectDelay').value = config.autoRedirectDelay;
            settingsContainer.querySelector('#toggleRedirect').textContent = 'ON';
            settingsContainer.querySelector('#toggleDarkMode').textContent = 'OFF';
            settingsContainer.querySelector('#bypassSelector').value = 'freedium';
            settingsContainer.classList.remove('dark');
            stealthNotification('Settings reset to defaults');
        });

        settingsContainer.querySelector('#saveSettings').addEventListener('click', () => {
            const newDelay = parseInt(settingsContainer.querySelector('#redirectDelay').value, 10);
            if (!isNaN(newDelay) && newDelay >= 0) {
                config.autoRedirectDelay = newDelay;
                GM_setValue('redirectDelay', newDelay);
                stealthNotification('Settings saved');
            }
        });

        settingsContainer.querySelector('#closeSettings').addEventListener('click', () => {
            settingsContainer.style.display = 'none';
        });

        settingsContainer.style.display = 'block';
    };

    const performAutoRedirect = () => {
        if (config.isBypassSession) {
            GM_setValue('isBypassSession', false);
            return;
        }

        if (config.autoRedirectEnabled && document.querySelector(config.memberOnlyDivSelector)) {
            setTimeout(() => {
                window.location.href = config.bypassUrls[config.currentBypass] + window.location.pathname;
            }, config.autoRedirectDelay);
            stealthNotification('Redirecting to bypass service...');
        }
    };

    const initializeScript = () => {
        injectStyles();

        const isBypassPage = Object.values(config.bypassUrls).some((url) => window.location.href.startsWith(url));

        if (isBypassPage) {
            GM_setValue('isBypassSession', true);
        } else if (window.location.href.startsWith('https://medium.com/')) {
            GM_registerMenuCommand('Open Medium Settings', showMediumSettings);
            performAutoRedirect();
        }
    };

    initializeScript();
})();