Mananelo/Mangakakalot/Manganato/Manga4life Bookmarks Export

Writes Mangakakalot, Manganelo, Manganato, Manga4life Bookmarks (name and visited number) to "manga_bookmarks.txt" on "Export Bookmarks" button click

目前為 2022-09-10 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Mananelo/Mangakakalot/Manganato/Manga4life Bookmarks Export
// @namespace    http://smoondev.com/
// @version      2.20
// @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://manganato.com/bookmark*
// @match        https://manga4life.com/user/bookmark.php
// @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
// ==/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, bookmarkHeader = `===========================\n${domain} Bookmarks\n===========================\n`

    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'
    }

    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 Bookmarks').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'
        };

        fetch("https://manga4life.com/user/bookmark.get.php", requestOptions)
            .then(response => response.json())
            .then(result => {
                let {success = false, val = []} = result
                if(success && val.length) {
                    for(let i = 0; i < val.length; i++) {
                        let chapter = parseInt(val[i].Chapter.slice(1, -1))
                        let page = val[i].Page == 0 ? '' : `-page-${val[i].Page}`
                        let link = `https://manga4life.com/read-online/${val[i].IndexName}-chapter-${chapter}${page}.html`
                        bookmarkedTitles += `${val[i].SeriesName} || Viewed: ${chapter} ${url ? `- ${link}` : ''} \n`
                    }
                    saveFile(bookmarkedTitles)
                }
            })
            .catch(error => console.log('error', error));
    }

    if($(`${exportContainer}`).length === 0){
    	$(`${btnContainer}`).append(`<div id='${exportContainer}'><button id='${exportButtonID}'>Export Bookmarks</button><input type="checkbox" id="${inclURL}"><span style="margin-left: 5px;"><label for="${inclURL}" class='${inclURL}'>Add URL</span></label></div>`)
    }

    const getBookmarks = (url) => {
        // main function generate file
        deleteTemp()

        $('body').append("<div id='temp_data'>")
        let pageSuccess = 0;
        let bookmarkedTitles = bookmarkHeader

        for(let i = 0; i < pageCount; i++) {
            $("#temp_data").append(`<div id='page${i+1}'>`)
            $(`#page${i+1}`).load(`https://${domain}/bookmark?page=${i+1} ${bmTag}`, (resp,status,xhr) => {
                if(status == "success") { pageSuccess++ }
                if(pageSuccess == pageCount) {
                    let bmItem = $(`#temp_data ${bmTag}`)
                    for(let j = 0; j < bmItem.length; j++) {
                        if($(bmItem[j]).find(`${bmTitle}`).text()) {
                            let last_viewed = $(bmItem[j]).find(`${lastViewed}`),
                            bookmarked_title = $(bmItem[j]).find(`${bmTitle}`);
                            if(bookmarked_title.length > 0) {
                                bookmarkedTitles += $(bmItem[j]).find(`${bmTitle}`).text() + ` ||  Viewed: ${last_viewed.length > 0 ? last_viewed[0].text : 'Not Found' } ${url ? `- ${last_viewed[0].href}` : ''} \n`
                            }
                        }
                    }

                    saveFile(bookmarkedTitles)
                    deleteTemp()
                }
            })
        }
    }

    $(`#${exportButtonID}`).on('click', async function() {
        bookmarkedTitles = bookmarkHeader
        let inclURLCheck = $(`#${inclURL}`).is(':checked');

        if(domain == 'mangakakalot.com') {
            $(this).html('Generating File...').prop('disabled', true)
            getBookmarks(inclURLCheck)
        } else if(domain == 'manganato.com' || domain == 'm.manganelo.com') {
            let userData = getCookie()
            if(userData) {
                $(this).html('Generating File...').prop('disabled', true)
                let initBMFetch = await getBMs(userData)
                pageCount = initBMFetch.bm_page_total || 0
                if(pageCount > 0) {
                    for(let i = 1; i <= pageCount; i++) {
                        let currPage = await getBMs(userData, i)
                        let currPageBMs = currPage.data
                        for(let j = 0; j < currPageBMs.length; j++) {
                            bookmarkedTitles += `${currPageBMs[j].note_story_name} || Viewed: ${currPageBMs[j].chapter_namenow} ${inclURLCheck ? `- ${currPageBMs[j].link_chapter_now}` : ''} \n`
                        }
                    }

                    saveFile(bookmarkedTitles)
                }
            }
        } else if (domain == 'mangakakalot.fun') {
            getFunBMs(inclURLCheck)
        } else if (domain == 'manga4life.com') {
            getM4LBMs(inclURLCheck)
        }
    })
})();