DeviantLinker

By berleberly Last update May 17, 2007 — Installed 835 times.
// ==UserScript==
// @name				DeviantLinker
// @namespace		AIM:berleberly
// @description	Adds direct-to-content links to DeviantArt galleries.
// @include			http://*.deviantart.com/*
// ==/UserScript==

/* Revision notes:
07039	Started with FADL-07039.  Chopped out great gobs of bullshit.
07040	#1-3 implemented.  Works, I think.  Colors could be improved.
07040 #4-5 added.
*/

// Start time:
var start = new Date();

// Revision date ( date +%y%j ) ######################################## rev ###
var rev = '07137';
// Prev: 07040b

// Put a bit on the page ############################################# put() ###
function put() {
	// 0=goesbefore 1=tag 2=content
	var ourobject = document.createElement( arguments[1] );
	// Add the content to the object
	ourobject.innerHTML = arguments[2] ;
	// Insert the object on the page before goesbefore
	document.body.insertBefore( ourobject, arguments[0] );
	// We'll also return this object so you can easily put something before it.
	return ourobject;
};


// All programs need pointless bloat! ################################ BLOAT ###
var mote = start.getMilliseconds(); // I don't need even pseudo-random.
// I optimized these with The GIMP, trimming off dead space, colormap
// minimization, etc.  (Wish I could do 2 or 3 bpp...)
if ( mote < 750 ) { // 75%
	mote // smile (93B)
		='R0lGODlhDwAPAJEBAAAAAL+/v///AAAAACH5BAEAAAEALAAAAAAPAA8AAAIujA'
		+'2Zx5EC4WIgWnnqvQBJLTyhE4khaG5Wqn4tp4ErFnMY+Sll9naUfGpkFL5DAQA7'
		+"' width='15' height='15' alt='smile'>"
		;
} else if ( mote < 900 ) { // 15%
	mote // laughing (923B, 64% reduction from 2595B)
		='R0lGODlhDwAPAKEAAAAAAJyc/////wAAACH/C05FVFNDQVBFMi4wAwEAAAA'
		+'h+QQFZAADACwAAAAADwAPAAACNpwNmceTAeFiIFp5qtIqAAQIohCOSzKm6W'
		+'a2Yle+q1fRzybV1/7pO+b46T6ISAeY8dEaSUWjAAAh+QQFZAADACwFAAsAA'
		+'QABAAACAkQBACH5BAUKAAMALAEAAwANAAkAAAIeXDKphgarAApvVJskFbx3'
		+'TQHiKB7miTbQGpEi6y4FACH5BAUKAAMALAIABAALAAYAAAIP3IKXhu3qooy'
		+'m2gqy1qMAACH5BAUKAAMALAIAAgALAAcAAAIS3ICXBuH9jpsU0muy3pyhDw'
		+'IFACH5BAUKAAMALAIAAgALAAcAAAISXI5oAc1+wJiSsolzzbzzBB4FACH5B'
		+'AUKAAMALAIAAgALAAcAAAIS3ICXBuH9jpsU0muy3pyhDwIFACH5BAUKAAMA'
		+'LAIAAgALAAcAAAISXI5oAc1+wJiSsolzzbzzBB4FACH5BAUKAAMALAIAAgA'
		+'LAAcAAAIS3ICXBuH9jpsU0muy3pyhDwIFACH5BAUKAAMALAIAAgALAAcAAA'
		+'ISXI5oAc1+wJiSsolzzbzzBB4FACH5BAUKAAMALAIAAgALAAcAAAIS3ICXB'
		+'uH9jpsU0muy3pyhDwIFACH5BAUKAAMALAIAAgALAAcAAAISXI5oAc1+wJiS'
		+'solzzbzzBB4FACH5BAUKAAMALAIAAgALAAcAAAIS3ICXBuH9jpsU0muy3py'
		+'hDwIFACH5BAUKAAMALAIAAgALAAcAAAISXI5oAc1+wJiSsolzzbzzBB4FAC'
		+'H5BAUKAAMALAIAAgALAAcAAAIS3ICXBuH9jpsU0muy3pyhDwIFACH5BAUKA'
		+'AMALAIAAgALAAcAAAISXI5oAc1+wJiSsolzzbzzBB4FACH5BAUKAAMALAIA'
		+'AgALAAcAAAIS3ICXBuH9jpsU0muy3pyhDwIFACH5BAVkAAMALAIAAwALAAM'
		+'AAAIM3ISXhoDixAC0WlAAACH5BAVkAAMALAQABAAGAAEAAAIDhG4FACH5BA'
		+'VkAAMALAQABAAHAAEAAAIDlGBXACH5BAVkAAMALAIAAgALAAUAAAIRXI5oA'
		+'c1+gJiShjFxzq37VgAAIfkEBfQBAwAsAgAIAAsABQAAAgqMjzHLPQkjenIU'
		+'ACH5BAEKAAMALAMABgAJAAYAAAIPlDUnwDDthpwy2HupljAWADs='
		+"' width='15' height='15' alt='laughing'>"
		;
} else if ( mote < 985 ) { // 8.5%
	mote // grinpimp (150B, 2% reduction from 153B)
		='R0lGODlhEQAWAMIAAAAAAP8AAAD/AFn/yP///wAAAAAAAAAAAC'
		+'H5BAEAAAcALAAAAAARABYAAANbeKrQ12BJFiqoIc6Hu92Xh2kS'
		+'ZJqgoK4ruQBs7DxnXYu4Ze8zMAyNH9AHLAF/PmLyJWw6i48hD5'
		+'okEADWq3UZxWq3WyoQTOZ2v1pzdJgNQplSt+tFFM42DNQkAQA7'
		+"' width='17' height='22' alt='grinpimp'>"
		;
} else { // 1.5%
	mote // thefinger (183B, 81% reduction from 986B)
		='R0lGODlhIQAPAMIAAAAAAAAIAFX/zP///wAAAAAAAAAAAAAAACH5BAEKAAQAL'
		+'AAAAAAhAA8AAAN8SLrM8a/JSZ+4N9LdAv4Z13WZV4bO5AWOYHpA5rYsWRMmqN'
		+'+r1CurB2BIHAoAi18yFhjiXINBICqNwghD2C3GPT6nVavV2+U+QciVeH2NgVh'
		+'uDPIbrv7ilzlWnixRLTMKcXqCeS0uEC8MboSFXg45JQ2MEgCWjUCJE5d6CQA7'
		+"' width='33' height='15' alt='thefinger'>"
		;
};
mote=' <img align=bottom src=\'data:image/gif;base64,'+mote;

var lem; // Last placed EleMent. (easier to type than lpe)
// Announce our presence. ####################################### (announce) ###
lem=put( document.body.lastChild.nextSibling, 'div',
	'You\'re using the <i>DeviantLinker</i> GreaseMonkey script by '
	+'<a href="aim:berleberly">berleberly</a>.'
	+mote+'</div>\n');
// Unset mote, 'cause it can be kinda big.
mote='';

// Only work on Gallery pages. ##################################### GO/NOGO ###
// No-go page check.  On a gallery page?
// (Usernames have letters, numbers, hyphen, and must be >=3 chars long.)
if (window.location.href.match(
	/^http:\/\/[a-z0-9-][a-z0-9-][a-z0-9-]+\.deviantart.com\/gallery\/\??(&.+)?$.*/i
	) ) {
// I'm not going to indent everything for this block.
// Apparently Sun didn't want any GOTO in JavaScript.  Fascists.


// Common strings ############################################ ic hida S U D ###
var ic = '3';	// Which icN server to use.
var hida = 'http://ic'+ic+'.deviantart.com/';


// METHod function array!  ########################################## meth[] ###
// Filename format check, breakdown, and construction
// We use an array 'cause it makes for an easy loop, trying each method in turn.
// True, unlike the FADL that spawned this we don't have so damned many, but
// I already have this great infrastructure developed in case it's needed.
// We have to order these carefully- some are more inclusive than others!
// I'm numbering them as I create them, and listing known interactions.
// Unfortunately the weird ordering may not be performance-optimal, but when
// you're running GreaseMonkey you probably expect a little overhead anyways.
// I'll still try to keep the less-common (or just older, really) patterns
// low in the list so it's not too bad.  (The reason for noting collisions.)
// meth[N](URL) will return false if it can't do it, an array if it can.
// [ URL, filename, comment ]
//##############################################################################
//##############################################################################
// Counter: 3
var meth = [
	// #1 fsNN
	// http://tn1-2.d....com/fs12/150/i/2006/301/2/c/NEStalgia_by_jasinski.jpg
	// http://ic1.deviantart.com/fs12/i/2006/301/2/c/NEStalgia_by_jasinski.jpg
	// caps:  fs12/ i/2006/301/2/c/ filename.ext
	function() { return ( arguments[0].match(
		/^http:\/\/tn\d-\d\.deviantart\.com\/(fs\d+\/)\d+\/(.\/\d\d\d\d\/\d+\/.\/.\/)([^\/]+\.(?:jpg|gif|png|jpeg))$/i
		)?[
		hida + RegExp.$1 + RegExp.$2 + RegExp.$3
		,RegExp.$3
		,'#1']:false );
	},
	// #3 just some oddness
	// http://tn1-4.deviantart.com/150/fs7.deviantart.com/i/2005/239/7/0/L....jpg
	// http://ic1.deviantart.com/fs7/i/2005/239/7/0/L_we_all_love_you_by_....jpg
	// fsN /i/.../0/ file.ext
	function() { return ( arguments[0].match(
		/^http:\/\/tn\d-\d.deviantart.com\/\d+\/((?:fs|images)\d)\.deviantart\.com(\/.\/\d\d\d\d\/\d+\/.\/.\/)([^\/]+.(?:jpg|gif|png|jpeg))$/i
		)?[
		hida + RegExp.$1 + RegExp.$2 + RegExp.$3
		,RegExp.$3
		,'#3']:false );
	},
	// #2 older, my sample from 2002.
	// http://tn1-1.deviantart.com/150/i/2002/23/2/a/little_star.jpg
	// http://ic3.deviantart.com/images/i/2002/23/2/a/little_star.jpg
	// i/.../a/ name.ext
	function() { return ( arguments[0].match(
		/^http:\/\/tn\d-\d\.deviantart.com\/\d+\/(.\/\d\d\d\d\/\d+\/.\/.\/)([^\/]+\.(?:jpg|gif|png|jpeg))$/i
		)?[
		hida + 'images/' + RegExp.$1 + RegExp.$2
		,RegExp.$2
		,'#2']:false );
	},
	// #4 an odd flavor
	// http://tn1-4.deviantart.com/150/i/4/f/8/City_Sun_2.jpg
	// http://fc01.deviantart.com/images/i/4/f/8/City_Sun_2.jpg
	// i/...8/ file.ext
	// Fortunately it looks like I can still use icN instead of fc01.  :)
	function() { return ( arguments[0].match(
		/^http:\/\/tn\d-\d\.deviantart.com\/\d+\/(.\/.\/.\/.\/)([^\/]+\.(?:jpg|gif|png|jpeg))$/i
		)?[
		hida + 'images/' + RegExp.$1 + RegExp.$2
		,RegExp.$2
		,'#4']:false );
	},
	// #5 an old flavor?  Very general regex!  Don't move up in list!
	// http://tn1-2.deviantart.com/150/large/indyart/popart/Mike_and_Celeste.jpg
	// http://ic1.deviantart.com/images/large/indyart/popart/Mike_and_Celeste.jpg
	// large/...popart/ name.ext
	function() { return ( arguments[0].match(
		/^http:\/\/tn\d-\d\.deviantart.com\/\d+\/(large\/[^\/]+\/[^\/]+\/)([^\/]+\.(?:jpg|gif|png|jpeg))$/i
		)?[
		hida + 'images/' + RegExp.$1 + RegExp.$2
		,RegExp.$2
		,'#5']:false );
	}
]; // End of meth[]
//##############################################################################
//##############################################################################


// IS THumbnail? ###################################################### isth ###
var isth = /http:\/\/tn[^.]+\.deviantart.com\/.+\./i;


/////////////////////////////////////////////////////////////////////////MAIN///

// Loop thru <img> elements. ################################### (<img>loop) ###
// Image element Array (ea would look like "each", so...)
var ia = document.getElementsByTagName('img');
// Processed Count, Linked Count, and Meth Output.
var pc=0, lc=0, mo;
// The loop proper- we work with each ImageArray[i].
for (var i=0; i < ia.length; i++ ) {
	// Ignore non-thumbnails and non-images.  (And offsite images.)
	if (!isth.exec(ia[i].src)) { continue; };
	// meth[] loop.  ########################################## (meth[] loop) ###
	// j counts off each element in meth.
	for (var j in meth) {
		// The function wants the <img src=URL, and we store/see what it returns
		if ( mo=meth[j](ia[i].src) ) { // We got something, so we can make a link!
			pc++; lc++ // Increment ProcessedCount and LinkedCount
			// Output a link.
			// (I used to use 'a' for second parameter, but then the numbers
			// change color/style with the link when you point at 'em.)
			lem=put(lem.nextSibling,'div',
				(pc<10?'0':'')+pc+': <a href="'+mo[0]+'">'
				+mo[1]+'</a> <font color="#DEDEDE">'+mo[2]+'</font></div>\n');
			break; // Stop running the fadl loop, we can do the next ia.
		}; // FI got something
	}; // DONE
	if (!mo) { // Did we succeed, or shall we note our miserable failure?
		lem=put(lem.nextSibling,'div', (++pc<10?'0':'') + pc +': Failed '
			+ia[i].src +', "'+ ia[i].alt +'"</div>\n');
	}; // FI fail
}; // end ia loop

// Put on the footer. ############################################ (goodbye) ###
// (Lets me know the thing didn't die halfway, reports final numbers.)
put(document.body.lastChild.nextSibling,'div',
	'R'+rev+' - Result: '
	+lc+' link'+(lc==1?'':'s')+', '
	+(j=pc-lc)+' fail'+(j==1?'':'s')+', '
	+(i-pc)+' skipped.'
	+(j?' URL='+window.location.href
	+'<br><a href="aim:berleberly">Send me an IM</a>'
	+' of this output (at least the last two lines) to report this bug!'
	:'')
	+' <font color="#DEDEDE">'+(new Date()-start)+'ms</font>'
	+'</div>\n');

} else { // NOGO: #################################################### NOGO: ###
	put(document.body.lastChild.nextSibling, 'div',
	'R'+rev+" - Page URL doesn't match regexp- no action taken."
	+' <font color="#DEDEDE">'+(new Date()-start)+'ms</font>'
	+'</div>\n');
};

///// ///// ///////////////////////////////////////////////////////////////////////////////// berleberly                                                vim:ts=3