nautiljon-total-time

Dans le bloc-notes et les collections, calcule la durée totale de la liste des animes et dramas sélectionnés ainsi que la durée totale par série. Calcule également la durée totale des séries sur leur fiche.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name             nautiljon-total-time
// @namespace        http://tampermonkey.net/
// @version          0.6.4
// @description      Dans le bloc-notes et les collections, calcule la durée totale de la liste des animes et dramas sélectionnés ainsi que la durée totale par série. Calcule également la durée totale des séries sur leur fiche.
// @author           Ed38
// @license          MIT
// @match            https://www.nautiljon.com/membre/a-voir,*,anime.html*
// @match            https://www.nautiljon.com/membre/a-voir,*,drama.html*
// @match            https://www.nautiljon.com/membre/possede,*,anime.html*
// @match            https://www.nautiljon.com/membre/possede,*,drama.html*
// @match            https://www.nautiljon.com/membre/vu,*,anime.html*
// @match            https://www.nautiljon.com/membre/vu,*,drama.html*
// @match            https://www.nautiljon.com/animes/*
// @match            https://www.nautiljon.com/dramas/*
// @icon             https://www.google.com/s2/favicons?sz=64&domain=nautiljon.com
// @grant            GM_addStyle
// @noframes
// ==/UserScript==

(function() {
    'use strict';
    const testListURL = /^https:\/\/www.nautiljon.com\/membre\/(a-voir|possede|vu),.*/ ;
    const episodeTypeLabel = [] ;
    episodeTypeLabel["a-voir"] = "Épisodes à voir : " ;
    episodeTypeLabel["possede"] = "Épisodes possédés : " ;
    let episodeType ;
    let searchTypingState = false ;
    let counterLock = false ;
    let infoSheetLock = false ;
    let collectionNode ;

    let urlMatch = document.location.href.match(testListURL) ;
    if (urlMatch) {
        episodeType = urlMatch[1] ;
        if (episodeType === "vu") {
            // Nauti'liste
            reformatNautiliste() ;
        }
        else
        {
            // Bloc-notes & Collection
            document.querySelector("input[data-id='listingListe']").addEventListener("keyup", searchTyping, false);
            totalTimeCounter();
        }
    }
    else {
        // Info sheet
        collectionNode = document.querySelector('#collection_anime') ;
        if (!collectionNode) {
            collectionNode = document.querySelector('#collection_drama') ;
        }
        if (collectionNode) {

            collectionNode.addEventListener("click", watchedChange, false);
        }
        infoSheetDuration() ;
    }

    function watchedChange() {
        setTimeout(infoSheetDuration, 300);
    }

    function searchTyping(){
        searchTypingState = true ;
        totalTimeCounter() ;
    }

    function infoSheetDuration(){
        let hours = 0 ;
        let minutes = 0 ;
        let numberOfEpisodesSpan = document.querySelector('span[itemprop = "numberOfEpisodes"]')
        let numberOfEpisodes = numberOfEpisodesSpan.textContent ;
        if(numberOfEpisodes > 1){
            let durationText = numberOfEpisodesSpan.nextSibling.textContent.replace(/\s+/g, '') ;
            // hours & minutes
            let hoursMatch = durationText.match(/(\d+)h/) ;
            if (hoursMatch) {
                hours = ~~hoursMatch[1] ;
                let minutesMatch = durationText.match(/h(\d+)/) ;
                if (minutesMatch) {
                    minutes = ~~minutesMatch[1] ;
                }
            }
            else {
                let minutesMatch = durationText.match(/(\d+)min/) ;
                if (minutesMatch) {
                    minutes = ~~minutesMatch[1] ;
                }
            }

            let epDuration = (hours * 60 + minutes) ;
            let totalDuration = numberOfEpisodes * epDuration ;
            let itemHours = Math.trunc(totalDuration / 60) ;
            let itemMinutes = totalDuration % 60 ;

            let totalDurationSpan = document.querySelector('#totalDuration') ;
            if (!totalDurationSpan) {
                totalDurationSpan = document.createElement("span") ;
                totalDurationSpan.classList.add("infos_small") ;
                totalDurationSpan.id = "totalDuration" ;
                numberOfEpisodesSpan.parentNode.appendChild(totalDurationSpan) ;
            }

            totalDurationSpan.innerHTML=' (' + itemHours + ' h ' + itemMinutes.toString().padStart(2,"0") + ' min)' ;

            // Watched / to watch durations
            if (collectionNode) {
                let watched = collectionNode.querySelector('span[id^="ep_"]') ;
                let watchedEp = ~~watched.innerHTML ;
                let toWatchEp = ~~numberOfEpisodes - watchedEp ;

                if (toWatchEp != 0 && watchedEp != 0) {
                    let watchedTime = watchedEp * epDuration ;
                    let watchedHours = Math.trunc(watchedTime / 60) ;
                    let watchedMinutes = watchedTime % 60 ;
                    let toWatchTime = toWatchEp * epDuration ;
                    let toWatchHours = Math.trunc(toWatchTime / 60) ;
                    let toWatchMinutes = toWatchTime % 60 ;
                    let watchedDetailsText = " Déjà&nbsp;vu&nbsp;:&nbsp;<strong>" + watchedHours + "&nbsp;h&nbsp;" + watchedMinutes + "&nbsp;min</strong>. À&nbsp;voir&nbsp;:&nbsp;<strong>" + toWatchHours + "&nbsp;h&nbsp;" + toWatchMinutes + "&nbsp;min</strong>." ;
                    let elDetails = document.querySelector('#watchedDetails');

                    if (!elDetails) {
                        elDetails = document.createElement("span") ;
                        elDetails.id = "watchedDetails" ;
                        elDetails.style.marginLeft = "1em" ;
                        collectionNode.querySelector("div").appendChild(elDetails) ;
                    }
                    elDetails.innerHTML = watchedDetailsText ;
                }
                else {
                    if (collectionNode.querySelector('#watchedDetails')){
                        collectionNode.querySelector('#watchedDetails').innerHTML = "" ;
                    }
                }
            }
        }
    }

    function totalTimeCounter() {
        if (counterLock === true) {
            return ;
        }
        counterLock = true ;
        GM_addStyle('@media (min-width:1025px) {.total-time::before {content:"\\A"; white-space: pre;}}') ;
        let durationLabel = "Temps total : " ;
        let episodesLabel = episodeTypeLabel[episodeType] ;
        let counter = 0 ;
        let episodesCounter = 0 ;
        let durationNode ;
        let durationText ;
        let itemTotal = 0 ;
        let itemHours = 0 ;
        let itemMinutes = 0 ;
        let durationsNode = document.getElementsByClassName("t_progression") ;

        for (let i = 0 ; i < durationsNode.length; i++) {
            itemLoop: {
                let numberOfEpisodes = 0 ;
                let hours = 0 ;
                let minutes = 0 ;
                if (durationsNode[i].checkVisibility()) {
                    durationNode = durationsNode[i] ;
                    durationText = durationsNode[i].textContent;
                    durationText = durationText.replace(/\s+/g, '') ; // remove whitespaces
                    let test=durationText;
                    durationText = durationText.replace(/\(.*\)$/, '') ; // remove existing result

                    // Skip if unknow data
                    if (durationText.match(/\?/)){
                        break itemLoop ;
                    }

                    // Number of episodes
                    let episodesMatch = durationText.match(/(\d+)[x×].*/) ;
                    if (episodesMatch) {
                        numberOfEpisodes = episodesMatch[1] ;
                    }
                    else {
                        numberOfEpisodes = 1 ;
                    }

                    // hours & minutes
                    let hoursMatch = durationText.match(/(\d+)h/) ;
                    if (hoursMatch) {
                        hours = hoursMatch[1] ;
                        let minutesMatch = durationText.match(/h(\d+)/) ;
                        if (minutesMatch) {
                            minutes = minutesMatch[1] ;
                        }
                    }
                    else {
                        let minutesMatch = durationText.match(/(\d+)min/) ;
                        if (minutesMatch) {
                            minutes = minutesMatch[1] ;
                        }
                    }
                }

                itemTotal = ~~numberOfEpisodes * (~~hours * 60 + ~~minutes) ;
                counter = counter + itemTotal ;

                if (numberOfEpisodes > 1){
                    itemHours = Math.trunc(itemTotal / 60) ;
                    itemMinutes = itemTotal % 60 ;
                    let itemTotalText = '(' + itemHours.toLocaleString() + ' h ' + itemMinutes.toString().padStart(2,"0") + ' min)' ;
                    let itemTotalDisplay = durationsNode[i].querySelector('[data-id="itemTotalDuration"]') ;
                    if (itemTotalDisplay) {
                        itemTotalDisplay.innerHTML=itemTotalText ;
                    }
                    else {
                        durationsNode[i].insertAdjacentHTML('beforeend', ' <span class="infos_small total-time" data-id="itemTotalDuration">' + itemTotalText + '</span>') ;
                    }
                }

                episodesCounter = ~~episodesCounter + ~~numberOfEpisodes ;

            }
        }

        let counterHours = Math.trunc(counter / 60) ;
        let counterMinutes = counter % 60 ;
        let totalDurationText = episodesLabel + "<strong>" + episodesCounter.toLocaleString() + "</strong>. " + durationLabel + "<strong>" + counterHours.toLocaleString() + " h " + counterMinutes.toString().padStart(2,"0") + " min</strong>";
        let totalDisplay = document.querySelector('[data-id="totalDuration"]') ;
        if (totalDisplay) {
            totalDisplay.innerHTML = totalDurationText ;
        }
        else {
            let statsStatut = document.getElementsByClassName("stats_statut") ;
            let counterDiv = document.createElement("div") ;
            counterDiv.setAttribute("class","stats_prix") ;
            counterDiv.dataset.id="totalDuration" ;
            counterDiv.innerHTML = totalDurationText ;
            statsStatut[0].parentNode.insertBefore(counterDiv,statsStatut[0]) ;
        }
        counterLock = false ;
        if (searchTypingState === true) {
            searchTypingState = false ;
            totalTimeCounter() ;
        }
    }

    function reformatNautiliste() {
        let totalEpisodesDisplay = document.getElementsByClassName("stats_prix")[0].querySelector("strong:nth-child(1)") ;
        let totalDurationDisplay = document.getElementsByClassName("stats_prix")[0].querySelector("strong:nth-child(2)") ;

        let totalEpisodes = ~~totalEpisodesDisplay.innerHTML ;
        totalEpisodesDisplay.innerHTML = totalEpisodes.toLocaleString() ;

        let totalDurationText = totalDurationDisplay.innerHTML ;
        let days = 0 ;
        let hours = 0 ;
        let minutes = 0 ;

        let daysMatch = totalDurationText.match(/(\d+) jour.*/)
        if (daysMatch) {
            days = daysMatch[1] ;
        }
        let hoursMatch = totalDurationText.match(/(\d+) heure.*/)
        if (hoursMatch) {
            hours = hoursMatch[1] ;
        }
        let minutesMatch = totalDurationText.match(/(\d+) minute.*/)
        if (minutesMatch) {
            minutes = minutesMatch[1] ;
        }

        let newTotalDurationText = (~~days * 24 + ~~hours).toLocaleString() + " h " + minutes.toLocaleString() + " min" ;

        totalDurationDisplay.innerHTML = newTotalDurationText ;
    }

})();