BitSoup.org - Add Movie IMDB Ratings, Improve Interface

By manixrock Last update Dec 19, 2007 — Installed 457 times.
// ==UserScript==
// @name           BitSoup.org - Add Movie IMDB Ratings, Improve Interface
// @namespace      Manix
// @include        http://www.bitsoup.org/*
// ==/UserScript==

// Settings:
var FadeOutTime = 0; // (0 = instantaneous)
var LevenshteinDistanceMatch = 60; // ("American Pie Presents Beta House 2007" fails with 62%)
var Debug = 0;

var $, _g = 'http://www.google.com/search?q=intitle:[', g_ = ']+site:imdb.com/title+"Register+or+login+to+rate+this+title."+"User+Rating"+10';
var ScriptsByPage = {
	'': function($) {
		$('td.navigation>A[href$=paypal_donate.php]').parent().css('height', '31px');
		$('body>div[align="center"], td.main>br').slideUp(FadeOutTime);
		$('td.navigation>A[href$=paypal_donate.php]').hide(FadeOutTime);
		$('td.main').css('padding', '0px');
	},
	'^http://www.bitsoup.org/browse.php': function($) {
		// Add L/S column
		var c = $('table.koptekst tr:eq(0)>td').length, p = $('td:eq('+(c-3)+'), td:eq('+(c-2)+')', $('table.koptekst tr'));
		for (var i=0; i<p.length; i+=2) {
			var s=p[i],l=p[i+1],r,t,e=(i? elem('td.rowhead', r=Math.round(parseInt(l.textContent)/parseInt(s.textContent)*100)/100, {align:'center'}) :
										  elem('td.menubar', 'L/S', {align:'center'}));
			if(r<1) {
				var t=Math.round(Math.sqrt(1-r)*155);
				e.style.color='rgb('+t+','+t+','+t+')';
			} else if(r>5) {
				e.style.fontWeight='bold';
				var t=Math.round(Math.sqrt(Math.min(r-5,95)/95)*255);
				e.style.color='rgb('+t+',0,0)';
			}
			l.parentNode.insertBefore(e, l.nextSibling);
		}
		
		// Add IMDB Ratings
		GM_addStyle('td.main {background:#99BBD5}');
		GM_addStyle('td.rowhead .imdb {font-size:8px; color:#999; cursor:default}');
		GM_addStyle('td.rowhead .imdb .title {text-decoration:none; font-size:10px; color:#48C; cursor:pointer}');
		GM_addStyle('td.rowhead .imdb .stars, td.rowhead .imdb .stars div {float:right; width:100px; height:10px; '+
					'background:url(http://img4.glowfoto.com/images/2007/12/18-0813321909T.png)}');
		GM_addStyle('td.rowhead .imdb .stars div {float:none; background-position:0px 10px}');
		$.each($('img[alt="Movies/XviD"], img[alt="Movies/DVD-R"]'), function(id, val) {
			var titleBox = $('td:eq(1)', val.parentNode.parentNode.parentNode)[0], title = $('A', titleBox)[0].textContent;
			// Retreive relevant name of the movie by filtering scene keywords
			var keywords = ('CAM|DVDRIP|XviD|DivX|DVDSCR|DVDR?|NTSC|PAL|HLS|STV|TC|TS|FS|NL|V2|R[1-5]|SCREENER|NEW SOURCE|PROPER|LIMITED'+
				'|CUSTOM|UNRATED|FINAL|Razor1911|DiAMOND').toLowerCase().split('|'), end = 999, m, i;
			for (i=0; i<keywords.length; i++) {
				m = RegExp('\\b'+keywords[i]+'\\b').exec(title.toLowerCase());
				if(m && m.index) end = Math.min(end, m.index);
			}
			title = title.substr(0, end).replace(/[.,;]/g, ' ').replace(/^ +| +$/g, '');
			// Numbers are in some cases represented in the roman system (ex: "Saw IV" instead of "Saw 4")
			// Some words are shorthands without the "'"
			var searchTitle = title
				.replace(/\b1\b/g, '1|I').replace(/\b2\b/g, '2|II').replace(/\b3\b/g, '3|III').replace(/\b4\b/g, '4|IV')
				.replace(/\b5\b/g, '5|V').replace(/\b6\b/g, '6|VI').replace(/\b7\b/g, '7|VII').replace(/\b8\b/g, '8|VIII')
				.replace(/\b9\b/g, '9|IX').replace(/\b10\b/g, '10|X').replace(/\b11\b/g, '11|XI').replace(/\b12\b/g, '12|XII')
				.replace(/\bIm\b/g, "Im|I'm");
			if(Debug) console.info(id+': '+searchTitle);
			
			// Check for cached version
			var c = GM_getValue('cache_'+searchTitle);
			if (c) {
				c = c.split(',');
				AddIMDBRating(titleBox, c[0], c[1], c[2], c[3], searchTitle);
				return;
			}
			
			var g=_g+searchTitle+g_;
			GM_xmlhttpRequest({
				method: 'get',
				headers: {'User-Agent':'Mozilla/4.0 (compatible) Greasemonkey', 'Content-Type':'application/x-www-form-urlencoded'},
				url: g,
				onload: function(result) {
					var res = result.responseText, m, f;
					m=RegExp('<a href="([^"]+)" class=l[^>]*>(.+?)</a>(?:.|\\n|\\r){0,300}<b>User Rating</b>: (\\d+(?:\\.\\d+))/<b>10</b>').exec(res);
					if(m) var it = m[2].replace(/<\/?b>/g, ''), h = m[1], lev = LevDistTitles(it, title), r = parseFloat(m[3]);
					if(m && lev<=LevenshteinDistanceMatch) AddIMDBRating(titleBox, it, r, lev, h, searchTitle);
					else {
						var n=RegExp('<a href="([^"]+)" class=l[^>]*>(.+?)</a>').exec(res);
						if(!n) { if(Debug)console.info('['+title+']- No Google results!'); return }
						// The "m" matched the first item which already failed the LD test:
						if(m && n[1]==h) { if(Debug)console.info('['+title+']- Failed LD Check!'); return }
						it = n[2].replace(/<\/?b>/g, ''), h = n[1], lev = LevDistTitles(it, title);
						console.info('lev: '+lev);
						if(lev<=LevenshteinDistanceMatch) GM_xmlhttpRequest({
							method: 'get',
							headers: {'User-Agent':'Mozilla/4.0 (compatible) Greasemonkey', 'Content-Type':'application/x-www-form-urlencoded'},
							url: h,
							onload: function(result) {
								var p=RegExp('<b>User Rating:</b>\\s*<b>(\\d+(?:\\.\\d+))/10</b>').exec(result.responseText);
								AddIMDBRating(titleBox, it, parseFloat(p[1]), lev, h, searchTitle);
							}
						});
					}
				}
			});
		});
	}
}


function AddIMDBRating(titleBox, it, r, lev, h, searchTitle) {
	$(titleBox).append(elem('DIV.imdb', '', {innerHTML: '<a href=\''+_g+searchTitle+g_+'\' class=stars title='+r+'/10><div style=width:'+
		(r*10)+'px></div></a><a class=title href='+h+'>'+it+'</a> on IMDB'}));
	GM_setValue('cache_'+searchTitle, it+','+r+','+lev+','+h);
	if(Debug) console.info(CleanTitle(it)+': '+r+' [LD:'+lev+'%] ('+h+')');
}
function LevDistTitles(it, title) { // shows the mismatch level (%)
	var cit = CleanTitle(it), lev = LevenshteinDistance(cit, CleanTitle(title)), r = lev/title.length;
	return Math.round(r<1 ? r*100 : 100/r);
}
function CleanTitle(t) {
	return t.replace(/ *\(?(19|20)\d\d\)?( *(V))?$/, '').replace(/&#39;/g, "'");
}

function LevenshteinDistance(s, t) {
	var d = new Array(), n = s.length, m = t.length, i, j, s_i, t_j, cost; // cost

	if (n == 0) return m;
	if (m == 0) return n;
	for(i=0; i<=n; i++) d[i] = [];
	for (i=0; i<=n; i++) d[i][0] = i;
	for (j=0; j<=m; j++) d[0][j] = j;
	for (i=1; i<=n; i++) {
		s_i = s.charAt(i-1);
		for (j=1; j<=m; j++) {
			t_j = t.charAt(j-1);
			cost = (s_i == t_j ? 0 : 1);
			d[i][j] = Math.min(d[i-1][j]+1, Math.min(d[i][j-1]+1, d[i-1][j-1] + cost));
		}
	}
	return d[n][m];
}

elem = function(n,t,a) {
	var f=/(\w+)?(?:#(\w+))?((?:\.\w+)*)/.exec(n), e=document.createElement(f[1]||'DIV');
	if(f[2]) e.id=f[2];
	if(f[3]) e.className=f[3].substr(1).replace(/\./g,' ');
	if(a) for(var k in a)
		if(k!='style') e[k]=a[k];
		else for(var s in a.style) e.style[s]=a.style[s];
	e.appendChild(document.createTextNode(t));
	return e;
}

var D=document,j;function r(){$=unsafeWindow.jQuery;if(!$){if(!j){
j=D.createElement('script');j.src='http://code.jquery.com/jquery-latest.pack.js';D.getElementsByTagName('head')[0].appendChild(j);
}setTimeout(r,10);}else for(k in ScriptsByPage)if(RegExp(k).test(D.location.href))ScriptsByPage[k]($);}r();