Cleared Pixiv Artists

Keeps track of Pixiv artists' works and image responses and adds a random link to one of those pages.

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey, Greasemonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name           Cleared Pixiv Artists
// @namespace      https://greasyfork.org/scripts/3634
// @description    Keeps track of Pixiv artists' works and image responses and adds a random link to one of those pages.
// @include        http://danbooru.donmai.us/*
// @include        https://danbooru.donmai.us/*
// @include        http://hijiribe.donmai.us/*
// @include        http://sonohara.donmai.us/*
// @include        http://www.donmai.us/*
// @include        http://donmai.us/*
// @include        http://www.pixiv.net/*
// @include        https://www.pixiv.net/*
// @grant          GM_setValue
// @grant          GM_getValue
// @version        2017.06.08
// ==/UserScript==

var waitingDays = 365;//Days since a page was cleared before the Random link will include it again (when all artists are cleared)
var worksWeight = 3;//Number of chances to give each member_illust link of being selected for the random link (response links get 1)

//////////////////////////////////////////////////////////////////////////////////////

if( window == window.top )
	addLinks();

function addLinks()
{
	if( typeof(GM_getValue) != "undefined" && GM_getValue('a', 'b') )
	{
		getList = function(name){ try{ return JSON.parse( GM_getValue(name,"[]") ); }catch(e){ return []; } }
		setList = function(name,list) { GM_setValue(name,JSON.stringify(list)); }
	}
	else if( location.host.indexOf("donmai.us") >= 0 )
	{
		return;//GM is needed to maintain a single list across both Pixiv and Danbooru, so Danbooru is disabled when that isn't available
	}
	else
	{
		//Use local storage instead.
		getList = function(name)
		{
			var value = localStorage.getItem("cleared_pixiv."+name);
			if( value )
				try{ return JSON.parse(value); } catch(e){}
			return [];
		}
		setList = function(name,list) { localStorage.setItem("cleared_pixiv."+name, JSON.stringify(list)); }
	}
	
	//Add random link
	var randomLink;
	if( location.hostname.indexOf("donmai") >= 0 )
	{
		//Danbooru: Add to right end of subnavbar
		randomLink = document.evaluate("//header/nav/menu[not(contains(@class,'main'))]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
		if( !randomLink )
			return;
		randomLink = randomLink.appendChild( document.createElement("li") ).appendChild( document.createElement("a") );
	}
	else
	{
		//Pixiv: Add to right of whatever
		randomLink = document.getElementsByTagName("header")[0];
		if( !randomLink )
			return;
		randomLink = randomLink.appendChild( document.createElement("a") );
		randomLink.style.cssFloat = "right";
		randomLink.style.margin = "3px";
	}
	randomLink.id = "random_pixiv_link";
	
	setRandomLink();
	
	if( location.href.indexOf("//www.pixiv.net/member.php?id=") > 0 )
	{
		//Member profile
		addListListener( document.evaluate("//div[@class='worksListOthers']//p/a[contains(@href,'member_illust.php?id=')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue, "worksList" );
		addListListener( document.evaluate("//div[@class='worksListOthers']//p/a[contains(@href,'response.php?mode=all&id=')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue, "responseList" );
	}
	else if( location.href.indexOf("//www.pixiv.net/member_illust.php?id=") > 0 )
	{
		//Member's works
		addListListener( document.evaluate("//div/h1/a[contains(@href,'member_illust.php?id=')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue, "worksList" );		
	}
	else if( location.href.indexOf("//www.pixiv.net/response.php?mode=all&id=") > 0 )
	{
		//Image responses
		var header = document.evaluate("//div[@class='search_top_result']/h2", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
		if( !header )
			addListListener( null, "responseList" );//deleted user
		else
		{
			var div = document.createElement("div");
			var link = div.appendChild( document.createElement("a") );
			link.textContent = header.textContent;
			link.href = location.href;
			addListListener(link, "responseList");
			header.innerHTML = "";
			header.appendChild(div);
		}
	}
	else if( location.href.indexOf("donmai.us/artist") >= 0 )
	{
		//Danbooru artist
		var links = document.evaluate('//ul/ul/li/a[contains(@href,"//www.pixiv.net/member.php?id=")]', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		for( var i = 0; i < links.snapshotLength; i++ )
			addListListener( links.snapshotItem(i), "worksList" );
	}
}

function setRandomLink()
{
	var randomLink = document.getElementById("random_pixiv_link");
	if( !randomLink )
		return;
	
	var worksList = getList("worksList");
	var responseList = getList("responseList");
	var found = 0, i, pending = [];
	
	var responseWeight = (worksWeight < 0 ? -worksWeight : 1);
	worksWeight = (worksWeight > 0 ? worksWeight : 1);
	
	function addToList(maxDate)
	{
		for( var i = 0; i < worksList.length; i++ )
			if( worksList[i].date < maxDate )
			{
				if( location.href.indexOf( "//www.pixiv.net/member_illust.php?id="+worksList[i].id ) < 0 )
					for( j = 0; j < worksWeight; j++ )
						pending.push( location.protocol+"//www.pixiv.net/member_illust.php?id="+worksList[i].id );
				found++;
			}
		for( var i = 0; i < responseList.length; i++ )
			if( responseList[i].date < maxDate )
			{
				if( location.href.indexOf( "//www.pixiv.net/response.php?mode=all&id="+responseList[i].id ) < 0 )
					for( j = 0; j < responseWeight; j++ )
						pending.push( location.protocol+"//www.pixiv.net/response.php?mode=all&id="+responseList[i].id );
				found++;
			}
	}
	addToList(1);
	
	if( !found && waitingDays > 1 )
		addToList( new Date().getTime() - waitingDays*24*3600*1000 );
	
	randomLink.title = found+" / "+(worksList.length+responseList.length)+" links pending";
	
	if( found > 0 )
	{
		randomLink.textContent = "Random pixiv link ("+found+")";
		randomLink.style.textDecoration = "";
		if( pending.length > 0 )
			randomLink.href = pending[Math.floor(Math.random()*pending.length)];
		else
			randomLink.removeAttribute("href");
	}
	else
	{
		randomLink.textContent = "Random pixiv link";
		randomLink.style.textDecoration = "line-through";
		randomLink.removeAttribute("href");
	}
}

function addListListener(curLink, listName)
{
	var thisList = getList(listName);
	var userID = (curLink ? curLink : location).href.replace(/.*id=(\d+).*/,"$1");
	
	if( /^\d+$/.test(userID) && ( listName == "worksList" || listName == "responseList" ) )
	{
		if( !curLink )
		{
			for( var index = thisList.length - 1; index >= 0; index-- )
				if( thisList[index].id == userID )
				{
					thisList.splice( index, 1 );
					setList(listName,thisList);
					setRandomLink();
					alert("Removed: "+userID+" from "+listName);
				}
			return;
		}
	}
	else return;
	
	curLink.parentNode.appendChild( document.createTextNode(" ") );
	var statusLink = curLink.parentNode.appendChild( document.createElement("a") );// Add / Remove
	statusLink.style.cursor = "pointer";
	statusLink.onclick = "return false;";
	
	var clearLink = curLink.parentNode.appendChild( document.createElement("a") ); // Clear
	clearLink.style.cursor = "pointer";
	clearLink.onclick = "return false;";
	
	var found = false;
	
	for( var i = thisList.length; i-- > 0; )
		if( userID == thisList[i].id )
		{
			if( found )
			{
				//Remove older duplicates that somehow managed to sneak in.
				thisList.splice( i, 1 );
				setList(listName,thisList);
			}
			else
			{
				if( thisList[i].date == 0 )
					clearLink.textContent = "/[Clear]";
				else
				{
					var days = Math.round( (new Date().getTime() - thisList[i].date)/(24*3600*1000) );
					clearLink.textContent = "/[Cleared "+days+" day"+(days != 1 ? "s" : "")+" ago]";
				}
				statusLink.textContent = "[Remove]";
				found = true;
			}
		}
	if( !found )
		statusLink.textContent = "[Add]";

	//Switch between "Add" and "Remove", modifying the list accordingly.
	statusLink.addEventListener("click", function()
	{
		var list = getList(listName);//Reload list in case it is being modified across multiple tabs
		for( var index = list.length - 1; index >= 0 && list[index].id != userID; index-- );
		
		if( !found )
		{
			//Add to list if it isn't there already.
			if( index < 0 )
				list.push( { id: userID, date: 0 } );
			found = true;
			
			statusLink.textContent = "[Remove]";
			clearLink.textContent = "/[Clear]";
		}
		else
		{
			//Remove from list if it's really there
			if( index >= 0 )
				list.splice( index, 1 );
			found = false;
			
			curLink.textContent = curLink.textContent.replace(/ \[.*/g,'');
			statusLink.textContent = "[Add]";
			clearLink.textContent = "";
		}
		setList(listName,list);
		setRandomLink();
	}, true );
	
	//Set link as cleared today
	clearLink.addEventListener("click", function()
	{
		var list = getList(listName);
		for( var index = 0; index < list.length && list[index].id != userID; index++ );
		list[index].id = userID;
		list[index].date = new Date().getTime();
		setList(listName,list);
		
		statusLink.textContent = "[Remove]";
		clearLink.textContent = "/[Cleared 0 days ago]";
		setRandomLink();
	}, true );
}

//document.body.innerHTML = "<b>Cleared Pixiv Artists</b><br><b>worksList</b> = "+JSON.stringify(getList("worksList"))+"<br><b>responseList</b> = "+JSON.stringify(getList("responseList"));