komigabor / NezzSorozatokat.info

// ==UserScript==
// @name         NezzSorozatokat.info
// @author       Komornik Gábor
// @updateURL    https://openuserjs.org/install/komigabor/NezzSorozatokat.info.user.js
// @downloadURL  https://openuserjs.org/install/komigabor/NezzSorozatokat.info.user.js
// @supportURL   https://openuserjs.org/scripts/komigabor/NezzSorozatokat.info/issues
// @version      1.3
// @description  Improve user experience on site
// @match        http://nezzsorozatokat.hu
// @match        http://nezzsorozatokat.hu/*
// @match        http://nezzsorozatokat.info
// @match        http://nezzsorozatokat.info/*
// @match        http://nezzsorozatokat.tk
// @match        http://nezzsorozatokat.tk/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_listValues
// @grant        GM_deleteValue
// @require      https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js
// @copyright    2013-2016, Komornik Gábor
// ==/UserScript==

// === CHANGE LOG ===

// 1.3
// - changed: babel no longer used (maybe in the future)
// - changed: jQuery updated to latest (google hosted)
// - fixed: crash when loading videos (due to page updated)
// - changed: only the first video shown automatically
// - feature: home link (at upper left)
// - feature: videos marked broken by the community goes to the bottom of the list

// 1.2
// - Fixed video auto opening

// 1.1 and before
// - undocumented

// === /CHANGE LOG ===

// parseUri 1.2.2
// (c) Steven Levithan <stevenlevithan.com>
// MIT License

// (Modified by Komornik Gábor)

function parseUri(str) {
    var o = parseUri.options,
        m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
        uri = {},
        i = 14;

    while (i--) {
        uri[o.key[i]] = m[i] || "";
    }uri[o.q.name] = {};
    uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
        if ($1) uri[o.q.name][$1] = $2;
    });

    return uri;
};

parseUri.options = {
    strictMode: false,
    key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"],
    q: {
        name: "queryKey",
        parser: /(?:^|&)([^&=]*)=?([^&]*)/g
    },
    parser: {
        strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
        loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
    }
};

// ============== END OF PARSE URI =====================

function _typeof(val, against) {
    var type = typeof val;
    if(against) {
        return type === against;
    }
    return type;
}

function runEval(code) {
    var tag = $("<script/>").attr("type", "text/javascript")
        .html( "// inserted by runEval function on " + (new Date()) 
            + "\neval(atob('" + btoa(code) + "'));" )
        .appendTo("body");
}

function img(src) {
    var i = new Image();i.src = src;return i;
}

var loading = img('data:image/gif;base64,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\nCwg1RAAAOwAAAAAAAAAAAA==');

// SCRIPT START!!!!
function truncate(text, length, more) {
    length = length || 80;
    more = more || '...';
    var len = text.length,
        lenmore = more.length;
    if (len <= length) return text;
    return text.substr(0, length - lenmore) + more;
}

function createClass(proto, statics) {
    var cls = function cls() {
        $.isFunction(this.initialize) && this.initialize.apply(this, arguments);
    };
    cls.prototype = proto;
    if (_typeof(statics, "object")) {
        $.extend(cls, statics);
    }
    return cls;
}

var Page = (function () {
    var url = parseUri("" + window.location);

    function pageType() {
        var s = url.queryKey['s'],
            e = url.queryKey['e'];
        if (!_typeof(e, "undefined") && !_typeof(s, "undefined")) {
            return 'e'; // epizód
        }
        if (!_typeof(s, "undefined")) {
            return 's'; // sorozat
        }
        return 'n'; // semmi
    }
    function isE() {
        return pageType() == 'e';
    }
    function isS() {
        return pageType() == 'e' || pageType() == 's';
    }

    function getSeriesId() {
        return isS() ? parseUri('' + window.location).queryKey['s'] : null;
    }

    function getSorozatCim() {
        return $.trim($('div#main > h1').text());
    }

    function _getEpDetailsRow() {
        if (!isS()) return null;
        return $('div#main > div:first tr')[1];
    }

    function getEpizodCim() {
        var node = _getEpDetailsRow();
        return node == null ? null : $.trim($('h2', node).text());
    }

    function getNeighbour(n_per_p) {
        var node = _getEpDetailsRow();
        if (!node) return null;
        var td = $('td:' + (n_per_p == 'previous' ? 'first' : 'last'), node);
        return {
            text: $.trim($('h3', td).text()),
            series: getSeriesId(),
            partId: parseUri($('a', td).attr('href')).queryKey['e']
        };
    }

    function listak() {
        return $('div[id^="lista_"]');
    }

    function clearHeader() {
        // remove social widgets
        // remove facebook like and google plus buttons
        $("h1#logo span:last").nextAll().remove();

        // clear the menu
        // categories are - more or less - useless
        // we can utilize this space better
        $('#header > ul').empty();

        // remove anoying ads
        $(".ctnet_adslot_wrapper").remove();

        // create a home button
        $("#logo").css('cursor', 'pointer')
            .click(function() { window.location = "/"; })
            .attr("title", "Kezdő oldal");
    }

    function clearEpHeader() {
        $('div#main > div:first tr:last').remove();
        // remove event handlers from episode headers
        // !attention: the page itself uses an older jquery (unbind)
        runEval("$('.doboz').unbind('click');");
        runEval("$(\"div[id^='lista']\").unbind('show');");
    }

    return {
        getCurrent: function getCurrent() {
            return {
                id: getSeriesId(),
                title: isS() ? getSorozatCim() : null
            };
        },
        getCurrentEp: function getCurrentEp() {
            return {
                next: getNeighbour('next'),
                previous: getNeighbour('previous'),

                text: getEpizodCim(),
                series: getSeriesId(),
                partId: parseUri('' + window.location).queryKey['e']

            };
        },
        isPart: isE,
        isSeries: isS,
        cleanUp: function cleanUp() {
            clearHeader();
            isE() && clearEpHeader();
            if (isS()) {
                $('ul', listak().show()).css('list-style-type', 'none');
            }
        },
        getLists: listak
    };
})();

var Video = createClass(
    {
        initialize: function initialize(initialnode, autoShow) {
            Video.instances.push(this);

            var that = this;
            this.node = $(initialnode);
            this.asText = null;
            this.htmlUpToDate = false;
            this.isVisible = autoShow;
            this.isAdvideo = false;
            this.isBroken = false;

            var vid = this.node.attr('id');
            if ( !/^lista_\d+$/.test(vid) ) {
                console.warn('mallformed video id: "' + vid + '"');
            }
            this.videoid = vid.substr(6);
            this.box = $('span.doboz[evad="' + this.videoid + '"]');
            this.box.click($.proxy(this, "boxClicked"));

            if ($('div.advideo[sorsz]', this.node).length > 0) {
                this.sorszam = $('div.advideo', this.node).attr('sorsz');
                this.isAdvideo = true;
            } else if(this.node.children('div[load-id]').length > 0) {
                this.sorszam = this.node.children('div').attr('load-id');
            } else if($(".hibasvideo", this.node).length > 0) {
                this.sorszam = $(".hibasvideo", this.node).attr('sorsz');
                this.isBroken = true;
            } else {
                console.warn('unknown case :(');
            }
            if (!this.sorszam) {
                throw '"sorszam" can not be determined';
            } else {
                console.log('sorszam found: ' + this.sorszam + " ( -> " + this.videoid + " )");
            }

            this.update();
            this.prefetch();
            console.log(this.name() + ': video initialized');
        },
        name: function() {
            return '[' + this.videoid + ' / ' + this.sorszam + ']';
        },
        hide: function() {
            if (this.isVisible) {
                console.log(this.name() + ': hide');
                this.isVisible = false;
                this.update();
            }
        },
        boxClicked: function() {
            if(!this.isVisible) {
                console.log(this.name() + ': video show');
                // hide all others
                var that = this;
                $.each(Video.instances, function(idx, inst) { if(inst !== that) inst.hide(); });

                // show this
                this.isVisible = true;
                this.update();
            }
        },
        update: function update( newHtmlContent ) {
            if(newHtmlContent) {
                console.log(this.name() + ': new content loaded');
                this.asText = newHtmlContent;
                this.htmlUpToDate = false;
            }
            this.node[this.isVisible ? "show" : "hide"]();
            this.box.css('cursor', this.isVisible ? "default" : "pointer");
            if(this.isBroken && !this.brokenLabel) {
                var last = $('div[id^="lista_"]:last');
                this.box.css('color', '#6F7951');
                this.box.html("[HIBÁS] " + this.box.html());
                this.node.detach().insertAfter(last);
                this.box.parent().detach().insertAfter(last);
                this.brokenLabel = true;
            }
            if(this.asText != null && !this.htmlUpToDate) {
                this.node.html(this.asText);
                this.htmlUpToDate = true;
            }

        },
        prefetch: function prefetch() {
            console.log(this.name() + ': download content');
            
            // if (!this.cache()) { 
            // console.log(' -> not in cache');
            var data = { id: this.sorszam };
            if(this.isAdvideo) data.ad = 1;
            this.fetch = $.get('/videobetolt.php', data, $.proxy(this, 'store'), 'text');
            // }

            this.fetch.done($.proxy(this, 'update'));
            this.fetch.fail($.proxy(this, 'report'));
        },
        cache: function cache() {
            var text = GM_getValue('video.' + this.sorszam, false);
            if (!text) return false;
            console.log(' -> in cache');
            var def = $.Deferred();
            this.fetch = def.promise();
            this.asText = JSON.parse(text);
            def.resolve(this.asText);
            return true;
        },
        report: function report() {
            console.warn('something crashed', arguments);
        },
        store: function store(text) {
            this.asText = text;
            var json = JSON.stringify(text);
            GM_setValue('video.cachesize', GM_getValue('video.cachesize', 0) + json.length);
            GM_setValue('video.' + this.sorszam, json);
        },
        toggle: function toggle() {
            console.log('box clicked' + this.videoid + '/' + this.sorszam);

        },
        nowloading: function nowloading() {
            console.log('loading: ' + this.videoid + '/' + this.sorszam);
            var img = $('<img/>').attr('src', loading.src);
            var div = $('<div/>').attr('style', 'margin:20px 15px 0; padding:5px; width:94%; display: inline-table;').addClass('advideo').append(img);
            this.node.empty().append(div);
            img.on('load', $.proxy(img, 'center'));
        }
    
    }, {

        instances: [],

        clearCache: function () {
            $.each(GM_listValues(), function (n, key) {
                if (key.substr(0, 6) == 'video.') {
                    GM_deleteValue(key);
                }
            });
            console.log('Cache cleared');
        },

        printDbSize: function () {
            console.log('Currently using ' + GM_getValue('video.cachesize', 0) + ' bytes for cache');
        }

    });

var Bookmarks = createClass({
    gmkey: 'bookmarks',
    initialize: function initialize() {
        var that = this;
        this.bookmarks = [];
        var bms = GM_getValue(this.gmkey, false);
        this.plus = this._registerItem2Dom({
            text: '+',
            command: $.proxy(this, 'addThis')
        });
        if (bms) {
            $.each(JSON.parse(bms), function (k, item) {
                that.add(item);
            });
        }
        if (Page.isPart()) {
            var item = this.getItemFor(Page.getCurrent().id);
            if (item) {
                item.lastviewed = Page.getCurrentEp().partId;
                this.save();
            }
        }
    },
    getItemFor: function getItemFor(id) {
        return $.grep(this.bookmarks, function (item) {
            return item.id === id;
        })[0];
    },
    addThis: function addThis() {
        var id = Page.getCurrent().id;
        if (id === null) return alert('Ezt az oldalt nem tudod könyvjelzőnek beállítani');
        if ('object' == _typeof(this.getItemFor(id))) return;
        this.add({
            text: Page.getCurrent().title,
            id: id
        });
        this.save();
    },
    save: function save() {
        var exp = [];
        $.each(this.bookmarks, function (k, bookmark) {
            exp.push({
                id: bookmark.id,
                text: bookmark.text,
                lastviewed: bookmark.lastviewed || null
            });
        });
        GM_setValue(this.gmkey, JSON.stringify(exp));
    },
    add: function add(item) {
        var id = this.bookmarks.length;
        this.bookmarks[id] = item;
        item.current = Page.getCurrent().id === item.id;
        item.command = $.proxy(this, 'open', item);
        item.tasks = { 'x': $.proxy(this, 'remove', item) };
        this._registerItem2Dom(item);
        return item;
    },
    remove: function remove(item) {
        var index = this.bookmarks.indexOf(item);
        this._removeItemFromDom(item);
        if (index > -1) {
            this.bookmarks.splice(index, 1);
        }
        // console.log(item, index, this.bookmarks);
        this.save();
    },
    open: function open(item, event) {
        var s, e, cs, ce, item;
        s = item.id;
        cs = Page.getCurrent().id;
        e = item.lastviewed || null;
        ce = Page.getCurrentEp().partId;
        // console.log('requested: ' + s + '/' + e + '\ncurrent: ' + cs + '/' + ce);
        if (s == cs && e == ce) return; // ott vagyunk ahol lennünk kell
        var url = '/?s=' + s;
        if (e) url += '&e=' + e;
        window.location.assign(url);
    },
    _getItem: function _getItem(id) {
        return this.bookmarks[id] || null;
    },
    _registerItem2Dom: function _registerItem2Dom(item) {
        var ul = $('#header > ul'),
            element = $('<li></li>');
        element.append($('<a></a>').attr('href', 'javascript:void(0)').append($('<span/>').text(truncate(item.text, 20))).click(item.command));
        if (item.tasks) {
            var span = function span() {
                return $('<span/>').css('display', 'inline').css('background', 'transparent').css('padding', '0');
            };
            var toggleUnderline = function toggleUnderline(e) {
                $(this).css('text-decoration', e.type == 'mouseenter' ? 'underline' : 'none');
            };
            var d = document,
                t = 'createTextNode',
                tasks = span().css('margin-left', '2px'),
                bracelet = [d[t]('('), d[t](')')],
                comma = d[t](','),
                run = 0;
            tasks.append(bracelet[0]);
            $.each(item.tasks, function (label, task) {
                if (run++ != 0) {
                    tasks.append(comma);
                }
                span().text(label).click(task).appendTo(tasks).on('mouseenter', toggleUnderline).on('mouseleave', toggleUnderline);
            });
            tasks.append(bracelet[1]);
            $('span', element).append(tasks);
        }
        if (item.current) {
            element.attr('id', 'current');
        }
        ul.prepend(element);
        item.element = element;
        return item;
    },
    _removeItemFromDom: function _removeItemFromDom(item) {
        if (item.element && item.element.remove) {
            item.element.remove();
            delete item.element;
        }
        return item;
    }
});

// ENTRY
$(window).on('load', function () {
    setTimeout(function () {
        Page.cleanUp();
        window.bm = new Bookmarks();
        if (Page.isPart()) {
            var isFirst = true;
            Page.getLists().each(function (k, node) {
                var video = new Video(node, isFirst);
                if (video.isBroken) {
                    video.hide();
                } else {
                    isFirst = false;
                }
            });
        }
    }, 10);
});
// CLEAR
$(window).keypress(function (e) {
    // ctrl + tab
    if (e.ctrlKey && !e.altKey && !e.shiftKey && e.which == 9) {
        Video.clearCache();
    }
    if (e.ctrlKey && e.altKey && !e.shiftKey && e.which == 205) {
        Video.printDbSize();
    }
});