// ==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 = () => {
// Prevent redirection loop
if (config.isBypassSession) {
GM_setValue('isBypassSession', false);
return;
}
// Redirect logic
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();
})();