Flickr Original Link

Show direct links to download biggest Flickr image available and some other sizes.

As of 2014-12-06. See the latest version.

// ==UserScript==
// @name        Flickr Original Link
// @namespace   https://greasyfork.org/scripts/1190-flickr-original-link
// @include     /^https?:\/\/.*\.?flickr\.com\/photos\/.*/
// @version		4.3.5
// @grant       GM_getValue
// @grant       GM_setValue
// @require 	http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
// @description 	Show direct links to download biggest Flickr image available and some other sizes. 
// ==/UserScript==
var source = "";
var postfix = "_d.jpg";
var prefix = "DOWNLOAD ";
var isChecked = "";
var key = "flickr_openLink";
var currentSetting = false;

/*
 * support function
 */
function getSetting() {
    currentSetting = GM_getValue(key, false);
    console.log("Get setting: " + currentSetting);
    if (currentSetting) {
        postfix = ".";
        isChecked = ' checked="checked" ';
        prefix = "OPEN ";
    }
    else {
        postfix = "_d.";
        isChecked = "";
        prefix = "DOWNLOAD ";
    }
}

function action_singlephoto(sourceCode) {
    var size = sourceCode.match(/"sizes":{(.+?})}/i);
    var mWidth, mHeight, mLink, mSize, length;
    var strCss = ".bigButton {display : inline-block; cursor : pointer; border-style : solid; border-width : 2px; border-radius : 50px; padding : 15px 15px; font-size : 10pt; font-weight : bold;} .smallButton { display: inline-block; padding: 0.6em; margin: 0.4em; background-color: pink; border-radius:1.5em;font-size:10pt}";
    $('head').append('<style>' + strCss + '</style>');
    mSize = size[0].match(/"width":"?\d+"?,"height":"?\d+"?,/ig);
    mLink = size[0].match(/"url":"[^"]+"/ig);
    length = mLink.length;
    
    for (var k = 0; k < length; k++) {
        mSize[k] = mSize[k].replace(/"width":(\d+),"height":(\d+),/i, "$1 x $2");
        mLink[k] = "http:" + mLink[k].replace(/"url":"([^"]+)"/i, "$1").replace(/\\/g, "").replace(/(_[a-z])\.([a-z]{3,4})/i, '$1' + postfix + '$2');
    }
    
    //$('.bigButton').remove();
    //$('.smallButton').remove();
    var insertLocation = $('.sub-photo-right-row1');
    if (insertLocation.length > 0) {
        insertLocation.append('<a class="bigButton" href="' + mLink[length - 1] + '">DOWNLOAD ' + mSize[length - 1] + ' px</a>');
        for (var k = 0; k < 7; k++) {
            var m = length-k-2;
            if (m>0) insertLocation.append('<a class="smallButton" href="' + mLink[m] + '">' + mSize[m] + ' px</a>');
        }
    }
}

function action_singlephoto_observer(oldURL) {
    var target = $('html')[0];
    var config = {
        childList : true,
        subtree : true,
    };
    var observer = new MutationObserver(function(mutations, ob) {
        if (document.URL == oldURL) return;
        oldURL = document.URL;
        $('<div>').load(oldURL, function() {
            action_singlephoto($(this).text());
        });
    });
    observer.observe(target, config);
}

function action_photostream() {  
    source = document.documentElement.innerHTML.match(/"file":"[^}]+}}/g);
    if (source == null) {
        console.log('err: no source');
        return false;
    }
    var t1 = $('a[data-track="prev"]').attr('href');
    if (t1 != null) {
        var t2 = $('span.this-page').text();
        t1 = t1.replace(/\/page\d+\//i, "/page" + t2 + "/");
        var $div = $('<div>');
        $div.load(t1, function() {
            var source2 = $(this).text().match(/"file":"[^}]+}}/g);
            source = source.concat(source2);
        });
    }
    var target = $('body')[0];
    var config = {
        childList : true,
        subtree : true,
    };
    var observer = new MutationObserver(function(mutations, ob) {
        if ($('.myFuckingLink').filter(':first').length > 0) return;
        var photoDisplayItem = $('.photo-display-item');
        console.time('Insert links');
        $('.myFuckingLink').remove();
        photoDisplayItem.each(showLink);
        console.timeEnd('Insert links');
    });
    observer.observe(target, config);
}

function pageType() {
    var title = $('head title').text();
    var type = "none";
    if (title.match(/flickr.+photostream/i) != null) type = 'photostream';
    else if (title.match(/an album on flickr/i) != null) type = 'photostream';
        else if (title.match(/flickr - photo sharing/i) != null) type = 'singlephoto';
        else if (title.match(/favorite photos and videos/i) != null) type = 'favorite';
            else if (title.match(/from the people you follow/i)!=null) type = 'favorite';
            // else if (document.URL.match(/flickr\.com\/groups\//i) != null) type = 'favorite';
            else if (title.match(/flickr.+pool$/i) != null) type = 'favorite';
                console.log("Page type: " + type);
    return type;
}

function showLink(index, elem) {
    var $e = $(elem);
    var photoId = $e.attr('data-photo-id');
    for (var i = 0; i < source.length; i++) {
        if (source[i].indexOf(photoId) == 8) {
            var link = source[i].match(/https?[^"]+/)[0].replace(/\\/g, "").replace(/(_[a-z])\.([a-z]{3,4})/i, '$1' + postfix + '$2').replace(/https/, "http");
            var size = source[i].replace(/.+"width":"?(\d+)"?,"height":"?(\d+)"?.*/, "$1 x $2 px");
            $e.find('.attribution-block').append('<a class="myFuckingLink" style="display:inline-block;padding:5px 5px 0px 5px;border-radius:3px;" href="' + link + '" target="_tab">' + prefix + size + '</a>');
            break;
        }
    }
}

function flickr_mouseenter() {
    var e = $(this);
    if (e.find('.myFuckingLink').filter(':first').length > 0) {
        e.off('mouseenter');
        return true;
    }
    var $div = $('<div>');
    var t = e.find('.rapidnofollow').filter(':first').attr('href');
    e.find('a.owner').after('<p><a class="myFuckingLink" style="display:inline-block;padding:5px 5px 0px 5px;border-radius:3px;" href="" target="_tab"> (Link loading...)</a></p>');
    $div.load(t, function() {
        var photo = $(this).html().match(/"sizes":.+"width":(\d+),"height":(\d+),"url":"([^"]+)"}}/i);
        var size = photo[1] + " x " + photo[2];
        var link = "http:" + photo[3].replace(/\\/g, "").replace(/(_[a-z])\.([a-z]{3,4})/i, '$1' + postfix + '$2');
        e.find('.myFuckingLink').attr('href', link);
        e.find('.myFuckingLink').html(prefix + size);
    });
}

function action_favorite() {
    var target = $('body')[0];
    var config = {
        childList : true,
        subtree : true,
    };
    var observer = new MutationObserver(function(mutations, ob) {
        $('.photo-display-item').mouseenter(flickr_mouseenter);
    });
    observer.observe(target, config);
}

/*
 * end support
 */
var count = 0;
getSetting();
var type = pageType();
$('#subnav-refresh .subnav-holder ul:first').append(
    '<li><div title="If this option is checked, you will OPEN the image, instead of downloading it. Nếu bạn đánh dấu tùy chọn này, khi nhấn vào link, bạn sẽ MỞ ảnh ra chứ không phải tải tự động về máy." id="optionBoxContainer" style="color:pink"><input id="optionBox" type="checkbox"'
    + isChecked + 'style="margin:5px"/>Open image link in browser</div></li>');

$('#optionBox').change(function() {
    console.time('Change option');
    GM_setValue(key, $(this).prop('checked'));
    getSetting();
    $('.myFuckingLink').remove();
    if (type == 'photostream') $('.photo-display-item').each(showLink);
    console.timeEnd('Change option');
});

if (type == 'photostream') action_photostream();
else if (type == 'singlephoto') action_singlephoto_observer("none");
    else if (type == 'favorite') action_favorite();