Steam DRM Highlighter Revenant

Highlight DRM-related words in Steam Store pages.

目前為 2016-02-03 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Steam DRM Highlighter Revenant
// @namespace    bf83963f-fffc-4c93-98ee-bc11e23e2176
// @author       Rebecca Menessec (fr. Denilson Sá)
// @version      1.7.0
// @description  Highlight DRM-related words in Steam Store pages.
// @icon         data:image/png;base64,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
// @encoding     utf-8
// @include      http://store.steampowered.com/app/*
// @include      http://store.steampowered.com/sub/*
// @include      https://store.steampowered.com/app/*
// @include      https://store.steampowered.com/sub/*
// ==/UserScript==

(function() {

	var bad_words = [
		/3rd-party DRM/gi
		,/\bSecuROM.?\b/gi
		,/\bTAGES\b/gi
		,/\bGameShield\b/gi
		,/\bSolidshield\b/gi
		,/\bStarforce\b/gi
		,/\bUniloc\b/gi
		,/\bUplay\b/gi
		,/\b\origin\.com\b/gi
		,/\bOrigin\b/g
		,/\bStardock\.com\b/gi
		,/FrontLine ProActive/gi
		,/Square Enix account/gi
		,/(Microsoft ?)?Games For Windows( ?. ?)?( ?LIVE)/gi
		,/www\.gamesforwindows\.com/gi
		,/activate\.ea\.com(\/deauthorize)?/gi
		,/EA (Access|Account)/gi
		,/Kalypso account/gi
		,/Microsoft SSA/gi
		,/Ubisoft’?s? Online Services?( Platform)?/gi
		,/(permanent |persistent )(high speed )?Internet( connection| access)?/gi
		,/SINGLE-USE SERIAL CODE/gi
		,/INTERNET CONNECTION.* REQUIRED TO PLAY/gi
		,/CREATION OF( A| AN)? UBISOFT ACCOUNT/gi
		,/([0-9]+ |unlimited )?(per (week|month|year) |total )?(machines? )?activations?( limit)?/gi

		// Matching whitespace to reduce false-positives.
		,/^\s*\bReality Pump\b\s*$/gi
		// This version matches in http://store.steampowered.com/sub/13656/
		,/DRM Reality Pump\b/gi

		// These games use Game For Windows, but that's not described at their
		// store pages
		,/^\s*Kane (&|and) Lynch: Dead Men.?\s*$/g
		,/^\s*Section 8\s*$/g
		,/^\s*Stormrise\s*$/g
		,/^\s*The Club.?\s*$/g
	];

	var ignored_tags = {
		'embed':''
		,'object':''
		,'applet':''
		,'style':''
		,'script':''
		,'input':''
		,'textarea':''
		,'button':''
		,'select':''
		,'option':''
	}


	// List of bad words found at this page
	var found_in_this_page = [];


	// Adds a new match to the found_in_this_page array.
	// Returns the added element.
	function add_match_to_page_list(text, element)
	{
		var new_match = {
			'text' : text.trim()
			,'element' : element
			,'index' : found_in_this_page.length
			,'id' : 'bad_word_' + this.index
		};

		found_in_this_page.push(new_match);
		return new_match;
	}


	// Creates and returns a new element like this:
	// <span class="bad_word" id="bad_word_3">text</span>
	function createBadWordElement(text)
	{
		var elem = document.createElement('span');
		var found = add_match_to_page_list(text, elem);
		elem.setAttribute('class', 'bad_word');
		elem.setAttribute('id', found.id);
		elem.appendChild(document.createTextNode(text));
		return elem;
	}


	// This function receives a list of text elements, and makes the highlight
	// in-place, directly in those elements. However, while doing so, some
	// elements are created and others are deleted. Thus, this function also
	// returns a new list of text elements (that can be passed again for
	// highlighting other words).
	//
	// This function was loosely based on:
	// http://userscripts.org/scripts/show/64232
	function find_highlight_in_elements(bad_word_regexp, text_elements)
	{
		var new_text_elements = [];
		for(var i=0 ; i < text_elements.length ; i++)
		{
			var current = text_elements[i];
			while(1)
			{
				// current is a TextNode always attached to the document tree
				var match = bad_word_regexp.exec(current.nodeValue);
				if(match)
				{
					var current_text = current.nodeValue;

					var before_text = current_text.substring(0, match.index);
					var middle_text = match[0];
					var after_text  = current_text.substring(bad_word_regexp.lastIndex);

					var before = document.createTextNode(before_text);
					var hl_node = createBadWordElement(middle_text);
					var after  = document.createTextNode(after_text);

					var par = current.parentNode;
					par.insertBefore(before, current);
					par.insertBefore(hl_node, current);
					par.insertBefore(after, current);
					par.removeChild(current);

					new_text_elements.push(before);
					current = after;

					// Making it restart from the beginning.
					bad_word_regexp.lastIndex = 0;
				}
				else // no match
				{
					new_text_elements.push(current);
					break;
				}
			}
		}
		return new_text_elements;
	}


	// This is basically the main function of this script.
	// It finds all text nodes in the document and, for each one, tries
	// to find and highlight the bad_words.
	function highlight_words_in_document()
	{
		// Getting all text using XPath
		var result = document.evaluate(
			"//body//text()",  // XPath expression
			document,          // contextNode
			null,              // namespaceResolver
			XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
			null               // a previous result
		);
		var result_len = result.snapshotLength;

		for(var text_i=0 ; text_i < result_len ; text_i++)
		{
			var text = result.snapshotItem(text_i);

			// Ignoring hidden text inside some elements:
			if( text.parentNode.nodeType == 1  // Node.ELEMENT_NODE == 1
			&& text.parentNode.nodeName.toLowerCase() in ignored_tags )
			{
				continue;
			}

			var text_elements = [text];
			for(var i=0 ; i < bad_words.length ; i++)
			{
				text_elements = find_highlight_in_elements(bad_words[i], text_elements);
			}
		}
	}


	// Adds a <style> element to the <head>
	function add_style_to_head()
	{
		var head=document.getElementsByTagName('head')[0];
		if(!head)
			return;

		var style=document.createElement('style');
		style.setAttribute('type','text/css');
		style.appendChild(document.createTextNode(
			'span.bad_word { background: #c00 !important; color: white !important; }'
			+ 'div#bad_word_msg { background: #c00; color: white; padding: 0.5em; position: absolute; top: 0; left: 200px; z-index: 999999999; font-size: 11px; line-height: normal; }'
			+ 'div#bad_word_msg a { text-decoration: underline; color: inherit; font: inherit; }'
			+ 'div#bad_word_msg ul, div#bad_word_msg li { list-style: disc; padding: 0; margin: 0; font: inherit; }'
			+ 'div#bad_word_msg ul { display: none; margin-left: 2em; }'
			+ 'div#bad_word_msg:hover ul { display: block; }'
		));
		head.appendChild(style);
	}


	function ignore_case_comparison(a, b)
	{
		a = a.toLowerCase();
		b = b.toLowerCase();
		if (a > b) return 1;
		if (a < b) return -1;
		return 0;
	}


	function add_message_at_page()
	{
		var body = document.getElementsByTagName('body')[0];
		if(!body)
			return;

		// Get the list of all matched bad words, filter duplicates
		// (ignoring case) and sort this list.
		var keys = {};
		var words = [];
		for(var i=0 ; i < found_in_this_page.length ; i++)
		{
			var text = found_in_this_page[i].text;
			keys[text.toLowerCase()] = text;
		}
		for(var i in keys)
		{
			words.push(keys[i]);
		}
		words.sort(ignore_case_comparison);

		var words_ul_list = '';
		for(var i=0; i < words.length ; i++)
		{
			words_ul_list += '<li>' + words[i] + '</li>';
		}

		var div = document.createElement('div');
		div.setAttribute('id', 'bad_word_msg');
		div.innerHTML = (
			'Warning: Some DRM-related words were found!'
			+ ' (<a href="http://forums.steampowered.com/forums/showthread.php?t=1537801">forum</a>, <a href="http://steamdrm.flibitijibibo.com/the-big-drm-list/">list</a>)'
		);
		var ul = document.createElement('ul');
		ul.innerHTML = words_ul_list;

		div.appendChild(ul);
		body.appendChild(div);
	}


	add_style_to_head();
	highlight_words_in_document();
	if( found_in_this_page.length > 0 )
	{
		add_message_at_page();
	}

})();