Flickr Original Link

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

目前為 2015-04-25 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        Flickr Original Link
// @namespace   https://greasyfork.org/scripts/1190-flickr-original-link
// @include     /flickr\.com\/(photos|groups)\//
// @version	4.3.8
// @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 log(s) {
    console.log(s);
}

function getSetting() {
    currentSetting = GM_getValue(key, false);
    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(/modelExport: {.+?"sizes":{.+?}}/i);
    var mWidth, mHeight, mLink, mSize, length;
    var strCss = ".bigButton {position:relative;z-index:9999999;display : inline-block; cursor : pointer; border-style : solid; border-width : 2px; border-radius : 50px; padding : 15px 15px; font-size : 10pt; font-weight : bold;} .smallButton {position:relative;z-index:9999999;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');
    }

    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) {
	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() {
	    source = source.concat($(this).text().match(/"file":"[^}]+}}/g));
	});
    }
    var target = $('body')[0];
    var config = {
	childList : true,
	subtree : true,
    };
    var observer = new MutationObserver(function(mutations, ob) {
	if ($('.myFuckingLink').filter(':first').length > 0) return;
	console.time('Insert links');
	var photoDisplayItem = $('.photo-display-item');
	$('.myFuckingLink').remove();
	photoDisplayItem.each(showLink);
	console.timeEnd('Insert links');
    });
    observer.observe(target, config);
}

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="position:relative;z-index:9999999;display:inline-block;padding:5px 5px 0px 5px;border-radius:3px;" href="' + link + '" target="_tab">' + prefix + size + '</a>');
	    break;
	}
    }
}

function action_groups() {
    log("This is groups");
    var target = $('body')[0];
    var config = {
	childList : true,
	subtree : true,
    };
    var observer = new MutationObserver(function(mutations, ob) {
	log("Mutation");
	var a = $('.photo-display-item').length;
	log("Length: " + a);
	var photo = document.documentElement.outerHTML.match(/16684059350/i);
	log("photo exists? " + photo);
    });
    observer.observe(target, config);
}

function showLink_groups(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('.meta').append('<a class="myFuckingLink" style="position:relative;z-index:9999999;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;
    }

    if (type == 'favorite') {
	var t = e.find('.rapidnofollow').filter(':first').attr('href');
	if (t == null) return;
	var $div = $('<div>');
	e.find('a.owner').after('<div><a class="myFuckingLink" style="position:relative;z-index:9999999;display:inline-block;padding:5px 2px 0px 2px;border-radius:2px;" href="" target="_tab">(Link loading...)</a><div>');
	$div.load(t, function() {
	    var photo = $(this).html().match(/modelExport: {.+?"sizes":.+?}}/i)[0].match(/"width":(\d+),"height":(\d+),"url":"([^"]+)"}}/i);
	    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 + photo[1] + " x " + photo[2]);
	});
    }
    else if (type == 'search') {
	var t = e.find('a.overlay').attr('href');
	if (t == null) return;
	var $div = $('<div>');
	e.find('.interaction-view').after('<div style=""><a class="myFuckingLink" style="position:relative;z-index:9999999;color:white;background-color:rgba(0,0,0,0.3);font-size:10pt;display:inline-block;padding:5px 2px 0px 2px;border-radius:2px;" href="" target="_tab">(Link loading...)</a></div>');
	$div.load(t, function() {
	    var photo = $(this).html().match(/modelExport: {.+?"sizes":.+?}}/i)[0].match(/"width":(\d+),"height":(\d+),"url":"([^"]+)"}}/i);
	    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 + photo[1] + " x " + photo[2]);
	});
    }
}

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

/*
 * end support
 */
function pageType() {
    var title = $('head title').text();
    var url = document.URL;
    var type = "none";
    if (url.match(/\/search\//) != null) type = 'search';
    else if (url.match(/\/groups\//) != null) {
	if (title.match(/flickr.+pool$/i) != null) type = 'favorite';
	else type = 'group_beta';
    }
    else 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';
    log("Page type: " + type);
    return type;
}
var type = pageType();
getSetting();
$('.top-nav:first').append(
	'<li class="toplink"><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;padding:10px"><input id="optionBox" type="checkbox"'
		+ isChecked + 'style="margin:6px"/>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 == 'singlephoto') action_singlephoto_observer("none");
else if (type == 'photostream') action_photostream();
else if (type == 'groups_beta') action_groups();
else if (type == 'favorite' || type == 'search') action_page_need_hover();