// ==UserScript== // @name Mananelo/Mangakakalot/Manganato/Manga4life Bookmarks Export // @namespace http://smoondev.com/ // @version 2.26 // @description Writes Mangakakalot, Manganelo, Manganato, Manga4life Bookmarks (name and visited number) to "manga_bookmarks.txt" on "Export Bookmarks" button click // @author Shawn Moon // @match https://mangakakalot.com/bookmark* // @match https://*.manganelo.com/bookmark* // @match https://manga4life.com/user/bookmark.php // @match https://manga4life.com/user/subscription.php // @match https://manganato.com/bookmark* // @match https://mangakakalot.fun/user/bookmarks // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js // @downloadURL none // ==/UserScript== function addBookarkStyles(css) { var head, style; head = document.getElementsByTagName('head')[0]; if (!head) { return; } style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); } addBookarkStyles(` #export_container_nato, #export_container_kakalot, #export_container_m4l { color: #000; cursor: pointer; float: right; } #export_container_fun { display: inline-block; vertical-align: bottom; } #export_container_kakalot { margin-right: 10px; } #export_nato:hover, #export_kakalot:hover, #export_m4l:hover { background-color: #b6e4e3; color: #000; cursor: pointer; } #export_nato, #export_kakalot, #export_m4l { border-radius: 5px; text-decoration: none; color: #fff; background-color: #76cdcb; border: none; font-weight: 600; } #export_nato, #export_kakalot { padding: 4px 8px; } #export_m4l { padding: 1px 12px; font-size: 16.5px; } #export_fun { color: #f05759; background-color: #fff; border: 1px solid #f05759; display: inline-block; margin-bottom: 0; font-weight: 400; text-align: center; touch-action: manipulation; cursor: pointer; white-space: nowrap; padding: 6px 12px; border-radius: 0; user-select: none; transition: all .2s ease-in-out; } #export_fun:hover { color: #fff; background-color: #f05759; } #inclURL_nato, #inclURL_kakalot, #inclURL_fun, #inclURL_m4l { margin-left: 10px; } .inclURL_kakalot, .inclURL_m4l { color: #ffffff; } .inclURL_m4l { color: #ffffff; font-size: 15px; font-weight: 500; } .inclURL_fun { font-weight:normal; } #temp_data { position: absolute; top: -9999px; left: -9999px; } `); (async function() { 'use strict'; let pageI, bmTag, bmTitle, lastViewed, btnContainer, exportButtonID, inclURL, bookmarkedTitles = '', exportContainer, pageCount = 0, domain = window.location.hostname, bmLabel = 'Bookmarks' if(domain == 'mangakakalot.com') { pageI = '.group_page a' bmTag = '.bookmark_item' bmTitle = '.bookmark_title' lastViewed = '.bookmark_chap a' btnContainer = '.breadcrumbs p' inclURL = 'inclURL_kakalot' pageCount = parseInt($(`${pageI}`).last().text().replace(/\D+/g, '')) exportButtonID = 'export_kakalot' exportContainer = 'export_container_kakalot' } else if(domain == 'manganato.com' || domain == 'm.manganelo.com') { btnContainer = '.panel-breadcrumb' inclURL = 'inclURL_nato' exportButtonID = 'export_nato' exportContainer = 'export_container_nato' } else if (domain == 'mangakakalot.fun') { bmTag = '.list-group-item' bmTitle = '.media-heading a' lastViewed = '.media-body p a' btnContainer = '.container-fluid:first div:last' inclURL = 'inclURL_fun' exportButtonID = 'export_fun' exportContainer = 'export_container_fun' } else if (domain == 'manga4life.com') { inclURL = 'inclURL_m4l' exportButtonID = 'export_m4l' btnContainer = '.BoxHeader' exportContainer = 'export_container_m4l' if(!window.location.pathname.includes('bookmark.php')) { bmLabel = 'Subscriptions' } } const waitFor = delay => new Promise(resolve => setTimeout(resolve, delay)); const saveFile = saveData => { // save file const fileData = new Blob([saveData], {type:"application/octet-stream"}) saveAs(fileData, "manga_bookmarks.txt") $(`#${exportButtonID}`).html(`Export ${bmLabel}`).prop('disabled', false) } const deleteTemp = () => { // delete temp container $('#temp_data').remove() } const getCookie = (name = 'user_acc') => { let returnVal = false const value = `; ${document.cookie}` try { const parts = value.split(`; ${name}=`) if (parts.length === 2) { let user = parts.pop().split(';').shift() if(name == 'user_acc') { user = JSON.parse(decodeURIComponent(user)) returnVal = user.user_data } } } catch (e) { returnVal = false } return returnVal } const getBMs = async (userCookie, currentPage = 1) => { var myHeaders = new Headers(); myHeaders.append("Content-Type", "application/x-www-form-urlencoded"); var urlencoded = new URLSearchParams(); urlencoded.append("out_type", "json"); urlencoded.append("bm_source", "manganato"); urlencoded.append("bm_page", currentPage); urlencoded.append("user_data", userCookie); var requestOptions = { method: 'POST', headers: myHeaders, body: urlencoded, redirect: 'follow' }; let bmArray = [] return await fetch("https://user.mngusr.com/bookmark_get_list_full", requestOptions) .then(response => response.json()) .then(result => result) .catch(error => console.log('ExportError', error)); } const getFunBMs = (url) => { let bmItems = $(`${bmTag}`) for(let i = 0; i < bmItems.length; i++) { let title = $(bmItems[i]).find(bmTitle)[0]?.text || false let lastViewed = $(bmItems[i]).find('.media-body p a')[0] || false bookmarkedTitles += `${title} || Viewed: ${lastViewed ? lastViewed.text : 'None'} ${url ? (lastViewed ? `- ${lastViewed.href}` : '') : ''} \n` } saveFile(bookmarkedTitles) } const getM4LBMs = (url) => { var myHeaders = new Headers(); let userCookie = document.cookie myHeaders.append("cookie", userCookie); var urlencoded = new URLSearchParams(); var requestOptions = { method: 'POST', headers: myHeaders, body: urlencoded, redirect: 'follow' }; let isM4LBM = window.location.pathname.includes('bookmark.php') fetch(`https://manga4life.com/user/${isM4LBM ? 'bookmark.get.php' : 'subscription.get.php'}`, requestOptions) .then(response => response.json()) .then(result => { let {success = false, val = []} = result let lastViewedArr = [] if(success && val.length) { if(!isM4LBM) { let lastViewed = $('script:last') if(lastViewed[0]) { let regex = /(?<=vm\.LastChapterRead\s=)(.*)(?=;)/g let match = lastViewed[0].innerText.match(regex) if(match.length) { lastViewedArr = JSON.parse(match[0]) } } } for(let i = 0; i < val.length; i++) { let indexStr = '', readStatus = false let chapter = isM4LBM ? val[i].Chapter : '1' if(!isM4LBM) { for(let j = 0; j < lastViewedArr.length; j++){ if(lastViewedArr[j].SeriesID == val[i].SeriesID){ chapter = lastViewedArr[j].Chapter; } } let indexTest = chapter.substring(0, 1); if(indexTest > 0 && indexTest != 1){ indexStr = "-index-"+indexTest; } if(val[i].ReadStatus == "1"){ readStatus = "Reading"; } else if(val[i].ReadStatus == "2"){ readStatus = "Finished"; } else if(val[i].ReadStatus == "3"){ readStatus = "On-hold"; } else if(val[i].ReadStatus == "4"){ readStatus = "Dropped"; } else if(val[i].ReadStatus == "5"){ readStatus = "Plan to read"; } } let chapterStr = parseInt(chapter.slice(1, -1)) || 1 let page = val[i].Page == '0' ? 1 : `-page-${val[i].Page}` let link = `https://manga4life.com/read-online/${val[i].IndexName}-chapter-${chapterStr}${indexStr}${isM4LBM ? page : ''}.html` bookmarkedTitles += `${val[i].SeriesName} ${readStatus ? `|| Status: ${readStatus}` : ''} || Viewed: ${chapterStr} ${url ? `- ${link}` : ''} \n` } saveFile(bookmarkedTitles) } }) .catch(error => console.log('error', error)); } if($(`${exportContainer}`).length === 0){ $(`${btnContainer}`).append(`