Hatchet_man

FB2 Converter for DM

May 23rd, 2020 (edited)
335
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name     FB2 Converter for DM
  3. // @version  1.2.5
  4. // @grant    none
  5. // @include  https://l.dm.am/ModuleInfo.aspx*
  6. // ==/UserScript==
  7.  
  8. /*
  9.  
  10. FB2 Converter
  11.  
  12. */
  13.  
  14. var rooms = document.querySelectorAll('a[id*="repRooms"]:not(.aspNetDisabled), a[id*="archiveRepRooms"]:not(.aspNetDisabled), a[id*="lnkSession"]');
  15.  
  16. if (window.location.href.indexOf('ModuleInfo') > 0) {
  17.  
  18.     //Загрузка файла в браузере
  19.     function download(data, filename, type) {
  20.         var file = new Blob([data], {type: type});
  21.         if (window.navigator.msSaveOrOpenBlob) // IE10+
  22.             window.navigator.msSaveOrOpenBlob(file, filename);
  23.         else { // Others
  24.             var a = document.createElement("a"),
  25.                 url = URL.createObjectURL(file);
  26.             a.href = url;
  27.             a.download = filename;
  28.             document.body.appendChild(a);
  29.             a.click();
  30.             setTimeout(function() {
  31.             document.body.removeChild(a);
  32.             window.URL.revokeObjectURL(url);  
  33.             }, 0);
  34.         }
  35.     }
  36.  
  37.     //Загрузка аватарок
  38.     async function getBase64ImageFromUrl(imageUrl) {
  39.     var name = imageUrl.match(/\d*\.jpg/);
  40.     var res = await fetch(imageUrl);
  41.     var blob = await res.blob();
  42.  
  43.     return new Promise((resolve, reject) => {
  44.         var reader  = new FileReader();
  45.         reader.addEventListener("load", function () {
  46.         resolve('["' + name +'","' + reader.result.replace("data:image/jpeg;base64,","") + '"]');
  47.         }, false);
  48.  
  49.         reader.onerror = () => {
  50.         return reject(this);
  51.         };
  52.         reader.readAsDataURL(blob);
  53.     })
  54.     }
  55.  
  56.     //Подготовка тегов
  57.     function replace_tags(content) {
  58.     var open = "";
  59.         var close = "";
  60.     content = content.replace(/<div><div><a href="javascript[^]+?none;">/g, "<br>");
  61.     content = content.replace(/<div class="spoiler-tag"><div><a href="javascript[^]+?none;">/g, "<br>");
  62.     content = content.replace(/<\/div><\/div><\/div>/g, "<br>");
  63.     content = content.replace(/<div class="nsfw-tag">[^]+?blurred-content">/g, "<br>");
  64.     content = content.replace(/<\/div>[^]+?<\/div><\/span><\/div>/g, "<br>");
  65.     content = content.replace(/<span class="nsfw-tag-end"><\/span>/g, "");
  66.     content = content.replace(/<(\/)?u>/g, "");
  67.     content = content.replace(/<(\/)?ul>/g, "");
  68.         content = content.replace(/<(\/)?ol>/g, "");
  69.     content = content.replace(/<(\/)?li>/g, "<br>");
  70.     content = content.replace(/<span class="comment">([^]+?)<\/span>/g, function (match, p1, offset, string) {
  71.         return "<br><sup>" + p1.replace(/<br>/g, "") + "</sup><br>";
  72.     });
  73.     content = content.replace(/<img src="([^]*?)">/g, function (match, p1, offset, string) {
  74.         p1 = p1.replace(/</g, "&lt;");
  75.         p1 = p1.replace(/>/g, "&gt;");
  76.         return '<a l:href="' + p1 + '">' + p1 + '<\/a>';
  77.     });
  78.     content = content.replace(/<a href="([^]*?)">ссылка/g, function (match, p1, offset, string) {
  79.         p1 = p1.replace(/</g, "&lt;");
  80.         p1 = p1.replace(/>/g, "&gt;");
  81.         return '<a l:href="' + p1 + '">' + p1;
  82.     });
  83.     content = content.replace(/<div class="greenText inline">([^]*?)<\/div>/g, "($1)");
  84.     content = content.replace(/(<br>)+/g, "</p><p>");
  85.     content = content.replace(/<span>([^]+?)<\/span>/g, function (match, p1, offset, string) {
  86.         return p1;
  87.     });
  88.     content = content.replace(/<span class="quote">/g, "<cite>");
  89.     content = content.replace(/<\/span>/g, "</cite>");
  90.     content = content.replace(/<(\/)?b>/g, "<$1strong>");
  91.     content = content.replace(/<(\/)?i>/g, "<$1emphasis>");
  92.     content = content.replace(/<(\/)?strike>/g, "<$1strikethrough>");
  93.     content = content.replace(/<(\/)?pre>/g, "<$1code>");
  94.     content = content.replace(/<(\/)?(cite|strong|emphasis|strikethrough|code|p)>/g, function (match, p1, p2, offset, string) {
  95.         if ((p2 == "strong" || p2 == "emphasis" || p2 == "strikethrough" || p2 == "code") && p1 == undefined) {
  96.         open = open + "<" + p2 + ">";
  97.         close = "</" + p2 + ">" + close;
  98.         return match;
  99.         }
  100.         if ((p2 == "strong" || p2 == "emphasis" || p2 == "strikethrough" || p2 == "code") && p1 !== undefined) {
  101.         var re_opn = new RegExp ("<" + p2 + ">([^]+?)?$");
  102.         open = open.replace(re_opn, "$1");
  103.                 var re_cls = new RegExp ("^([^]+?)?</" + p2 + ">");
  104.         close = close.replace(re_cls, "$1");
  105.         return match;
  106.         }
  107.         if (p2 == "p" && p1 !== undefined) {
  108.         return close + match;
  109.         }
  110.         if (p2 == "p" && p1 == undefined) {
  111.         return match + open;
  112.         }
  113.         if (p2 == "cite" && p1 == undefined) {
  114.         return close + match + "<p>" + open;
  115.         }
  116.         if (p2 == "cite" && p1 !== undefined) {
  117.         return close + "</p>" + match + open;
  118.         }
  119.         });
  120.     content = content.replace(/&nbsp;/g, " ");
  121.     return content;
  122.     }
  123.  
  124.     //Подготовка загрузки
  125.     function prepare_download() {
  126.     var main = document.getElementById("main");
  127.     var workframe = document.createElement("div");
  128.     var insert = "<p><b>Опции</b></p>";
  129.     insert += "<p><input type='checkbox' id='chars'> Выгружать чарлисты</p>";
  130.     insert += "<p><input type='checkbox' id='avatars'> Отображать аватары в постах</p>";
  131.     insert += "<p><b>Выберите комнаты для выгрузки</b></p>";
  132.     insert += "<p><input type='checkbox' id='toggle'> <i>Выделить/снять все</i></p>";
  133.     workframe.setAttribute("id", "workframe");
  134.     workframe.setAttribute("style", "position:absolute;top:0px;left:500px;background-color:white;padding:50px;border:1px solid black;max-height:500px;max-width:300px;overflow:scroll;white-space:nowrap;");
  135.     for (var i = 0; i < rooms.length; i++) {
  136.         insert = insert + "<p><input type='checkbox' name='selection' value='" + i + "'> " + rooms[i].innerHTML + "&nbsp;</p>";
  137.     }
  138.     insert = insert+ "<p><input id='start_convert' type='button' value='Старт'>&nbsp;&nbsp;&nbsp;&nbsp;<input id='cancel' type='button' value='Закрыть' onclick='this.parentElement.parentElement.remove();'></p>";
  139.         workframe.innerHTML = insert;
  140.     main.appendChild(workframe);
  141.     document.getElementById("start_convert").addEventListener("click", convert);
  142.     document.getElementById("toggle").addEventListener("change", toggle);
  143.     }
  144.  
  145.     //Выделить все
  146.     function toggle() {
  147.     var selection = document.querySelectorAll('input[name=selection]');
  148.     if (document.getElementById("toggle").checked == true) {
  149.         for (var i = 0; i < selection.length; i++) {
  150.             selection[i].checked = true;
  151.             }
  152.     } else {
  153.         for (var i = 0; i < selection.length; i++) {
  154.             selection[i].checked = false;
  155.             }
  156.     }
  157.     }
  158.  
  159.     //Загрузка страницы
  160.     function loadifrm (item, page, pagesize, href) {
  161.     if (href == null)  href = "https://l.dm.am/" + rooms[item].getAttribute("href").replace(/#\d+$/, "") + "&page=" + page + "&pagesize=" + pagesize;
  162.     var xhr= new XMLHttpRequest();
  163.     xhr.open('GET', href, false);
  164.         xhr.send();
  165.     if (xhr.status != 200) {
  166.         return ("error");
  167.     } else {
  168.         var parser = new DOMParser ();
  169.             var doc = parser.parseFromString (xhr.response, "text/html");
  170.         return (doc);
  171.     }
  172.     }
  173.  
  174.     function convert() {
  175.     //Готовим формат FB2
  176.     var fb2 = '<?xml version="1.0" encoding="utf-8"?><FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>adventure</genre>';
  177.     var tags = document.getElementById("ctl00_mainContent_panTags").children;
  178.     var tags_arr = new Map([
  179.         ['Альтернативная история', 'sf_history'],
  180.         ['Боевик', 'det_action'],
  181.         ['Детектив', 'detective'],
  182.         ['Киберпанк', 'sf_cyberpunk'],
  183.         ['Космоопера', 'sf_space'],
  184.         ['Триллер', 'thriller'],
  185.         ['Ужас', 'sf_horror'],
  186.         ['Фентези', 'sf_fantasy']
  187.         ]);
  188.     for (var i = 0; i < tags.length; i++) {
  189.             if (tags_arr.has(tags[i].innerHTML)) {
  190.         fb2 = fb2 + "<genre>" + tags_arr.get(tags[i].innerHTML) + "</genre>";
  191.         }
  192.     }
  193.     fb2 = fb2 + "<author><nickname>" + document.getElementById('ctl00_mainContent_lnkMaster').innerHTML + "</nickname></author>";
  194.     var title = document.querySelector('#ctl00_mainContent_panModuleInfo > h1').innerHTML.replace(/([^]+?) \| Описание игры/, "$1").trim();
  195.     fb2 = fb2 + "<book-title>" + title + "</book-title>";
  196.     fb2 = fb2 + "<lang>ru</lang></title-info><document-info><author><nickname>Hatchet</nickname></author><program-used>FB2 Converter for DM</program-used>";
  197.     var time = new Date(Date.now());
  198.     date = time.getFullYear() + '-' + ('0' + (time.getMonth() + 1)).slice(-2) + '-' + ('0' + time.getDate()).slice(-2);
  199.     var time = time.getHours() + '-' + time.getMinutes() + '-' + time.getSeconds();
  200.     fb2 = fb2 + '<date value="' + date + '">' + date + '</date>';
  201.     fb2 = fb2 + "<src-url>" + window.location.href + "</src-url>";
  202.     fb2 = fb2 + "<id>" + date + "-" + time + "</id>";
  203.     fb2 = fb2 + "<version>1.2.5</version>";
  204.  
  205.     fb2 = fb2 + "</document-info>";
  206.  
  207.     fb2 = fb2 + "</description><body>";
  208.  
  209.     var progress = document.createElement("span");
  210.     progress.setAttribute("style", "color:#393;");
  211.     progress.innerHTML = "&nbsp;Загрузка";
  212.     var loaderror = document.createElement("span");
  213.     loaderror.innerHTML = "&nbsp;Ошибка загрузки или комната не содержит сообщений";
  214.     loaderror.setAttribute("style", "color:#933;");
  215.     var readyerror = document.createElement("span");
  216.     readyerror.innerHTML = "&nbsp;Ошибка загрузки";
  217.     readyerror.setAttribute("style", "color:#933;");
  218.  
  219.     //Загрузка персонажей и аватарок
  220.     document.getElementById("start_convert").remove();
  221.     var chars_select = document.getElementById("chars");
  222.     var avs_select = document.getElementById("avatars");
  223.     if (chars_select.checked || avs_select.checked) {
  224.         if (chars_select.checked) chars_select.parentNode.appendChild(progress.cloneNode(true));
  225.         if (avs_select.checked) avs_select.parentNode.appendChild(progress.cloneNode(true));
  226.         var href = window.location.href.replace("ModuleInfo", "PlayerProfiles");
  227.         var chars = loadifrm(null, null, null, href);
  228.         if (chars == "error") {
  229.         if (chars_select.checked) chars_select.parentNode.appendChild(readyerror.cloneNode(true));
  230.         if (avs_select.checked) avs_select.parentNode.appendChild(readyerror.cloneNode(true));
  231.         } else {
  232.         if (chars_select.checked) {
  233.             var chrs = chars.querySelectorAll(".padding5");
  234.             if (chrs) {
  235.                 fb2 = fb2 + "<section><title><p>Персонажи</p></title>";
  236.                 for (var i = 0; i < chrs.length; i++) {
  237.                 fb2 = fb2 + "<p><b>" + chrs[i].querySelector("h2").innerHTML + "</b></p>";
  238.                 if (chrs[i].querySelector('img[id*="imgAvatar"]')) fb2 = fb2 + "<image l:href='#"+ chrs[i].querySelector('img[id*="imgAvatar"]').src.match(/\d*\.jpg/) + "'/>";
  239.                 fb2 = fb2 + "<p><b>Автор:</b> " + chrs[i].querySelector('a[id*="lnkPlayer"]').innerHTML + "</p>";
  240.                 var char_info = chrs[i].querySelectorAll(".p");
  241.                 for (var j = 1; j < char_info.length; j++) {
  242.                     fb2 = fb2 + "<p>" + replace_tags(char_info[j].innerHTML).replace("Информация доступна только мастеру и хозяину персонажа.", "") + "</p>";
  243.                 }
  244.                 }
  245.                 fb2 = fb2 + "</section>";
  246.             } else {
  247.                 chars_select.parentNode.appendChild(readyerror.cloneNode(true));
  248.             }
  249.         }
  250.             var avs = chars.querySelectorAll('img[id*="imgAvatar"]');
  251.         if (avs) {
  252.             var avs_res = "";
  253.                 for (var i = 0; i < avs.length; i++) {
  254.                 var src = avs[i].src.replace(/\?[^]*/, "");
  255.                 getBase64ImageFromUrl(src).then(
  256.                     result => {
  257.                     var json = JSON.parse(result);
  258.                     avs_res = avs_res + "<binary id='" + json[0] + "' content-type='image/jpeg'>" + json[1] + "</binary>"
  259.                     },
  260.                     error => {
  261.                 if (avs_select.checked) avs_select.parentNode.appendChild(readyerror.cloneNode(true));
  262.                 if (chars_select.checked) chars_select.parentNode.appendChild(readyerror.cloneNode(true));
  263.                 }
  264.                 );
  265.                 }
  266.         } else {
  267.             if (avs_select.checked) avs_select.parentNode.appendChild(readyerror.cloneNode(true));
  268.             if (chars_select.checked) chars_select.parentNode.appendChild(readyerror.cloneNode(true));
  269.         }
  270.         }
  271.     }
  272.  
  273.     //Загрузка комнат
  274.     var selection = document.querySelectorAll('input[name=selection]');
  275.     var selected = [];
  276.     for (var i = 0; i < selection.length; i++) {
  277.         if (selection[i].checked == true) selected.push(selection[i].value);
  278.     }
  279.     selected.forEach(function(item, i, arr) {
  280.         var page = 1;
  281.         selection[item].parentNode.appendChild(progress.cloneNode(true));
  282.         do {
  283.         selection[item].parentNode.children[1].innerHTML += ">";
  284.             var pagesize = 100;
  285.             var loaded = loadifrm (item, page, pagesize, null);
  286.         if (loaded == "error") {
  287.             selection[item].parentNode.appendChild(readyerror.cloneNode(true));
  288.             break;
  289.         }
  290.             var pager = loaded.querySelector(".pager");
  291.             if (pager) {
  292.             pager = pager.querySelectorAll("a, span");
  293.             if (pager[0].tagName == "SPAN") var first = true;
  294.             if (pager[pager.length - 1].tagName == "SPAN") var last = true;
  295.             } else {
  296.             var first = true;
  297.             var last = true;
  298.             }
  299.             if (first == true) {
  300.             fb2 = fb2 + "<section><title><p>" + rooms[item].innerHTML + "</p></title>";
  301.             first = false;
  302.             }
  303.             var posts = loaded.getElementsByClassName("commentItem").length;
  304.             if (posts !== 0) {
  305.             var author = loaded.getElementsByClassName("gray6");
  306.             for (var i = 0; i < posts; i++) {
  307.                 var post_id = "[id$='lblBody_" + i + "']>.p";
  308.                 var comment_id = "[id$='lblComment_" + i + "']";
  309.                 var author_i = author[i].innerHTML + ":";
  310.                 var avatar = false;
  311.                 if (avs_select.checked && loaded.querySelector("[id$='imgAvatar_" + i + "']")) avatar = loaded.querySelector("[id$='imgAvatar_" + i + "']").src.match(/\d*\.jpg/);
  312.                 var post_content = loaded.querySelector(post_id).innerHTML;
  313.  
  314.                 //Готовим текст поста для выгрузки
  315.                 author_i = author_i.replace(/<(\/)?b>/g, "<$1strong>");
  316.                 post_content = replace_tags(post_content);
  317.  
  318.                 //Готовим комментарий для выгрузки
  319.                 if (loaded.querySelector(comment_id).innerHTML !== "") {
  320.                 var comment = loaded.querySelector(comment_id).firstChild.innerHTML;
  321.                 comment = "</p><p>----------</p><p>" + comment;
  322.                 comment = replace_tags(comment);
  323.                 } else var comment = "";
  324.                 if (avatar) fb2 = fb2 + "<image l:href='#"+ avatar + "'/>";
  325.                 fb2 = fb2 + "<p>" + author_i + "</p><p>" + post_content + comment + "</p>";
  326.             }
  327.             } else {
  328.             selection[item].parentNode.appendChild(loaderror.cloneNode(true));
  329.             fb2 = fb2 + "</section>";
  330.             break;
  331.             }
  332.             if (last == true) {
  333.             fb2 = fb2 + "</section>";
  334.             }
  335.             page++;
  336.         } while (last !== true);
  337.         });
  338.     fb2 = fb2 + "</body>";
  339.  
  340.         fb2 = fb2 + avs_res;
  341.  
  342.     fb2 = fb2 + "</FictionBook>";
  343.     download (fb2, title + ".fb2", "text/plain");  
  344.     }
  345.  
  346.     var actions = document.getElementById("ctl00_leftMenu_ctl00_lnkManagePlayers").outerHTML;
  347.     if (document.getElementById("dwnld") == null) {
  348.         document.getElementById("ctl00_leftMenu_ctl00_lnkManagePlayers").outerHTML = actions + "<br>- <a id='dwnld' href='javascript:void(0);'>Скачать в формате FB2</a>";
  349.         document.getElementById("dwnld").addEventListener("click", prepare_download);
  350.     }
  351. }
Add Comment
Please, Sign In to add comment