Literotica Downloader

Single page HTML download for Literotica with improved readability

Versione datata 13/04/2021. Vedi la nuova versione l'ultima versione.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==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
// @version     2.8
// @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 isUsernameInFilename = true;
var isDescriptionInFilename = false;
var isNoteInFilename = false;
var isCategoryInFilename = false;

// @grant 
var SEPARATOR = '_';
var PREFIX_NOTE = 'NOTE_';
var bodyStyle = ' 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 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 (isUsernameInFilename) {
        toReturn = toReturn + SEPARATOR + author;
    }
    if (isDescriptionInFilename) {
        if (description != null && description != "") {
            toReturn = toReturn + SEPARATOR + description.replace(/[^\w\s]/gi, '');
        }
    }
    if (isNoteInFilename) {
        if (note != null && note != "") {
            toReturn = toReturn + SEPARATOR + PREFIX_NOTE + note;
        }
    }
    if (isCategoryInFilename) {
        if (category != null && category != "") {
            toReturn = toReturn + SEPARATOR + category;
        }
    }
    // Add file extension;
    toReturn = toReturn + '.html';
    return toReturn;
}
$(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}`);

    if (isGM) {

        GMsetValue = GM.setValue;
        GMgetValue = GM.getValue;
        GMregisterMenuCommand = GM.registerMenuCommand;
        GMunregisterMenuCommand = () => {};
        GMnotification = GM.notification;
        GMopenInTab = (a, b) => {
            window.open(a, Math.random().toString(36).slice(-6), '', b instanceof String);
        };
        console.log("It's GM !");

        GMgetValue('isUsernameInFilename', true).then((myData) => {
            isUsernameInFilename = myData;
            GMregisterMenuCommand("Toggle Username in filename (" + isUsernameInFilename + ")", () => {
                GMsetValue('isUsernameInFilename', !isUsernameInFilename);
                alert(messagePleaseRefreshPage);
            });

        });
        GMgetValue('isDescriptionInFilename', true).then((myData) => {
            isDescriptionInFilename = myData;
            GMregisterMenuCommand("Toggle Description in filename (" + isDescriptionInFilename + ")", () => {
                GMsetValue('isDescriptionInFilename', !isDescriptionInFilename);
                alert(messagePleaseRefreshPage);
            });
        });
        GMgetValue('isNoteInFilename', true).then((myData) => {
            isNoteInFilename = myData;
            GMregisterMenuCommand("Toggle Rating in filename (" + isNoteInFilename + ")", () => {
                GMsetValue('isNoteInFilename', !isNoteInFilename);
                alert(messagePleaseRefreshPage);
            });
        });
        GMgetValue('isCategoryInFilename', true).then((myData) => {
            isCategoryInFilename = myData;
            GMregisterMenuCommand("Toggle Category in filename (" + isCategoryInFilename + ")", () => {
                GMsetValue('isCategoryInFilename', !isCategoryInFilename);
                alert(messagePleaseRefreshPage);
            });
        });
    } else {
        console.log("Other")
        GMsetValue = GM_setValue;
        GMgetValue = GM_getValue;
        GMregisterMenuCommand = GM_registerMenuCommand;
        GMunregisterMenuCommand = GM_unregisterMenuCommand;
        GMnotification = GM_notification;
        GMopenInTab = GM_openInTab;
        isUsernameInFilename = GMgetValue('isUsernameInFilename', true);
        GMregisterMenuCommand("Toggle Username in filename (" + isUsernameInFilename + ")", () => {
            GMsetValue('isUsernameInFilename', !isUsernameInFilename);
            alert(messagePleaseRefreshPage);
        });
        isDescriptionInFilename = GMgetValue('isDescriptionInFilename', true);
        GMregisterMenuCommand("Toggle Description in filename (" + isDescriptionInFilename + ")", () => {
            GMsetValue('isDescriptionInFilename', !isDescriptionInFilename);
            alert(messagePleaseRefreshPage);
        });
        isNoteInFilename = GMgetValue('isNoteInFilename', true);
        GMregisterMenuCommand("Toggle Rating in filename (" + isNoteInFilename + ")", () => {
            GMsetValue('isNoteInFilename', !isNoteInFilename);
            alert(messagePleaseRefreshPage);
        });
        isCategoryInFilename = GMgetValue('isCategoryInFilename', true);
        GMregisterMenuCommand("Toggle Category in filename (" + isCategoryInFilename + ")", () => {
            GMsetValue('isCategoryInFilename', !isCategoryInFilename);
            alert(messagePleaseRefreshPage);
        });
    }
    

    // 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">';
        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">';
        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());
    });
});