Zelluloza Dumper

Сохраняет фрагмент или все фрагменты книги, доступные для чтения в формате fb2. Книги защищенные максимальной защитой сохранет в виде картинок в pdf или fb2

目前为 2016-08-11 提交的版本。查看 最新版本

// ==UserScript==
// @name         Zelluloza Dumper
// @version      0.5
// @description  Сохраняет фрагмент или все фрагменты книги, доступные для чтения в формате fb2. Книги защищенные максимальной защитой сохранет в виде картинок в pdf или fb2
// @author       MadDAD
// @require  https://greasyfork.org/scripts/15924-jspdf/code/jsPDF.js?version=99137
// @require  https://greasyfork.org/scripts/2350-filesaver-js/code/filesaverjs.js?version=6255
// @include  https://zelluloza.ru/books/*
// @namespace https://greasyfork.org/users/38856
// ==/UserScript==
//*************************************

//Asinc image loader
function ImageLoader(images, callback)
{
	// store the call-back
	this.callback = callback;
	// initialize internal state.
	this.nLoaded = 0;
	this.nProcessed = 0;
	this.aImages = new Array();
	// record the number of images.
	this.nImages = images.length;
	// for each image, call preload()
	for (var i = 0; i < images.length; i++)
		this.preload(images[i]);
}

ImageLoader.prototype.preload = function (image)
{
	// create new Image object and add to array
	var oImage = new Image();
	this.aImages.push(oImage);
	// set up event handlers for the Image object
	oImage.onload = ImageLoader.prototype.onload;
	oImage.onerror = ImageLoader.prototype.onerror;
	oImage.onabort = ImageLoader.prototype.onabort;
	// assign pointer back to this.
	oImage.oImageLoader = this;
	oImage.bLoaded = false;
	oImage._src = image;
	// assign the .src property of the Image object
	oImage.src = image;
};

ImageLoader.prototype.onComplete = function ()
{
	this.nProcessed++;
	my_getbyid("bookpg").innerHTML = 'Загружено страниц: ' + this.nProcessed + ' из ' + this.nImages;
	if (this.nProcessed == this.nImages)
	{
		this.callback(this.aImages, this.nLoaded);
	}
};

ImageLoader.prototype.onload = function ()
{
	this.bLoaded = true;
	this.oImageLoader.nLoaded++;
	this.oImageLoader.onComplete();
};

ImageLoader.prototype.onerror = function ()
{
	this.bError = true;
	this.oImageLoader.onComplete();
};

ImageLoader.prototype.onabort = function ()
{
	this.bAbort = true;
	this.oImageLoader.onComplete();
};
//*************************************

function ParceUserToken(aScripts)
{
	for (var i = 0; i < aScripts.length; i++)
	{
		var CurrentScript = aScripts[i];
		if(CurrentScript.text !== "")
			if (CurrentScript.text.indexOf('getbook') > 0)

			{
				UserToken = eval(CurrentScript.text.split(';')[1].split(',')[5]);
				if (UserToken !== undefined)
					return UserToken;
			}
	}
}

function GetUserToken()
{
	var UserToken = ParceUserToken(document.getElementsByTagName("script"));

	if (UserToken === undefined)
	{
		var URL = document.getElementsByClassName("taglnk2");
		for (var i = 0; i < URL.length; i++)
		{
			var xmlhttp = getXmlHttp();
			xmlhttp.open("GET", URL[i], false);

			if (xmlhttp.readyState == 1)
			{
				xmlhttp.setRequestHeader("Content-Type", "text/html");
				xmlhttp.send();
			}

			if (xmlhttp.status != 200)
			{
				alert(xmlhttp.status + ': ' + xmlhttp.statusText); // пример вывода: 404: Not Found
			}
			else
			{
				var doc = new DOMParser().parseFromString(xmlhttp.responseText, "text/html");

				UserToken = ParceUserToken(doc.getElementsByTagName("script"));
				if (UserToken !== undefined)
					return UserToken;
			}

		}
	}

	return UserToken;
}

function MyAjax(obj, notused, par1, par2, par3, par4, append)
{
	var xmlhttp = getXmlHttp();
	var params = "op=" + encodeURIComponent(par1) + "&par1=" + encodeURIComponent(par2) + "&par2=" + encodeURIComponent(par3) + "&par4=" + encodeURIComponent(par4);
	ajaxDone = 0;
	if (xmlhttp.readyState == 0)
	{
		xmlhttp.open("POST", "/ajaxcall/", false);
	}
	if (xmlhttp.readyState == 1)
	{
		xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		xmlhttp.send(params);
	}

	if (xmlhttp.readyState == 4)
	{
		if (xmlhttp.status == 200)
		{
			ajaxDone = 1;
			if (obj != "")
			{
				var str = xmlhttp.responseText;
				if (par1 == "getbook")
				{
					chp = str.split("<END>");
					return chp;
				}
			}
		}
	}

}

function AllBook(book)
{
	//var MaxProtection = my_getbyid("protected1").src !== '';

	var MaxProtection = false;
	if (!MaxProtection)
	{

		var pageHtml = "";
		var BookId = document.getElementById("gotobook").value;
		var PartId = document.getElementsByClassName("taglnk2")[0].href.split('/')[4];
		var UserToken = GetUserToken();
		var BookTitle = document.getElementsByClassName("booklnk4")[1].childNodes[0].innerHTML;
		var PartTitle = document.getElementsByClassName("taglnk2")[0].text;

		var series = "";
		var res = new RegExp('.*Серия: (.*)$', 'm').exec(document.getElementsByClassName('serie')[1].outerText);
		if (res !== null)
			series = res[1];

		pageHtml = '<?xml version="1.0" encoding="utf-8"?><FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:xlink="http://www.w3.org/1999/xlink">';
		pageHtml += '<description><title-info><genre/><author><first-name>' + document.getElementsByClassName("txt")[5].text + '</first-name><last-name/></author>';
		pageHtml += '<book-title>' + BookTitle + '</book-title>';
		pageHtml += '<annotation><p>' + document.getElementsByTagName("meta", "")[4].content + '</p></annotation>';
		pageHtml += '<lang>ru</lang><src-lang>ru</src-lang>';
		pageHtml += '<sequence name="' + series + '" number="" />';
		pageHtml += '</title-info><document-info><author><nickname/><email/></author><version>2.0</version></document-info>';
		pageHtml += '<publish-info><book-name>' + BookTitle + '</book-name></publish-info></description>';
		pageHtml += '<body>';
		pageHtml += '<title>';
		pageHtml += '<p>' + BookTitle + '</p>';
		pageHtml += '</title>';

		//var chp = new Array();

		var links = document.getElementsByClassName("taglnk2");
		for (var i = 0; i < links.length; i++)
		{
			book.childNodes[0].innerHTML = BookTitle + "(" + (i / links.length * 100) + "% загружено...)";
			var item = links[i];

			PartId = item.href.split('/')[5];
			PartTitle = item.text;

			var chp = MyAjax('booktext', '', 'getbook', BookId, PartId + ':0.0.1::0', UserToken, 0);

			pageHtml += '<section><title><p>' + PartTitle + '</p></title>';

			var Z = chp[0].split(/\n/);
			for (var j in Z)
			{
				pageHtml += '<p>' + DS('', Z[j]).replace('\r', '').replace('\n', '').replace('[ctr][gry]- Конец фрагмента -[/][/]', '') + '</p>\n';
			}

			pageHtml += '</section>';
		};

		pageHtml += '</body></FictionBook>';

		var file = new File([pageHtml], BookTitle + '.fb2',
							{
			type : "text/plain;charset=utf-8"
		}
						   );
		saveAs(file, BookTitle + '.fb2');
	}

}

function unprotect(text, format)
{
	var pageHtml = null;
	if (format === undefined)
		format = "fb2";

	if (document.location.hostname == "zelluloza.ru")
	{
		var BookId = document.getElementById("gotobook").value;
		var PartId = document.getElementsByClassName("taglnk2")[0].href.split('/')[4];
		var UserToken = GetUserToken();
		var BookTitle = document.getElementsByClassName("booklnk4")[1].childNodes[0].innerHTML;
		var PartTitle = document.getElementsByClassName("taglnk2")[0].text;

		if (document.getElementsByClassName("booklnk4"))
		{

			var series = "";
			var res = new RegExp('.*Серия: (.*)$', 'm').exec(document.getElementsByClassName('serie')[1].outerText);
			if (res !== null)
				series = res[1];

			pageHtml = '<?xml version="1.0" encoding="utf-8"?><FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:xlink="http://www.w3.org/1999/xlink">';
			pageHtml += '<description><title-info><genre/><author><first-name>' + document.getElementsByClassName("txt")[5].text + '</first-name><last-name/></author>';
			pageHtml += '<book-title>' + BookTitle + '</book-title>';
			pageHtml += '<annotation><p>' + document.getElementsByTagName("meta", "")[4].content + '</p></annotation>';
			pageHtml += '<lang>ru</lang><src-lang>ru</src-lang>';
			pageHtml += '<sequence name="' + series + '" number="" />';
			pageHtml += '</title-info><document-info><author><nickname/><email/></author><version>2.0</version></document-info>';
			pageHtml += '<publish-info><book-name>' + BookTitle + '</book-name></publish-info></description>';
			pageHtml += '<body>';
			pageHtml += '<title>';
			pageHtml += '<p>' + BookTitle + '</p>';
			pageHtml += '</title>';
			pageHtml += '<section><title><p>' + PartTitle + '</p></title>';
		}

		var MaxProtection = my_getbyid("protected1").src !== '';
		if (!MaxProtection)
		{
			var Z = chp[0].split(/\n/);
			for (var j in Z)
			{
				pageHtml += '<p>' + DS('', Z[j]).replace('\r', '').replace('\n', '').replace('[ctr][gry]- Конец фрагмента -[/][/]', '') + '</p>\n';
			}
			pageHtml += '</section></body></FictionBook>';
			var file = new File([pageHtml], BookTitle + '.fb2',
								{
				type : "text/plain;charset=utf-8"
			}
							   );
			saveAs(file, BookTitle + '(' + PartTitle + ').fb2');
		}
		else
		{
			var pages = new Array();
			oCanvas = my_getbyid("cnv1");
			oCtx = oCanvas.getContext("2d");
			var page = 0;
			var loaded = false;
			for (page = 0; page <= maxpg; page += pagessize)
			{
				pages[page] = "/get/" + base64_encode(bookid + ":" + chapterid + ":" + pagessize + ":" + page);
			}

			var binaryImages = "";
			var pp = new ImageLoader(pages, function (aImages, nLoaded)
									 {
				if (format == "fb2")
				{

					aImages.forEach(function (item, i, aImages)
									{
						if (item.bLoaded)
						{
							oCtx.drawImage(item, 0, 0);
							pageHtml += '<image xlink:href="#page_' + i + '.jpg"/>\n';
							binaryImages += '<binary content-type="image/png" id="page_' + i + '.jpg">\n' + oCanvas.toDataURL("image/png", 1.0).replace('data:image/png;base64,', '') + '\n</binary>';
						}
					}
								   );

					pageHtml += '</section></body>';
					pageHtml += binaryImages;
					pageHtml += '</FictionBook>';
					var file = new File([pageHtml], BookTitle + '(' + PartTitle + ').fb2',
										{
						type : "text/plain;charset=utf-8"
					}
									   );
					saveAs(file, BookTitle + '(' + PartTitle + ').fb2');
				}
				else
				{
					var pdf = new jsPDF('p', 'pt', 'b5', 1);
					pdf.internal.pageSize = {height:480, widht:550};

					var pdfInternals = pdf.internal;
					var pdfPageSize = pdfInternals.pageSize;
					var pdfPageWidth = pdfPageSize.width;
					var pdfPageHeight = pdfPageSize.height;

					var flags = {noBOM:true, autoencode:true};

					pdf.text(BookTitle, pdfPageWidth / 3, 20, flags);
					pdf.text(PartTitle, pdfPageWidth / 3, 40, flags);

					aImages.forEach(function (item, i, aImages){
						if (item.bLoaded)
						{
							oCtx.drawImage(item, 0, 0);
							var img = oCanvas.toDataURL("image/png", 1.0);
							pdf.addPage();
							pdf.addImage(img, "png", 10, 70, 0, 0);
						}
					});

					pdf.save(BookTitle + '(' + PartTitle + ').pdf');
				}
			});

		}
	}
}

unsafeWindow.wait_for_text = function ()
{
	var text = document.getElementById("bookpgm");
	if (null === text)
	{
		var book = document.getElementsByClassName("booklnk4")[1];
		if (null === book)
			alert('No copyable text found!');
		else
		{
			var button = document.createElement("BUTTON");
			button.innerHTML = 'Get fb2';
			button.addEventListener('click', function ()
									{
				AllBook(book);
			}, true);
			book.parentNode.insertBefore(button, book);
		}
		return;
	}

	if (text.innerHTML.length > 100)
	{
		var button = document.createElement("BUTTON");
		button.innerHTML = 'Get fb2';
		button.addEventListener('click', function ()
								{
			unprotect(text);
		}, true);
		text.parentNode.insertBefore(button, text);
		var MaxProtection = my_getbyid("protected1").src !== '';
		if (MaxProtection)
		{
			var button2 = document.createElement("BUTTON");
			button2.innerHTML = 'Get pdf';
			button2.addEventListener('click', function ()
									 {
				unprotect(text, "pdf");
			}, true);
			text.parentNode.insertBefore(button2, text);			
		}
	}
	else
		window.setTimeout("wait_for_text()", 1000);
};

window.setTimeout("wait_for_text()", 1000);