Sleazy Fork is available in English.

Literotica Downloader

Single page HTML download for Literotica with improved readability

25.04.2021 itibariyledir. En son verisyonu görün.

// ==UserScript==
// @name        Literotica Downloader
// @description Single page HTML download for Literotica with improved readability
// @namespace   literotica_downloader
// @include     https://www.literotica.com/stories/memberpage.php*
// @require     https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @require     https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js
// @version     2.9
// @grant           GM_info
// @grant           GM_registerMenuCommand
// @grant           GM.registerMenuCommand
// @grant           GM_unregisterMenuCommand
// @grant           GM_openInTab
// @grant           GM_getValue
// @grant           GM.getValue
// @grant           GM_setValue
// @grant           GM.setValue
// @grant           GM_notification
// @grant           GM.notification
// @author      Improved by a random redditor and @nylonmachete, originally by Patrick Kolodziejczyk
// ==/UserScript==

// Those valuse can be modifyed by the icon GreaseMonkey > User script commands > Toggle ...
var options= {
	'isNightMode' : true,
	'isUsernameInFilename' : true,
	'isDescriptionInFilename' : false,
	'isNoteInFilename' : false,
	'isCategoryInFilename' : false
}

// @grant
var SEPARATOR = '_';
var PREFIX_NOTE = 'RATING_';
var bodyStyleNight = ' style="background-color:#333333; color: #EEEEEE; font-family: Helvetica,Arial,sans-serif; width: 50%; margin: 0 auto; line-height: 1.5em; font-size:2.2em; padding: 50px 0 50px 0;" ';
var bodyStyle = ' style="font-family: Helvetica,Arial,sans-serif; width: 50%; margin: 0 auto; line-height: 1.5em; font-size:2.2em; padding: 50px 0 50px 0;" ';
var chapterStyle = '_style="line-height: 1.4em;" ';
var descriptionStyle = ' style="line-height: 1.2em;" ';
// Creating style for a download icon
var iconDonwload = ' style=\'background-image: url("https://marcoceppi.github.io/bootstrap-glyphicons/img/glyphicons-halflings.png");     background-position: -120px -24px;cursor: pointer;cursor: hand;    background-repeat: no-repeat;    display: inline-block;    height: 14px;    line-height: 14px;    vertical-align: text-bottom;    width: 14px;}\'';
var messagePleaseRefreshPage= 'For the modification to be taken into account.\nPlease refresh the page.';
function buildFilename(title, author, description, note, category) {
    var toReturn = title;
    if (options.isUsernameInFilename) {
        toReturn = toReturn + SEPARATOR + author;
    }
    if (options.isDescriptionInFilename) {
        if (description != null && description != "") {
            toReturn = toReturn + SEPARATOR + description.replace(/[^\w\s]/gi, '');
        }
    }
    if (options.isNoteInFilename) {
        if (note != null && note != "") {
            toReturn = toReturn + SEPARATOR + PREFIX_NOTE + note;
        }
    }
    if (options.isCategoryInFilename) {
        if (category != null && category != "") {
            toReturn = toReturn + SEPARATOR + category;
        }
    }
    // Add file extension;
    toReturn = toReturn + '.html';
    return toReturn;
}
$("head").append (
	// loading CSS JqueryUI for options menu
  '<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css">'
);
$(document).ready(function() {
    'use strict';
    const isdebug = false;
    const debug = isdebug ? console.log.bind(console) : () => {};

    /* Perfectly Compatible For Greasemonkey4.0+, TamperMonkey, ViolentMonkey * F9y4ng * 20210209 */

    let GMsetValue, GMgetValue, GMregisterMenuCommand, GMunregisterMenuCommand, GMnotification, GMopenInTab;
    const GMinfo = GM_info;
    const handlerInfo = GMinfo.scriptHandler;
    const isGM = Boolean(handlerInfo.toLowerCase() === 'greasemonkey');

    debug(`//-> CheckGM: ${isGM} >> ${handlerInfo}`);
		var panelOptionDownloader=  `
<div id="literoticaDownloaderOption" title="Options Literotica Downloader" >
   Please Configure the options :
	<fieldset>
      <legend>Reading: </legend>
			<div>
      	<input type="checkbox" name="isNightMode" id="isNightMode" class="ldCheckbox">
    	  <span>Night Mode</span>
   	</div>
	</fieldset>
   <fieldset>
      <legend>Filename: </legend>
      <div>
         <input type="checkbox" name="isUsernameInFilename" id="isUsernameInFilename" class="ldCheckbox">
         <span>Username in filename</span>
      </div>
      <div>
         <input type="checkbox" name="isDescriptionInFilename" id="isDescriptionInFilename" class="ldCheckbox">
         <span>Description in filename (Not on series)</span>
      </div>
      <div>
         <input type="checkbox" name="isNoteInFilename" id="isNoteInFilename" class="ldCheckbox">
         <span>Rating in filename (Not on series)</span>
      </div>
      <div>
         <input type="checkbox" name="isCategoryInFilename" id="isCategoryInFilename" class="ldCheckbox">
         <span>Category in filename (Not on series)</span>
      </div>
   </fieldset>
</div>
`;
  $('body').append(panelOptionDownloader);
  // Handle of change of value by user.
  $('.ldCheckbox').change(function onChangeCheckBox(checkbox){
    GMsetValue(this.id, this.checked);
    options[this.id] = this.checked;
  });
  $( "#literoticaDownloaderOption" ).dialog({ autoOpen: false, width: 350 });

    if (isGM) {
        GMsetValue = GM.setValue;
        GMgetValue = GM.getValue;
        GMregisterMenuCommand = GM.registerMenuCommand;
        GMunregisterMenuCommand = () => {};
        GMnotification = GM.notification;
        console.log("It's GM !");
    } else {
        console.log("Other")
        GMsetValue = GM_setValue;
        GMgetValue = GM_getValue;
        GMregisterMenuCommand = GM_registerMenuCommand;
        GMunregisterMenuCommand = GM_unregisterMenuCommand;
    }
  // Globale registry of the options menu.
  GMregisterMenuCommand("Literotica Downloader Options", () => {
    $( "#literoticaDownloaderOption" ).dialog( "open" );
  });
    	function initCheckBox(element, index, array) {
			if (isGM) {
				GMgetValue(element,  options[element]).then((myData) => {
					options[element] = myData;
					$("#"+element)[0].checked= options[element];
				});
			}else {
				options[element] = GMgetValue(element, options[element]);
				$("#"+element)[0].checked= options[element];
			}

			return true;
		}
  // Init of all options
  Object.getOwnPropertyNames(options).every(initCheckBox)

    // Function used to return content as a file for the user.
    function saveTextAsFile(textToWrite, fileNameToSaveAs) {
        var textFileAsBlob = new Blob([textToWrite], {
            type: 'text/javascript'
        });
        var downloadLink = document.createElement('a');
        downloadLink.download = fileNameToSaveAs;
        downloadLink.innerHTML = 'Download File';
        // Firefox requires the link to be added to the DOM
        // before it can be clicked.
        downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
        //downloadLink.onclick = destroyClickedElement;
        downloadLink.style.display = 'none';
        document.body.appendChild(downloadLink);
        downloadLink.click();
    }
    // Function parsing all pages to get the storie based
    function getContentOfStoie(baseURL) {
        console.log("Fetching " + baseURL);
        var remote;
        $.ajax({
            url: baseURL,
            type: 'GET',
            async: false,
            crossDomain: true,
            success: function(data) {
                if ($(data).find('a.l_bJ.l_bL').size() > 0) {
                    console.log($(data).find('a.l_bJ.l_bL').size());
                    remote = $(data).find('.panel.article.aa_eQ .aa_ht').html() + getContentOfStoie($(data).find('a.l_bJ.l_bL')[0].href);
                } else {
                    remote = $(data).find('.panel.article.aa_eQ .aa_ht').html();
                }
            }
        });
        return remote;
    }

    function getABookForSerieDiv(myDiv) {
        var title = $.trim(myDiv.text().split(':')[0]);
        // Get the X Part Series
        var descriptionSeries = $.trim(myDiv.text().split(':')[1]);
        var author = $('.contactheader').text();
        alert("Starting building file for " + title + " of " + author + ".\nPlease wait...");
        var book = '<html>\n<head>\n<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">\n';
        book += '<title>' + title + '</title>';
        book += '<meta content="' + author + '" name="author">';
      	if(options.isNightMode){
          book += '</head>\n<body ' + bodyStyleNight + ' >';
        }else  {
        	book += '</head>\n<body ' + bodyStyle + ' >';
        }

        function addChapter(element, index, array) {
            if ($(this).find('a').size() > 0) {
                var chapeterTitle = $($(this).find('td a')[0]).text();
                var description = $($(this).find('td')[1]).text();
                book += '<h1 class=\'chapter\'' + chapterStyle + '>' + chapeterTitle + '</h1>';
                book += '<h2 class=\'chapter\'' + descriptionStyle + '>' + description + '</h2>';
                var link = $($(this).find('a')[0]);
                book += getContentOfStoie(link.attr('href'));
            }
        }
        myDiv.nextUntil('.ser-ttl,.root-story').each(addChapter);
        saveTextAsFile(book, buildFilename(title, author, descriptionSeries, ));
    }

    function getABookForStoryDiv(myDiv) {
        var title = $.trim($($(myDiv)).text().split('(')[0]);
        var note = $.trim($($(myDiv)).text().split('(')[1]).replace(")", "");
        if ($(myDiv).find('a').size() >= 0) {
            var chapterTitle = $($(myDiv.parent()).find('td a')[0]).text();
            var description = $($(myDiv.parent()).find('td')[1]).text();
            var category = $($(myDiv.parent()).find('td')[2]).text();
        }
        var author = $('.contactheader').text();
        var book = '<html>\n<head>\n<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">\n';
        console.log('title' + title);
        book += '<title>' + title + '</title>';
        book += '<meta content="' + author + '" name="author">';
        book += '<meta content="' + author + '" name="author">';
        if(options.isNightMode){
          book += '</head>\n<body ' + bodyStyleNight + ' >';
        }else  {
        	book += '</head>\n<body ' + bodyStyle + ' >';
        }
        book += '<h1 class=\'chapter\'' + chapterStyle + '>' + chapterTitle + '</h1>';
        book += '<h2 class=\'chapter\'' + descriptionStyle + '>' + description + '</h2>';
        var link = $($(myDiv).find('a')[0]);
        book += getContentOfStoie(link.attr('href'));

        saveTextAsFile(book, buildFilename(title, author, description, note, category));
    }
    $('.ser-ttl td:nth-child(1)').prepend('<span ' + iconDonwload + '></span>');
    $('.ser-ttl td:nth-child(1) span').click(function() {
        getABookForSerieDiv($(this).parent().parent());
    });
    var idIcon = Math.floor(Math.random() * 100);
    $('.root-story td:nth-child(1), .sl td:nth-child(1)').prepend('<span ' + iconDonwload + ' id="' + idIcon + '"></span>');
    $('.root-story td:nth-child(1), .sl td:nth-child(1) span').click(function() {
        getABookForStoryDiv($(this).parent());
    });
});