// ==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 isRatingInFilename = 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 (isRatingInFilename) {
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('isRatingInFilename', true).then((myData) => {
isRatingInFilename = myData;
GMregisterMenuCommand("Toggle Rating in filename (" + isRatingInFilename + ")", () => {
GMsetValue('isRatingInFilename', !isRatingInFilename);
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;
}
// 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());
});
});