Advertisement
Guest User

MangaBat bookmarks exporter

a guest
Feb 22nd, 2025
426
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 12.94 KB | Software | 0 0
  1. // ==UserScript==
  2. // @name         Mananelo/Mangakakalot/Manganato/Manga4life Bookmarks Export
  3. // @namespace    http://smoondev.com/
  4. // @version      2.26
  5. // @description  Writes Mangakakalot, Manganelo, Manganato, Manga4life Bookmarks (name and visited number) to "manga_bookmarks.txt" on "Export Bookmarks" button click
  6. // @author       Shawn Moon
  7. // @match        https://*.mangabat.com/bookmark*
  8. // @match        https://mangabat.com/bookmark*
  9. // @require      http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
  10. // @require      https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js
  11. // ==/UserScript==
  12.  
  13. function addBookarkStyles(css) {
  14.     var head, style;
  15.     head = document.getElementsByTagName('head')[0];
  16.     if (!head) { return; }
  17.     style = document.createElement('style');
  18.     style.type = 'text/css';
  19.     style.innerHTML = css;
  20.     head.appendChild(style);
  21. }
  22.  
  23. addBookarkStyles(`
  24. #export_container_nato, #export_container_kakalot, #export_container_m4l {
  25.   color: #000;
  26.   cursor: pointer;
  27.   float: right;
  28. }
  29.  
  30. #export_container_fun {
  31.   display: inline-block;
  32.   vertical-align: bottom;
  33. }
  34.  
  35. #export_container_kakalot {
  36.   margin-right: 10px;
  37. }
  38.  
  39. #export_nato:hover, #export_kakalot:hover, #export_m4l:hover {
  40.   background-color: #b6e4e3;
  41.   color: #000;
  42.   cursor: pointer;
  43. }
  44.  
  45. #export_nato, #export_kakalot, #export_m4l {
  46.   border-radius: 5px;
  47.   text-decoration: none;
  48.   color: #fff;
  49.   background-color: #76cdcb;
  50.   border: none;
  51.   font-weight: 600;
  52. }
  53.  
  54. #export_nato, #export_kakalot {
  55.   padding: 4px 8px;
  56. }
  57.  
  58. #export_m4l {
  59.   padding: 1px 12px;
  60.   font-size: 16.5px;
  61. }
  62.  
  63. #export_fun {
  64.   color: #f05759;
  65.   background-color: #fff;
  66.   border: 1px solid #f05759;
  67.   display: inline-block;
  68.   margin-bottom: 0;
  69.   font-weight: 400;
  70.   text-align: center;
  71.   touch-action: manipulation;
  72.   cursor: pointer;
  73.   white-space: nowrap;
  74.   padding: 6px 12px;
  75.   border-radius: 0;
  76.   user-select: none;
  77.   transition: all .2s ease-in-out;
  78. }
  79.  
  80. #export_fun:hover {
  81.   color: #fff;
  82.   background-color: #f05759;
  83. }
  84.  
  85. #inclURL_nato, #inclURL_kakalot, #inclURL_fun, #inclURL_m4l {
  86.   margin-left: 10px;
  87. }
  88.  
  89. .inclURL_kakalot, .inclURL_m4l {
  90.   color: #ffffff;
  91. }
  92.  
  93. .inclURL_m4l {
  94.   color: #ffffff;
  95.   font-size: 15px;
  96.   font-weight: 500;
  97. }
  98.  
  99. .inclURL_fun {
  100.   font-weight:normal;
  101. }
  102.  
  103. #temp_data {
  104.   position: absolute; top: -9999px;
  105.   left: -9999px;
  106. }
  107. `);
  108.  
  109. (async function() {
  110.     'use strict';
  111.     let pageI, bmTag, bmTitle, lastViewed, btnContainer, exportButtonID, inclURL, bookmarkedTitles = '',
  112.         exportContainer, pageCount = 0, domain = window.location.hostname, bmLabel = 'Bookmarks'
  113.  
  114.     if(domain == 'mangabat.com' || domain == 'h.mangabat.com') {
  115.         pageI = '.group_page a'
  116.         bmTag = '.user-bookmark-item'
  117.         bmTitle = '.bm-title'
  118.        // lastViewed = '.bookmark_chap a'
  119.         btnContainer = '.panel-breadcrumb'
  120.  
  121.         inclURL = 'inclURL_kakalot'
  122.         pageCount = parseInt($(`${pageI}`).last().text().replace(/\D+/g, ''))
  123.         exportButtonID = 'export_kakalot'
  124.         exportContainer = 'export_container_kakalot'
  125.     } else if(domain == 'manganato.com' || domain == 'm.manganelo.com') {
  126.         btnContainer = '.panel-breadcrumb'
  127.  
  128.         inclURL = 'inclURL_nato'
  129.         exportButtonID = 'export_nato'
  130.         exportContainer = 'export_container_nato'
  131.     } else if (domain == 'mangakakalot.fun') {
  132.         bmTag = '.list-group-item'
  133.         bmTitle = '.media-heading a'
  134.         lastViewed = '.media-body p a'
  135.         btnContainer = '.container-fluid:first div:last'
  136.  
  137.         inclURL = 'inclURL_fun'
  138.         exportButtonID = 'export_fun'
  139.         exportContainer = 'export_container_fun'
  140.     } else if (domain == 'manga4life.com') {
  141.         inclURL = 'inclURL_m4l'
  142.         exportButtonID = 'export_m4l'
  143.         btnContainer = '.BoxHeader'
  144.         exportContainer = 'export_container_m4l'
  145.         if(!window.location.pathname.includes('bookmark.php')) {
  146.             bmLabel = 'Subscriptions'
  147.         }
  148.     }
  149.  
  150.     const waitFor = delay => new Promise(resolve => setTimeout(resolve, delay));
  151.  
  152.     const saveFile = saveData => {
  153.         // save file
  154.         const fileData = new Blob([saveData], {type:"application/octet-stream"})
  155.         saveAs(fileData, "manga_bookmarks.txt")
  156.  
  157.         $(`#${exportButtonID}`).html(`Export ${bmLabel}`).prop('disabled', false)
  158.     }
  159.  
  160.     const deleteTemp = () => {
  161.         // delete temp container
  162.         $('#temp_data').remove()
  163.     }
  164.  
  165.     const getCookie = (name = 'user_acc') => {
  166.         let returnVal = false
  167.         const value = `; ${document.cookie}`
  168.         try {
  169.             const parts = value.split(`; ${name}=`)
  170.             if (parts.length === 2) {
  171.                 let user = parts.pop().split(';').shift()
  172.                 if(name == 'user_acc') {
  173.                     user = JSON.parse(decodeURIComponent(user))
  174.                     returnVal = user.user_data
  175.                 }
  176.  
  177.             }
  178.         } catch (e) {
  179.             returnVal = false
  180.         }
  181.  
  182.         return returnVal
  183.     }
  184.  
  185.     const getBMs = async (userCookie, currentPage = 1) => {
  186.         var myHeaders = new Headers();
  187.         myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
  188.  
  189.         var urlencoded = new URLSearchParams();
  190.         urlencoded.append("out_type", "json");
  191.         urlencoded.append("bm_source", "manganato");
  192.         urlencoded.append("bm_page", currentPage);
  193.         urlencoded.append("user_data", userCookie);
  194.  
  195.         var requestOptions = {
  196.             method: 'POST',
  197.             headers: myHeaders,
  198.             body: urlencoded,
  199.             redirect: 'follow'
  200.         };
  201.  
  202.         let bmArray = []
  203.  
  204.         return await fetch("https://user.mngusr.com/bookmark_get_list_full", requestOptions)
  205.             .then(response => response.json())
  206.             .then(result => result)
  207.             .catch(error => console.log('ExportError', error));
  208.     }
  209.  
  210.     const getFunBMs = (url) => {
  211.         let bmItems = $(`${bmTag}`)
  212.         for(let i = 0; i < bmItems.length; i++) {
  213.             let title = $(bmItems[i]).find(bmTitle)[0]?.text || false
  214.             let lastViewed = $(bmItems[i]).find('.media-body p a')[0] || false
  215.             bookmarkedTitles += `${title} || Viewed: ${lastViewed ? lastViewed.text : 'None'} ${url ? (lastViewed ? `- ${lastViewed.href}` : '') : ''} \n`
  216.         }
  217.         saveFile(bookmarkedTitles)
  218.     }
  219.  
  220.     const getM4LBMs = (url) => {
  221.         var myHeaders = new Headers();
  222.         let userCookie = document.cookie
  223.         myHeaders.append("cookie", userCookie);
  224.  
  225.         var urlencoded = new URLSearchParams();
  226.  
  227.         var requestOptions = {
  228.             method: 'POST',
  229.             headers: myHeaders,
  230.             body: urlencoded,
  231.             redirect: 'follow'
  232.         };
  233.  
  234.         let isM4LBM = window.location.pathname.includes('bookmark.php')
  235.  
  236.         fetch(`https://manga4life.com/user/${isM4LBM ? 'bookmark.get.php' : 'subscription.get.php'}`, requestOptions)
  237.             .then(response => response.json())
  238.             .then(result => {
  239.                 let {success = false, val = []} = result
  240.                 let lastViewedArr = []
  241.                 if(success && val.length) {
  242.                     if(!isM4LBM) {
  243.                         let lastViewed = $('script:last')
  244.                         if(lastViewed[0]) {
  245.                             let regex = /(?<=vm\.LastChapterRead\s=)(.*)(?=;)/g
  246.                             let match = lastViewed[0].innerText.match(regex)
  247.                             if(match.length) {
  248.                                 lastViewedArr = JSON.parse(match[0])
  249.                             }
  250.                         }
  251.                     }
  252.  
  253.                     for(let i = 0; i < val.length; i++) {
  254.                         let indexStr = '', readStatus = false
  255.                         let chapter = isM4LBM ? val[i].Chapter : '1'
  256.                         if(!isM4LBM) {
  257.                             for(let j = 0; j < lastViewedArr.length; j++){
  258.                                 if(lastViewedArr[j].SeriesID == val[i].SeriesID){
  259.                                     chapter = lastViewedArr[j].Chapter;
  260.                                 }
  261.                             }
  262.  
  263.                             let indexTest = chapter.substring(0, 1);
  264.                             if(indexTest > 0 && indexTest != 1){
  265.                                 indexStr = "-index-"+indexTest;
  266.                             }
  267.  
  268.                             if(val[i].ReadStatus == "1"){
  269.                                 readStatus = "Reading";
  270.                             } else if(val[i].ReadStatus == "2"){
  271.                                 readStatus = "Finished";
  272.                             } else if(val[i].ReadStatus == "3"){
  273.                                 readStatus = "On-hold";
  274.                             } else if(val[i].ReadStatus == "4"){
  275.                                 readStatus = "Dropped";
  276.                             } else if(val[i].ReadStatus == "5"){
  277.                                 readStatus = "Plan to read";
  278.                             }
  279.                         }
  280.  
  281.                         let chapterStr = parseInt(chapter.slice(1, -1)) || 1
  282.                         let page = val[i].Page == '0' ? 1 : `-page-${val[i].Page}`
  283.                         let link = `https://manga4life.com/read-online/${val[i].IndexName}-chapter-${chapterStr}${indexStr}${isM4LBM ? page : ''}.html`
  284.                         bookmarkedTitles += `${val[i].SeriesName} ${readStatus ?  `|| Status: ${readStatus}` : ''} || Viewed: ${chapterStr} ${url ? `- ${link}` : ''} \n`
  285.                     }
  286.                     saveFile(bookmarkedTitles)
  287.                 }
  288.             })
  289.             .catch(error => console.log('error', error));
  290.     }
  291.  
  292.     if($(`${exportContainer}`).length === 0){
  293.         $(`${btnContainer}`).append(`<div id='${exportContainer}'><button id='${exportButtonID}'>Export ${bmLabel}</button><input type="checkbox" id="${inclURL}"><span style="margin-left: 5px;"><label for="${inclURL}" class='${inclURL}'>Add URL</span></label></div>`)
  294.     }
  295.  
  296.     const getBookmarks = (url) => {
  297.         // main function generate file
  298.         deleteTemp()
  299.  
  300.         $('body').append("<div id='temp_data'>")
  301.         let pageSuccess = 0;
  302.         let bookmarkedTitles = bookmarkHeader
  303.  
  304.         for(let i = 0; i < pageCount; i++) {
  305.             $("#temp_data").append(`<div id='page${i+1}'>`)
  306.             $(`#page${i+1}`).load(`https://${domain}/bookmark?page=${i+1} ${bmTag}`, (resp,status,xhr) => {
  307.                 if(status == "success") { pageSuccess++ }
  308.                 if(pageSuccess == pageCount) {
  309.                     let bmItem = $(`#temp_data ${bmTag}`)
  310.                     for(let j = 0; j < bmItem.length; j++) {
  311.                         if($(bmItem[j]).find(`${bmTitle}`).text()) {
  312.                             let last_viewed = $(bmItem[j]).find(`${lastViewed}`),
  313.                             bookmarked_title = $(bmItem[j]).find(`${bmTitle}`);
  314.                             if(bookmarked_title.length > 0) {
  315.                                 bookmarkedTitles += $(bmItem[j]).find(`${bmTitle}`).text() + ` ||  Viewed: ${last_viewed.length > 0 ? last_viewed[0].text : 'Not Found' } ${url ? `- ${last_viewed[0].href}` : ''} \n`
  316.                             }
  317.                         }
  318.                     }
  319.  
  320.                     saveFile(bookmarkedTitles)
  321.                     deleteTemp()
  322.                 }
  323.             })
  324.         }
  325.     }
  326.  
  327.     $(`#${exportButtonID}`).on('click', async function() {
  328.         let bookmarkHeader = `===========================\n${domain} ${bmLabel}\n===========================\n`
  329.         bookmarkedTitles = bookmarkHeader
  330.         let inclURLCheck = $(`#${inclURL}`).is(':checked');
  331.  
  332.         if(domain == 'mangakakalot.com') {
  333.             $(this).html('Generating File...').prop('disabled', true)
  334.             getBookmarks(inclURLCheck)
  335.         } else if(domain == 'mangabat.com' || domain == 'h.mangabat.com') {
  336.             let userData = getCookie()
  337.             if(userData) {
  338.                 $(this).html('Generating File...').prop('disabled', true)
  339.                 let initBMFetch = await getBMs(userData)
  340.                 pageCount = initBMFetch.bm_page_total || 0
  341.                 if(pageCount > 0) {
  342.                     for(let i = 1; i <= pageCount; i++) {
  343.                         let currPage = await getBMs(userData, i)
  344.                         let currPageBMs = currPage.data
  345.                         for(let j = 0; j < currPageBMs.length; j++) {
  346.                             bookmarkedTitles += `${currPageBMs[j].note_story_name} || Viewed: ${currPageBMs[j].chapter_namenow} ${inclURLCheck ? `- ${currPageBMs[j].link_chapter_now}` : ''} \n`
  347.                         }
  348.                     }
  349.  
  350.                     saveFile(bookmarkedTitles)
  351.                 }
  352.             }
  353.         } else if (domain == 'mangakakalot.fun') {
  354.             getFunBMs(inclURLCheck)
  355.         } else if (domain == 'manga4life.com') {
  356.             getM4LBMs(inclURLCheck)
  357.         }
  358.     })
  359. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement