AnimeWorld Scrobbling

Segna automaticamente gli episodi visualizzati su Trakt.TV

当前为 2020-07-24 提交的版本,查看 最新版本

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

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

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

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

您需要先安装一款用户脚本管理器扩展,例如 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);