Greasy Fork is available in English.

Newspaper Paywall Bypasser

Bypass the paywall on online newspapers

Versione datata 11/08/2016. Vedi la nuova versione l'ultima versione.

// ==UserScript==
// @name         Newspaper Paywall Bypasser
// @namespace    https://greasyfork.org/users/649
// @version      1.2.5
// @description  Bypass the paywall on online newspapers
// @author       Adrien Pyke
// @match        *://www.thenation.com/*
// @match        *://www.wsj.com/*
// @match        *://www.bostonglobe.com/*
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @noframes
// ==/UserScript==

(function() {
	'use strict';
	
	// short reference to unsafeWindow (or window if unsafeWindow is unavailable e.g. bookmarklet)
	var W = (typeof unsafeWindow === 'undefined') ? window : unsafeWindow;
	var SCRIPT_NAME = 'Newspaper Paywall Bypasser';

	/**
	* Sample Implementation:
	{
		name: 'something', // name of the implementation 
		match: "^https?://domain.com/.*", // the url to react to
		remove: '#element', // css selector to get element to remove 
		wait: 3000, // how many ms to wait before running (to wait for elements to load), or a css selector to keep trying until it returns an elem
		referer: 'something', // load content in with an xhr using this referrer
		replace: '#element', // css selector to get element to replace with xhr
		css: {}, // object, keyed by css selector of css rules
		bmmode: function() { } // function to call before doing anything else if in BM_MODE
	}
	* Any of the CSS selectors can be functions instead that return the desired value.
	*/

	var implementations = [{
		name: 'The Nation',
		match: "^https?://www.thenation.com/.*",
		remove: '#paywall',
		wait: '#paywall',
		bmmode: function() { Paywall.hide(); }
	}, {
		name: 'Wall Street Journal',
		match: "^https?://www.wsj.com/.*",
		referer: 'http://www.google.com',
		replace: '#article_sector > article > div:nth-of-type(1)'
	}, {
		name: 'Boston Globe',
		match: "^https?://www.bostonglobe.com/.*",
		css: {
			'html, body, #contain': {
				overflow: 'visible'
			},
			'.mfp-wrap, .mfp-ready': {
				display: 'none'
			}
		}
	}];

	// END OF IMPLEMENTATIONS

	var Util = {
		log: function () {
			var args = [].slice.call(arguments);
			args.unshift('%c' + SCRIPT_NAME + ':', 'font-weight: bold;color: #233c7b;');
			console.log.apply(console, args);
		},
		q: function(query, context) {
			return (context || document).querySelector(query);
		},
		qq: function(query, context) {
			return [].slice.call((context || document).querySelectorAll(query));
		}
	};

	var App = {
		currentImpName: null,
		
		appendStyle: function(css) {
			var out = '';
			for (var selector in css) {
				out += selector + '{';
				for (var rule in css[selector]) {
					out += rule + ':' + css[selector][rule] + '!important;';
				}
				out += '}';
			}
			
			var style = document.createElement('style');
			style.type = 'text/css';
			style.appendChild(document.createTextNode(out));
			document.head.appendChild(style);
		},

		bypass: function(imp) {
			if (W.BM_MODE && imp.bmmode) {
				imp.bmmode();
			}
			if (imp.css) {
				var cssObj = typeof imp.css === 'function' ? imp.css() : imp.css;
				App.appendStyle(cssObj);
			}
			if (imp.remove) {
				var elemToRemove = typeof imp.remove === 'function' ? imp.remove() : Util.q(imp.remove);
				elemToRemove.remove();
			}
			if (imp.referer) {
				var theReferer = typeof imp.referer === 'function' ? imp.referer() : imp.referer;
				GM_xmlhttpRequest ({
					method: 'GET',
					url: W.location.href,
					headers: {
						referer: theReferer
					},
					anonymous: true,
					onload: function(response) {
						Util.log('successfully loaded xhr with referer: ' + theReferer);
						if (imp.replace) {
							var replaceSelector = typeof imp.replace === 'function' ? imp.replace() : imp.replace;
							
							var tempDiv = document.createElement('div');
							tempDiv.innerHTML = response.responseText;
							
							Util.q(replaceSelector).innerHTML = Util.q(replaceSelector, tempDiv).innerHTML;
						} else {
							document.body.innerHTML = response.responseText;
						}
					},
					onerror: function(error) {
						Util.log('error occured when loading xhr with referer: ' + theReferer, 'error');
					}
				});
			}
		},

		waitAndBypass: function(imp) {
			if (imp.wait) {
				var waitType = typeof imp.wait;
				if(waitType === 'number') {
					setTimeout(App.bypass(imp), imp.wait || 0);
				} else {
					var isReady = waitType === 'function' ? imp.wait : function() {
						return Util.q(imp.wait);
					};
					var intervalId = setInterval(function() {
						if(isReady()) {
							Util.log('Condition fulfilled, bypassing');
							clearInterval(intervalId);
							App.bypass(imp);
						}
					}, 200);
				}
			} else {
				App.bypass(imp);
			}
		},

		start: function(imps) {
			Util.log('starting...');
			var success = imps.some(function(imp) {
				if (imp.match && (new RegExp(imp.match, 'i')).test(W.location.href)) {
					currentImpName = imp.name;
					App.waitAndBypass(imp);
					return true;
				}
			});

			if (!success) {
				Util.log('no implementation for ' + W.location.href, 'error');
			}
		}
	};

	App.start(implementations);
})();