// ==UserScript== // @name Mananelo/Mangakakalot/Manganato/Manga4life Bookmarks Export // @namespace http://smoondev.com/ // @version 2.30 // @description Writes Mangakakalot, Manganelo, Manganato Bookmarks (name and visited number) to "manga_bookmarks.txt" on "Export Bookmarks" button click // @author Shawn Moon // @match https://*.mangakakalot.gg/bookmark* // @match https://*.nelomanga.com/bookmark* // @match https://*.natomanga.com/bookmark* // @match https://*.manganato.gg/bookmark* // @match https://mangakakalot.fun/user/bookmarks // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js // @downloadURL none // ==/UserScript== (function () { 'use strict' function addBookarkStyles(css) { const head = document.head || document.getElementsByTagName('head')[0] if (!head) return const 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-flex; vertical-align: bottom; align-items: baseline; margin-top: 20px; text-align: right; float: right; margin-right: 20px; } #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; } `) let pageI, bmTag, bmTitle, lastViewed, btnContainer, exportButtonID, inclURL, bookmarkedTitles = '', exportContainer, pageCount = 0, domain = window.location.hostname, tld = domain.replace('www.', ''), bmLabel = 'Bookmarks' let mangagakalotDomains = [ 'mangakakalot.gg', 'nelomanga.com', 'natomanga.com', 'manganato.gg' ] if (mangagakalotDomains.includes(tld)) { pageI = '.group-page a' bmTag = '.user-bookmark-item-right' bmTitle = '.bm-title' lastViewed = 'span:nth-of-type(2) a' btnContainer = '.breadcrumbs p' inclURL = 'inclURL_kakalot' let pageElList = document.querySelectorAll(pageI) if (pageElList.length > 0) { let lastText = pageElList[pageElList.length - 1].textContent pageCount = parseInt(lastText.replace(/\D+/g, ''), 10) || 0 } exportButtonID = 'export_kakalot' exportContainer = 'export_container_kakalot' } else if (domain.indexOf('mangakakalot.fun') !== -1) { bmTag = '.list-group-item' bmTitle = '.media-heading a' lastViewed = '.media-body p a' btnContainer = '.container-fluid:first-child div:last-child' inclURL = 'inclURL_fun' exportButtonID = 'export_fun' exportContainer = 'export_container_fun' } const waitFor = delay => new Promise(resolve => setTimeout(resolve, delay)) const saveFile = saveData => { const fileData = new Blob([saveData], { type: 'application/octet-stream' }) saveAs(fileData, 'manga_bookmarks.txt') const btn = document.getElementById(exportButtonID) if (btn) { btn.innerHTML = `Export ${bmLabel}` btn.disabled = false } } const deleteTemp = () => { const tempData = document.getElementById('temp_data') if (tempData) { tempData.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) => { const urlencoded = new URLSearchParams() urlencoded.append('out_type', 'json') urlencoded.append('bm_source', 'manganato') urlencoded.append('bm_page', currentPage) urlencoded.append('user_data', userCookie) try { const response = await fetch('https://user.mngusr.com/bookmark_get_list_full', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: urlencoded, redirect: 'follow' }) return await response.json() } catch (error) { console.log('ExportError', error) } } const getFunBMs = url => { const bmItems = document.querySelectorAll(bmTag) for (let i = 0; i < bmItems.length; i++) { const titleElem = bmItems[i].querySelector(bmTitle) const title = titleElem ? titleElem.textContent : '' const lastViewedElem = bmItems[i].querySelector('.media-body p a') const lastViewedText = lastViewedElem ? lastViewedElem.textContent.trim() : 'None' const linkText = (url && lastViewedElem && lastViewedElem.href) ? `- ${lastViewedElem.href}` : '' bookmarkedTitles += `${title} || Viewed: ${lastViewedText} ${linkText} \n` } saveFile(bookmarkedTitles) } if (!document.getElementById(exportContainer)) { const btnContElem = document.querySelector(btnContainer) if (btnContElem) { btnContElem.insertAdjacentHTML( 'beforeend', `