您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
提供动漫之家漫画的订阅批量导入导出功能
// ==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);