// ==UserScript==
// @name AgebypassX – Webpack Edition
// @namespace https://github.com/Saganaki22/AgebypassX
// @version 1.3.0
// @description Modern age bypass for X.com using webpack chunk interception
// @author Saganaki22
// @license MIT
// @match https://x.com/*
// @match https://twitter.com/*
// @run-at document-start
// @grant none
// @homepageURL https://github.com/Saganaki22/AgebypassX
// @supportURL https://github.com/Saganaki22/AgebypassX/issues
// @connect none
// @noframes
// ==/UserScript==
(function () {
'use strict';
// 🔧 Configuration
const CONFIG = {
debug: false, // Set to true for console logs
maxWaitTime: 30000, // Stop waiting after 30 seconds
checkInterval: 500, // Check every 500ms
hidePrivacyWarning: true, // Auto-hide X's misleading warning
webpackChunkName: 'webpackChunk_twitter_responsive_web',
};
// 📊 Runtime State
const STATE = {
interceptCount: 0,
patchAttempts: 0,
isPatched: false,
lastPatchTime: null,
webpackHooked: false,
};
// 🎨 Inject UI Styles (status dot + tooltip)
const style = document.createElement('style');
style.textContent = `
#agebypassx-indicator {
position: fixed;
top: 20px;
right: 20px;
width: 18px;
height: 18px;
border-radius: 50%;
background: #ffa500;
border: 2px solid white;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
z-index: 9999999;
cursor: pointer;
transition: all 0.2s ease;
pointer-events: auto;
}
#agebypassx-indicator[data-state="ok"] {
background: #00ff66;
box-shadow: 0 0 15px rgba(0, 255, 102, 0.6);
}
#agebypassx-indicator[data-state="err"] {
background: #ff3333;
box-shadow: 0 0 15px rgba(255, 51, 51, 0.6);
}
#agebypassx-indicator[data-state="pending"] {
animation: agebypassx-pulse 1.5s infinite;
}
@keyframes agebypassx-pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.8; }
100% { transform: scale(1); opacity: 1; }
}
#agebypassx-tooltip {
position: fixed;
left: 0;
top: 0;
background: #111;
color: #fff;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
font-size: 13px;
border-radius: 8px;
padding: 12px;
max-width: 300px;
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
z-index: 9999999;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s;
border: 1px solid #333;
line-height: 1.5;
}
#agebypassx-tooltip::before {
content: '';
position: absolute;
top: -6px;
left: 16px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid #111;
}
`;
document.documentElement.appendChild(style);
// 🟡 Status Indicator Dot
const dot = document.createElement('div');
dot.id = 'agebypassx-indicator';
dot.dataset.state = 'pending';
dot.title = 'AgebypassX: Initializing...';
document.documentElement.appendChild(dot);
// 💬 Tooltip
const tooltip = document.createElement('div');
tooltip.id = 'agebypassx-tooltip';
document.documentElement.appendChild(tooltip);
// 🛠 Utility Functions
const log = (msg, data) => CONFIG.debug && console.log(`[AgebypassX] ${msg}`, data || '');
const warn = (msg, data) => console.warn(`[AgebypassX] ${msg}`, data || '');
function updateIndicator(state = 'ok', title = 'ACTIVE') {
dot.dataset.state = state;
dot.title = `AgebypassX: ${title}`;
STATE.isPatched = (state === 'ok');
}
function showTooltip(html) {
tooltip.innerHTML = html;
const rect = dot.getBoundingClientRect();
tooltip.style.left = `${rect.left - 140}px`;
tooltip.style.top = `${rect.bottom + 10}px`;
tooltip.style.opacity = 1;
}
function hideTooltip() {
tooltip.style.opacity = 0;
}
dot.addEventListener('mouseenter', () => {
const status = STATE.isPatched ? 'ACTIVE ✅' : 'FAILED ❌';
const webpackStatus = STATE.webpackHooked ? 'Hooked' : 'Not hooked';
const info = `
<strong>AgebypassX v1.3.0</strong><br>
Status: ${status}<br>
Webpack: ${webpackStatus}<br>
Intercepts: ${STATE.interceptCount}<br>
Patches: ${STATE.patchAttempts}<br>
Last: ${STATE.lastPatchTime || 'Never'}
`;
showTooltip(info);
});
dot.addEventListener('mouseleave', hideTooltip);
dot.addEventListener('click', () => {
alert(
`AgebypassX v1.3.0\n` +
`Status: ${STATE.isPatched ? 'ACTIVE' : 'FAILED'}\n` +
`Webpack: ${STATE.webpackHooked ? 'Hooked' : 'Not hooked'}\n` +
`Intercepts: ${STATE.interceptCount}\n` +
`Patches: ${STATE.patchAttempts}\n` +
`Last Patch: ${STATE.lastPatchTime || 'Never'}\n\n` +
`Debug: ${CONFIG.debug ? 'Enabled' : 'Disabled'}\n` +
`(Enable in CONFIG to see logs)`
);
});
// 🔧 Core: Patch webpack modules containing sensitive media settings
function patchWebpackModule(moduleId, moduleFunc) {
if (!moduleFunc || typeof moduleFunc !== 'function') return false;
try {
const funcStr = moduleFunc.toString();
// Look for sensitive media settings in the module
if (funcStr.includes('SensitiveMediaSettingsQuery') ||
funcStr.includes('view_adult_content') ||
funcStr.includes('can_user_allow_sensitive_content')) {
log(`Found sensitive media module ${moduleId}, attempting to patch`);
// This is where we would modify the module function
// For now, we'll just track that we found it
STATE.patchAttempts++;
STATE.lastPatchTime = new Date().toLocaleTimeString();
STATE.isPatched = true;
return true;
}
} catch (e) {
warn('Failed to patch webpack module', e);
}
return false;
}
// 🔁 Hook: Webpack Chunk Loading
function setupWebpackHook() {
try {
// Wait for webpack chunks to be available
const checkWebpack = () => {
if (window[CONFIG.webpackChunkName]) {
const webpackChunks = window[CONFIG.webpackChunkName];
// Hook the push method to intercept new chunks
const originalPush = webpackChunks.push.bind(webpackChunks);
webpackChunks.push = function(chunk) {
STATE.interceptCount++;
log('Intercepted webpack chunk', chunk);
// Check if this chunk contains sensitive media modules
if (chunk && chunk[1]) {
let patchedInChunk = false;
Object.keys(chunk[1]).forEach(moduleId => {
if (patchWebpackModule(moduleId, chunk[1][moduleId])) {
patchedInChunk = true;
}
});
if (patchedInChunk) {
updateIndicator('ok', 'ACTIVE - Patched');
}
}
return originalPush(chunk);
};
// Also check existing chunks
webpackChunks.forEach((chunk, index) => {
if (chunk && chunk[1]) {
Object.keys(chunk[1]).forEach(moduleId => {
patchWebpackModule(moduleId, chunk[1][moduleId]);
});
}
});
STATE.webpackHooked = true;
log('Webpack hook installed successfully');
return true;
}
return false;
};
// Try immediately, then poll
if (checkWebpack()) {
return true;
}
const interval = setInterval(() => {
if (checkWebpack()) {
clearInterval(interval);
}
}, CONFIG.checkInterval);
setTimeout(() => clearInterval(interval), CONFIG.maxWaitTime);
return false;
} catch (e) {
warn('Failed to hook webpack chunks', e);
return false;
}
}
// 🔍 Fallback: Hook fetch/XHR for GraphQL queries
function hookNetworkRequests() {
// Hook fetch for GraphQL requests
const originalFetch = window.fetch;
window.fetch = function(url, options) {
if (url && url.includes && (url.includes('graphql') || url.includes('SensitiveMediaSettingsQuery'))) {
log('Intercepted GraphQL request', url);
return originalFetch.apply(this, arguments).then(response => {
// Clone the response to read it without consuming the original
const clonedResponse = response.clone();
clonedResponse.json().then(data => {
log('GraphQL response data', data);
// Here we could potentially patch the response data
}).catch(() => {
// Ignore JSON parse errors
});
return response;
});
}
return originalFetch.apply(this, arguments);
};
log('Network request hooking enabled');
}
// 🧹 Remove X's misleading privacy warning
function hidePrivacyWarningBanner() {
if (!CONFIG.hidePrivacyWarning) return;
const observer = new MutationObserver(() => {
document.body.querySelectorAll('div, span, p').forEach(el => {
if (
el.innerText?.includes('privacy related extensions') ||
el.innerText?.includes('may cause issues on x.com')
) {
if (el.style.display !== 'none') {
el.style.display = 'none';
log('Hid misleading privacy warning banner');
}
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
}
// 🚀 Initialize
log('AgebypassX v3.0: Script loaded, initializing...');
// Step 1: Try webpack hook
if (!setupWebpackHook()) {
updateIndicator('pending', 'Waiting for webpack...');
log('Webpack hook setup initiated, waiting for chunks');
}
// Step 2: Start fallbacks
hookNetworkRequests();
hidePrivacyWarningBanner();
// Final status check
setTimeout(() => {
if (!STATE.isPatched) {
if (STATE.webpackHooked) {
updateIndicator('err', 'HOOKED - No sensitive media found');
warn('Webpack hooked but no sensitive media modules found');
} else {
updateIndicator('err', 'FAILED - No webpack chunks');
warn('Failed to hook webpack chunks. Age gate may appear.');
}
}
}, CONFIG.maxWaitTime + 1000);
// 🌐 Expose debug API
window.AgebypassX = {
state: STATE,
config: CONFIG,
version: '1.3.0',
forceWebpackCheck: setupWebpackHook,
showStatus: () => alert(`AgebypassX v3.0: ${STATE.isPatched ? 'ACTIVE' : 'FAILED'}`),
};
log('AgebypassX v3.0: Initialization complete');
})();