AnimeWorld Scrobbling

Segna automaticamente gli episodi visualizzati su Trakt.TV

目前為 2020-07-24 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         AnimeWorld Scrobbling
// @namespace    https://www.pizidavi.altervista.org/
// @description  Segna automaticamente gli episodi visualizzati su Trakt.TV
// @author       pizidavi
// @version      1.4.0
// @copyright    2020, PIZIDAVI
// @license      MIT
// @homepageURL  https://www.pizidavi.altervista.org/AnimeWoldScrobbling/
// @require      https://greasyfork.org/scripts/401626-notify-library/code/Notify%20Library.js
// @include      https://*.animeworld.*/play/*

// @connect      https://api.trakt.tv/
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_xmlhttpRequest

// ==/UserScript==

(function($) {
    'use strict';

    // USER INFO
    const CLIENT_ID = '';
    const ACCESS_TOKEN = '';
    const EXPIRES = '';

    // SETTINGS
    const SHOW_HELPER = true;
    const AUTO_NEXT_EPISODE = false;


    /* ----------- CODE ----------- */
    const css = '#body .sidebar { float: right; width: 300px; position: relative; z-index: 1; }';
    const template = '<div id="trakt" class="sidebar"><div class="widget"><div class="widget-title"><div class="title">Trakt</div></div><div class="widget-body"><div class="row" style="margin-bottom:1em;"><div class="col-sm-10" style=" padding-right: 0; "><button class="btn btn-primary btn-block" id="watched">Episodio Visto</button></div><div class="col-sm-2"><input type="checkbox" id="autoNext" style="margin-top: 8px;" title="Prossimo episodio automatico"></div></div><div class="row"><div class="col-sm-6" style=" padding-right: 0; "><input type="text" class="form-control" placeholder="Trakt Slug"><small id="helper" style="display:none;margin:0.3em 0px -5px 0.5em;"><a href="https://www.pizidavi.altervista.org/AnimeWoldScrobbling/#trakt" target="_blank" style="color:grey;">Dove lo trovo?</a></small></div><div class="col-sm-2" style=" padding-right: 0; "><input type="number" class="form-control" value="1" min="0" placeholder="Season"></div><div class="col-sm-4"><button class="btn btn-success btn-block">Salva</button></div></div></div></div></div>';

    const AnimeID = getAnimeID();
    var Trakt = GM_getValue(AnimeID, {});
    var section = $(template);

    GM_addStyle(css);
    $('#body #body-container').append(section);

    if(!CLIENT_ID || !ACCESS_TOKEN || !EXPIRES) {
        section.find('div.widget-body').html('Dati Trakt mancanti. Segui la <a href="https://www.pizidavi.altervista.org/AnimeWoldScrobbling/" target="_blank">guida</a>');
        return; }
    if(new Date() >= new Date(EXPIRES)) {
        section.find('div.widget-body').html('Access Token Trakt Scaduto. <a href="https://www.pizidavi.altervista.org/AnimeWoldScrobbling/#login" target="_blank">Aggiorna</a>');
        return; }
    if(AnimeID == undefined) {
        section.find('div.widget-body').html('Errore. AnimeID non trovato');
        return; }

    section.find('input[type="text"]').val(Trakt.slug);
    section.find('input[type="number"]').val((Trakt.season || '1'));
    if(AUTO_NEXT_EPISODE)
        section.find('input[type="checkbox"]').attr('checked', '');
    if(SHOW_HELPER)
        section.find('#helper').css('display', 'block');

    section.find('button.btn:not(#watched)').on('click', function() {
        var title = $('#main div.widget.info div.info > div.head h2').text();
        var slug = $(this).parent().parent().find('input[type="text"]').val();
        var season = $(this).parent().parent().find('input[type="number"]').val();

        if(slug != '' && season != '') {
            Trakt.title = title.trim();
            Trakt.slug = slug.trim();
            Trakt.season = season;
            GM_setValue(AnimeID, Trakt);

            section.find('button#watched').removeAttr('disabled');

            new Notify({
                text: 'Dati salvati',
                type: 'success'
            }).show();
        } else {
            new Notify({
                text: 'Completa tutti i campi',
                type: 'warn'
            }).show();
        }
    });

    console.log(Trakt);
    if(Trakt.slug == undefined || Trakt.season == undefined) {
        console.log('no')
        section.find('button#watched').attr('disabled', ''); }
    $('button#watched').on('click', function() {
        var _this = $(this);
        var episode = $('div.server ul a.active').attr('data-base');
        if(Trakt.slug == undefined || Trakt.season == undefined || episode == undefined) {
            new Notify({
                text: 'Errore',
                type: 'error'
            }).show();
            return;
        }
        _this.attr('disabled', '');

        var joData = {
            'shows': [
                {
                    'ids': {
                        'slug': Trakt.slug,
                    },
                    'seasons': [
                        {
                            'number': parseInt(Trakt.season),
                            'episodes': [
                                {
                                    'watched_at': new Date().toJSON(),
                                    'number': parseFloat(episode)
                                }
                            ]
                        }
                    ]
                }
            ]
        };
        request(joData, function(data) {
            if(data.added.episodes > 0) {
                new Notify({
                    text: 'Episodio '+episode+' salvato',
                    type: 'success'
                }).show();

                if(AUTO_NEXT_EPISODE || section.find('#autoNext').prop('checked'))
                    $('#controls > div.prevnext[data-value="next"]').click();
            } else {
                new Notify({
                    text: 'Errore. Episodio non trovato',
                    type: 'error'
                }).show();
            }
            _this.removeAttr('disabled');
        });
    });
    $(document).on('click', '#controls > div.userbookmark > ul > li:nth-child(2), #controls > div.userbookmark > ul > li:nth-child(7)', function() {
        var deleted = deleteOne(AnimeID);
        if(deleted) {
            section.find('input[type="text"]').val('');
            section.find('input[type="number"]').val('1');
            section.find('button#watched').attr('disabled', '');
            Trakt = {};

            new Notify({
                text: 'Dati Trakt rimossi',
                type: 'success'
            }).show();
        }
    });


    // Functions
    function request(data, success) {
        var r = new XMLHttpRequest();
        r.open('POST', 'https://api.trakt.tv/sync/history');

        r.setRequestHeader('Content-Type', 'application/json');
        r.setRequestHeader('Authorization', 'Bearer '+ACCESS_TOKEN);
        r.setRequestHeader('trakt-api-version', '2');
        r.setRequestHeader('trakt-api-key', CLIENT_ID);

        r.onreadystatechange = function () {
            if (this.readyState === 4 && (this.status == 200 || this.status == 201)) {
                success(JSON.parse(this.responseText));
            } else if (this.readyState === 4) {
                new Notify({
                    text: 'Errore nella richiesta. Ricarica la pagina',
                    type: 'error'
                }).show();
            }
        };
        r.send(JSON.stringify(data));
    }

    function getAnimeID() {
        var url = location.pathname;
        var start = url.indexOf('.')+1;
        var end = start + (url.substring(start).indexOf('/') >= 0 ? url.substring(start).indexOf('/') : url.substring(start).length);
        return url.substring(start, end) || undefined;
    }

    function deleteOne(key) {
        if(GM_listValues().includes(key)) {
            GM_deleteValue(key);
            return true;
        } else {
            return false;
        }
    }
    function deleteAll() {
        GM_listValues().forEach(function(key) {
            GM_deleteValue(key);
        });
        return true;
    }

})(jQuery);