Greasy Fork

Greasy Fork is available in English.

DMZJ Subscriber 动漫之家订阅助手

提供动漫之家漫画的订阅批量导入导出功能

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name          DMZJ Subscriber 动漫之家订阅助手
// @namespace     https://github.com/DriverHub/dmzj-assistant
// @version       0.1.3
// @description   提供动漫之家漫画的订阅批量导入导出功能
// @match         http://i.dmzj.com/*
// @match         http://manhua.dmzj.com/*
// @copyright     2016, DriverHub
// @author        UnluckyNinja, pa001024

// @grant         unsafeWindow
// @grant         GM_xmlhttpRequest
// @connect       self
// @connect       user.dmzj.com
// @connect       s.acg.178.com
// ==/UserScript==

// userscript for https://chrome.google.com/webstore/detail/dhdgffkkebhmkfjojejmpbldmpobfkfo
(function($, window) {
    // loadCSS start
    var styleRes = function() {
        /*
            #da_import_button, .dy_content_li{cursor: pointer;}
            .da_button{width: 400px; display:block; float:right;}
            div.popup {
                padding: 6px;
                position: relative;
                margin-top: 5px;
                left: calc(-50px);
                display: block;
                background-color: white;
                color: black;
                width: 200px;
                height: 100px;
                border: 1px solid #e6e6e6;
            }
            div.popup.import {
                left: -120px;
                height: 135px;
            }
            div.popup.import i.popup {
                right: 33px;
            }
            textarea.popup {
                display: block;
                width: 100%;
                height: 100px;
                color: black;
                font-size: small;
                overflow: hidden;
            }
            i.popup {
                position: absolute;
                display: inline-block;
                width: initial;
                height: initial;
                margin: 0;
                border: 10px solid;
                top: -20px;
                right: calc(100px - 10px);
                border-color: transparent;
                border-bottom-color: #e6e6e6;
            }
            #da_import_button {
                margin-right: 6px;
                padding-left: 4px;
                float: right;
                background: url(img/border.gif) no-repeat scroll -283px -46px;
                color: #fd3600;
                height: 20px;
                margin: 0 1px 0 0;
                padding: 3px 0 0 3px;
            }
            #import_button {
                position:relative;
                width: 50px;
                height: 30px;
                margin: 5px 0 0 0;
                float: left;
                left: calc(50% - 25px);
                font-size: small;
            }
            
        */
    };
    var myCSS = $("#ad_style");
    if (!myCSS.length)
        myCSS = $("<style id='ad_style'>").insertAfter($(document.body).find(":last"));
    var stylestr = styleRes.toString().replace(/^[\s\S]*?\/\*\s*|\s*\*\/[\s\S]*?$/g, "");
    myCSS.html(stylestr);
    // loadCSS end

    window.DmzjAssistant = {
        version: '0.1.3',
        auto_expand_enable: true,
        teleport_enable: false,
        choosing_enable: false,
        is_loading: false,
        cur_page: 1,
        uid: 0,
        over_subscribed: false,
        itemOnClick: function(event) {
            var item = $(event.currentTarget);
            item.find('div.dy_img').toggleClass("comic_chosen");
            item.toggleClass("on_choosing");
            item.hasClass('on_choosing') ? item.fadeTo('fast', 1) : item.fadeTo('fast', 0.3);
        },

        hideNonChosenItem: function(event) {
            var all_item = $('div.dy_content_li');
            all_item.not('.on_choosing').fadeTo('slow', 0.3);
        },

        subscribeAll: function(obj, callback) {
            this.over_subscribed = false;
            var self = this;
            if (!self.uid) {
                return;
            }
            console.log('dmzj助手 - 开始批量订阅漫画');
            var count = Object.keys(obj).length;
            var success_count = 0;
            var fail_count = 0;
            var finished = 0;
            var failed = {};
            $.each(obj, function(comic_id, v) {
                self.subscribe(self.uid, comic_id, v, function(comic_id, subscribe_status) {
                    finished += 1;
                    callback(comic_id, subscribe_status);
                    if (subscribe_status === 0) {
                        fail_count += 1;
                        failed[comic_id] = v;
                        console.log(`dmzj助手 - 漫画 ${v.name} 订阅失败 (${success_count}:${fail_count}/${finished})`);
                    }
                    else if (subscribe_status === 1) {
                        success_count += 1;
                        console.log(`dmzj助手 - 漫画 ${v.name} 订阅成功 (${success_count}:${fail_count}/${finished})`);
                    }
                    else if (subscribe_status === 2) {
                        fail_count += 1;
                        failed[comic_id] = v;
                        if (!self.over_subscribed) {
                            self.over_subscribed = true;
                            console.log(`dmzj助手 - 漫画 ${v.name} 无法订阅,超出订阅数量限制 (${success_count}:${fail_count}/${finished})`);
                        }
                    }
                    else if (subscribe_status === 3) {
                        success_count += 1;
                        console.log(`dmzj助手 - 漫画 ${v.name} 已经订阅 (${success_count}:${fail_count}/${finished})`);
                    }
                    if (finished == count) {
                        var text = `dmzj助手 - 批量订阅完成,${success_count} 成功 ${fail_count} 失败`;
                        if (Object.keys(failed).length == 0) {
                            alert(text);
                        }
                        else {
                            alert(text+'\n订阅失败的部分请在浏览器控制台窗口复制,重新尝试批量订阅');
                            console.log(JSON.stringify(failed));
                        }
                    }
                    else {
                        console.log(`dmzj助手 - 订阅进度 ${success_count}:${fail_count} / No. ${finished} / Total ${count}`);
                    }
                });
            });
        },

        subscribe: function(uid, comic_id, value, callback) {
            if (this.over_subscribed) {
                callback(comic_id, 2);
                return;
            }
            var self = this;
            var proxy_url = "http://s.acg.178.com/sns/comic_test.php?jsonpcallback=?";
            console.log('dmzj助手 - 正在订阅漫画 ' + value.name);
            // 避免跨域错误
            GM_xmlhttpRequest({
                url: 'http://user.dmzj.com/subscribe/sure/' + uid + '/mh/' + comic_id,
                method: 'GET',
                headers: {
                    'Referer': location.href
                },
                // overrideMimeType: 'text/plain',
                onerror: function(response) {
                    self.over_subscribed = true;
                    callback(comic_id, 0);
                    console.log('dmzj助手 - 请求异常,终止订阅');
                },
                onload: function(response) {
                    // 订阅查询
                    var string = response.responseText;
                    var match = string.match(/\((.)\)/);
                    if (match && match.length == 2 && match[1] == 1) {
                        callback(comic_id, 3);
                        return;
                    }
                    else if (!match || match.length != 2) {
                        console.log('dmzj助手 - 订阅漫画' + value.name + '时服务器返回数据异常');
                        callback(comic_id, 0);
                        return;
                    }
                    var dataobj = {
                        'operation': 'subscribe',
                        'comic_id': comic_id,
                        'uid': uid
                    };
                    // 真正订阅,jsonp
                    $.getJSON(proxy_url, dataobj, function(jsondata) {
                        callback(comic_id, jsondata.subscribe_status);
                    }).fail(function(jsondata) {
                        self.over_subscribed = true;
                        console.log('dmzj助手 - 请求异常,终止订阅');
                        callback(comic_id, 0);
                    });
                }
            });
        },

        subscribeFetch: function(data, callback, fail) {
            var url = "/ajax/my/subscribe";
            /* data 格式
            var data = {
                page: 2,
                type_id: "2", //1国漫2日漫3动画4轻小说,页面标签
                letter_id: "0", //首字母,0 ALL
                read_id: "1" //1全部更新,2未读更新
            };
            */
            $.post(url, data, function(text, status, jqxhr) {
                callback(text);
                console.log('dmzj助手 - 成功获取第' + data.page + '页订阅列表');
            }).fail(fail);
        },

        subscribeLoad: function(event) {
            var self = this;
            var pagefoot = $('#page_id');
            var should_load = function() {
                return self.isElementInViewport(pagefoot);
            };
            // 避免重复加载
            if (this.auto_expand_enable && should_load() && !self.is_loading) {
                self.is_loading = true;
                var type_id = $('.optioned').attr('value');
                var letter_id = $('.cur').attr('value');
                var read_id = $('.oped').attr('value');
                var data = {
                    'page': self.cur_page + 1,
                    'type_id': type_id,
                    'letter_id': letter_id,
                    'read_id': read_id
                };

                self.subscribeFetch(data, function(text) {
                    //初始检测
                    var target = $('#my_subscribe_id_' + self.cur_page);
                    if (target.length < 1) {
                        target = $('#my_subscribe_id');
                    }
                    // 添加内容
                    var newList = $(text);
                    self.cur_page += 1;
                    var container = $(`<div class="dy_content autoHeight" id="my_subscribe_id_${self.cur_page}" style="border-top-width: 1px; border-top-style: solid; border-top-color: rgb(230, 230, 230);"></div>`);
                    container.insertAfter(target).append(newList);
                    $('#my_subscribe_id_' + self.cur_page).append(newList);

                    // 动画效果与事件响应
                    if (self.choosing_enable) {
                        self.hideNonChosenItem();
                        $('#my_subscribe_id_' + self.cur_page + ' div.dy_content_li').click(function(event) {
                            self.itemOnClick(event);
                        });
                    }
                    else {
                        $('#my_subscribe_id_' + self.cur_page + ' div.dy_content_li').click(function(event) {
                            self.choosing_enable = true;
                            var item = $(event.currentTarget);
                            item.find('div.dy_img').toggleClass("comic_chosen");
                            item.addClass('on_choosing');

                            self.hideNonChosenItem(event);

                            $('div.dy_content_li').off('click').click(function(event) {
                                self.itemOnClick(event);
                            });
                        });
                    }
                    self.is_loading = false;
                }, function() {
                    self.is_loading = false;
                });

            }

        },
        // source: http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport/7557433#7557433
        isElementInViewport: function(element) {

            //special bonus for those using jQuery
            if (typeof jQuery === "function" && element instanceof jQuery) {
                element = element[0];
            }

            var rect = element.getBoundingClientRect();

            return (
                rect.top >= 0 &&
                rect.left >= 0 &&
                rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
                rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
            );
        },

        exportSubscribe: function() {
            var self = this;
            var result = {};
            if (self.choosing_enable) {
                $('.on_choosing .dy_r').each(function(index, element) {

                    var info = $(element).find('h3 a');
                    var name = info.text();
                    var url = info.attr('href').trim();
                    var id = $(element).find('a.qx').attr('value');
                    result[id] = {
                        'name': name,
                        'url': url
                    };
                });
            }
            return JSON.stringify(result);
        },

        importSubscribe: function(text) {
            var self = this;
            var obj = {};
            try {
                obj = JSON.parse(text);
                var all_clear = true;
                $.each(obj, function(k, v) {
                    if(k.match(/^\d+$/).length < 1){
                        all_clear = false;
                    }
                });
                if(!all_clear || Object.keys(obj).length == 0){
                    alert("JSON数据有误,请检查分享代码格式!");
                    return;
                }
            }
            catch (e) {
                console.log(e);
                alert("解析JSON发生异常,请检查分享代码格式!");
            }
            self.subscribeAll(obj, function(id, jsondata) {
                    // nothing to do
            });
        },
        popupTextArea: function(element, content, select) {
            var popup = $(`<div class="popup"><i class="popup"></i><textarea id="popup_text" class="popup">${content}</textarea></div>`)
                .insertAfter(element);
            if (select) {
                popup.find('textarea').focus().select();
            }
            return popup;
        }
    };

    var _da = window._da = window.DmzjAssistant;

    function enable_subscribe() {
        // 好像然并卵
        /*$('div.dy_content_li').on("load change", function() {
            if (_da.choosing_enable) {
                _da.hideNonChosenItem();
            }
        });*/
        // 触发自动续屏,一颗赛艇
        $(window).scroll(function(event) {
            _da.subscribeLoad(event);
        });

        // 添加一键导出按钮
        var origin = $('.sub_potion').css('display', 'inline-block');
        var new_tab = $('<ul class="sub_potion da_button">' +
            '<li><a href="javascript:;" id="clear_choose" class="sub_potion_li sub_type_id" value="1">清除选择</a></li>' +
            '<li><a href="javascript:;" id="expand_off" class="sub_potion_li sub_type_id" value="1">关闭滚动</a></li>' +
            '<li><a href="javascript:;" id="da_export" class="sub_potion_li sub_type_id" value="1">导出订阅</a></li>' +
            '<li><a href="javascript:;" id="da_import" class="sub_potion_li sub_type_id" value="1">批量订阅</a></li>' +
            '</ul>').insertAfter(origin);
        new_tab.find('#clear_choose').click(function(event) {
            if (_da.choosing_enable) {
                _da.choosing_enable = false;
                $('.on_choosing').removeClass('on_choosing');
                // the same as above one
                $('div.dy_content_li').off('click').click(function(event) {
                    _da.choosing_enable = true;
                    var item = $(event.currentTarget);
                    item.find('div.dy_img').toggleClass("comic_chosen");
                    item.addClass('on_choosing');

                    _da.hideNonChosenItem(event);

                    $('div.dy_content_li').off('click').click(function(event) {
                        _da.itemOnClick(event);
                    });
                });
                $('div.dy_content_li').fadeTo('slow', 1.0);
            }
        });
        new_tab.find('#expand_off').click(function(event) {
            if (_da.auto_expand_enable) {
                _da.auto_expand_enable = false;
                $(event.target).text('开启滚动');
            }
            else {
                _da.auto_expand_enable = true;
                $(event.target).text('关闭滚动');
            }
        });
        // 导出按钮
        new_tab.find('#da_export').click(function(event) {
            if (_da.choosing_enable) {
                var popup = _da.popupTextArea(event.currentTarget, _da.exportSubscribe(), true);
                popup.find('textarea').attr('readonly', true);
                popup.focusout(function(event) {
                    $(event.currentTarget).remove();
                });
            }
            else {
                alert('请先选择漫画!');
            }
        });
        // 导入按钮
        new_tab.find('#da_import').click(function(event) {
            if($('div.popup.import').length > 0 ){
                return;
            }
            var popup = _da.popupTextArea(event.currentTarget, '{}', false);
            popup.addClass('import');
            popup.mouseleave(function(event) {
                $('div.popup.import').remove();
            });
            $('<button id="import_button">提交</button>').appendTo(popup).click(function(event) {
                _da.importSubscribe($('#popup_text').val());
                popup.remove();
            });
        });
        // 首次点击隐藏其余元素
        $('.dy_content_li').ready(function(event) {
            $('.dy_content_li').click(function(event) {
                _da.choosing_enable = true;
                var item = $(event.currentTarget);
                item.find('.dy_img').toggleClass("comic_chosen");
                item.addClass('on_choosing');

                _da.hideNonChosenItem(event);

                $('.dy_content_li').off('click').click(function(event) {
                    _da.itemOnClick(event);
                });
            });
        });
    }

    function popupText(name, content) {
        var base = "data:text/html;charset=utf-8,";
        return open(base + content, name, 'height=300,width=1000');
    }

    function enable_import() {
        var button = $('<li class="history_tab s-nav3" id="da_import_button" target_div="subscribe_panel">' +
            '<span id="subscribe_tab">订阅导入</span></li>');
        $('li[target_div]').eq(0).after(button);
        button.click(function(event) {
            // _da.importOnClick(event); // 删掉了
        });
    }

    function enable_import2() {
        var button = $('<span class="update"><a href="javascript:;">订阅导入</a></span>');
        $('.anim_title_text').eq(0).after(button);
        button.click(function(event) {
            // _da.importOnClick(event);
        });
    }
    /*global Cookies*/

    function dmzj_init() {
        console.log('dmzj助手 - 正在启动');
        console.log('dmzj助手 - 判断用户登陆情况');

        // get UID
        if (window.userId) {
            var uid = window.userId;
        }
        else {
            var datas = Cookies.get('my');
            if (datas != null && datas != '') {
                var t = datas.split('|');
                uid = t[0];
            }
            else {
                uid = 0;
            }
        }

        if (uid) {
            console.log('dmzj助手 - 用户已登录,UID为' + uid);
        }
        else {
            console.log('dmzj助手 - 用户未登录,请先登录');
        }

        if (uid) {
            _da.uid = uid;
            /* //before 4/28 OLD
            var mh_found = $('#mh');
            var mh_clicked = $('#mh2');
            if (mh_found.length > 0 || mh_clicked.length > 0) {
                enable_subscribe();
            }*/
            var mh_found = $('#yc1.optioned');
            if (mh_found.length > 0) {
                enable_subscribe();
            }
            else {
                /*
                if (location.hostname == 'manhua.dmzj.com') {
                    if (location.pathname == '/') {
                        // enable_import();
                    }
                    else {
                        // enable_import2();
                    }
                }
                // enable_teleport();*/
            }
            console.log('dmzj助手 - 启动完成');
            console.log('dmzj助手 - v' + _da.version + ' repo: https://github.com/DriverHub/dmzj-assistant author: UnluckyNinja, pa001024');
        }
    }

    /*! js-cookie v2.1.0 | MIT */
    ! function(a) {
        if ("function" == typeof define && define.amd) define(a);
        else if ("object" == typeof exports) module.exports = a();
        else {
            var b = window.Cookies,
                c = window.Cookies = a();
            c.noConflict = function() {
                return window.Cookies = b, c
            }
        }
    }(function() {
        function a() {
            for (var a = 0, b = {}; a < arguments.length; a++) {
                var c = arguments[a];
                for (var d in c) b[d] = c[d]
            }
            return b
        }

        function b(c) {
            function d(b, e, f) {
                var g;
                if (arguments.length > 1) {
                    if (f = a({
                            path: "/"
                        }, d.defaults, f), "number" == typeof f.expires) {
                        var h = new Date;
                        h.setMilliseconds(h.getMilliseconds() + 864e5 * f.expires), f.expires = h
                    }
                    try {
                        g = JSON.stringify(e), /^[\{\[]/.test(g) && (e = g)
                    }
                    catch (i) {}
                    return e = c.write ? c.write(e, b) : encodeURIComponent(String(e)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent), b = encodeURIComponent(String(b)), b = b.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent), b = b.replace(/[\(\)]/g, escape), document.cookie = [b, "=", e, f.expires && "; expires=" + f.expires.toUTCString(), f.path && "; path=" + f.path, f.domain && "; domain=" + f.domain, f.secure ? "; secure" : ""].join("")
                }
                b || (g = {});
                for (var j = document.cookie ? document.cookie.split("; ") : [], k = /(%[0-9A-Z]{2})+/g, l = 0; l < j.length; l++) {
                    var m = j[l].split("="),
                        n = m[0].replace(k, decodeURIComponent),
                        o = m.slice(1).join("=");
                    '"' === o.charAt(0) && (o = o.slice(1, -1));
                    try {
                        if (o = c.read ? c.read(o, n) : c(o, n) || o.replace(k, decodeURIComponent), this.json) try {
                            o = JSON.parse(o)
                        }
                        catch (i) {}
                        if (b === n) {
                            g = o;
                            break
                        }
                        b || (g[n] = o)
                    }
                    catch (i) {}
                }
                return g
            }
            return d.get = d.set = d, d.getJSON = function() {
                return d.apply({
                    json: !0
                }, [].slice.call(arguments))
            }, d.defaults = {}, d.remove = function(b, c) {
                d(b, "", a(c, {
                    expires: -1
                }))
            }, d.withConverter = b, d
        }
        return b(function() {})
    });


    $('body').ready(dmzj_init);

}).call(unsafeWindow || window, (unsafeWindow || window).$, unsafeWindow || window);