您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
tracking more than 50 subjects on bangumi index page
// ==UserScript== // @name bangumi tracking improvement // @namespace BTI.chaucerling.bangumi // @version 0.4.2 // @description tracking more than 50 subjects on bangumi index page // @author chaucerling // @include http://bangumi.tv/ // @include https://bgm.tv/ // @include http://bgm.tv/ // @include http://chii.in/ // @grant none // ==/UserScript== /* jshint loopfunc:true */ /* jshint esversion:6 */ // var $ = unsafeWindow.jQuery; // use to access 'chiiLib.home' and '$.cluetip' var origin_tv_queue = []; // max size 50 var origin_book_queue = []; // max size 50 var extra_tv_queue = []; var extra_book_queue = []; var watching_subjects = {}; var extra_watching_subjects = {}; var animes_size = 0, reals_size = 0, books_size = 0; var auto_refresh = false; // 进入首页自动刷新extra项目进度 var watching_list = []; var refresh = false; var progress_changed = false; var subjects_size = 0; const LS_SCOPE = 'BTI.extra_subjects'; // const DB_SCOPE = 'BTI'; // const DB_VERSION = '1'; // indexedDB // In the following line, you should include the prefixes of implementations you want to test. // window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; // // DON'T use "var indexedDB = ..." if you're not in a function. // // Moreover, you may need references to some window.IDB* objects: // window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"}; // This line should only be needed if it is needed to support the object's constants for older browsers // window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange; // // (Mozilla has never prefixed these objects, so we don't need window.mozIDB*) // var db; // var request = window.indexedDB.open(DB_SCOPE, DB_VERSION); // request.onerror = function(event) { // console.log("access IndexedDB fail"); // }; // request.onsuccess = function(event) { // db = event.target.result; // }; // request.onupgradeneeded = function(event){ // db = event.target.result; // if(!db.objectStoreNames.contains("subjects")){ // db.createObjectStore("subjects", {keyPath:"subject_id"}); // } // }; // var transaction = db.transaction("subjects", "readwrite"); function GM_addStyle(style) { $('head').append(`<style>${style}</style>`); } GM_addStyle(` #ti-alert { display:none; font-size: 14px; text-align: center; padding: 5px; background-color: #fcf8e3; } #ti-pages.categoryTab { padding: 5px; } #ti-pages.categoryTab a.focus { color: #FFF; background: #F09199; } #ti-pages.categoryTab a.refresh-btn, #ti-pages.categoryTab a.clear-btn { color: #FFF; background: #4EB1D4; } #ti-pages.categoryTab a.refresh-btn.disabled, #ti-pages.categoryTab a.clear-btn.disabled { cursor: not-allowed; opacity: 0.6 } #ti-pages.categoryTab a { display: inline-block; box-sizing: border-box; min-width: 50px; padding: 3px 10px; color: #555; font-size: 13px; text-align: center; border-radius: 15px; background: #F0F0F0; } .infoWrapper_tv.disabled, .infoWrapper_book.disabled { opacity: 0.5; pointer-events: none; } `); function Subject() { var info = arguments[0]; this.id = info.id; this.title = info.title; this.progress = info.progress; this.prg_list_html = info.prg_list_html; this.prg_content_html = info.prg_content_html; this.thumb = info.thumb; this.extra = info.extra; //boolean this.type = info.type; // 1: book, 2: amine, 6: real } function remove_img_src(str) { return str.replace(/<img src=\S+/ig, "<img src=''"); } function get_display_subject_type() { return $("#prgCatrgoryFilter > li > a.focus").atrr('subject_type'); } function change_mode() { $('#switchNormalManager').removeClass(); $('#switchNormalManager').hide(); $('#switchTinyManager').addClass('active'); $('.cloumnSubjects').hide(); $('#cloumnSubjectInfo .infoWrapper').removeClass('blockMode', 'info_hidden').addClass('tinyMode'); $('#cloumnSubjectInfo').css('width', '100%'); $('#prgManagerMain').css('height', 'auto').removeClass('blockModeWrapper').addClass('tinyModeWrapper'); $.cookie('prg_display_mode', 'tiny', { expires: 2592000 }); $('#ti-pages').show(); } function recover_mode() { // $('#prgCatrgoryFilter a').show(); $('#switchNormalManager').show(); $('.infoWrapper_tv > div').show(); $('#ti-pages').hide(); } function get_path_and_size_of_all_type() { animes_size = -1; reals_size = -1; books_size = -1; return [{ value: 2, path: $("#navMenuNeue > li:nth-child(1) > ul > li > a.nav")[5].getAttribute('href'), size: function() { return animes_size; }, set_size: function(value) { animes_size = value; } }, { value: 6, path: $("#navMenuNeue > li:nth-child(5) > ul > li > a.nav")[5].getAttribute('href'), size: function() { return reals_size; }, set_size: function(value) { reals_size = value; } }, { value: 1, path: $("#navMenuNeue > li:nth-child(2) > ul > li > a.nav")[4].getAttribute('href'), size: function() { return books_size; }, set_size: function(value) { books_size = value; } } ]; } function in_origin_queue(subject_id){ return origin_tv_queue.indexOf(subject_id) >= 0 || origin_book_queue.indexOf(subject_id) >= 0; } // 解析在看第一页的数据,获取在看数目和条目html function get_watching_list() { watching_list = []; subjects_size = 0; watching_subjects = {}; extra_tv_queue = []; extra_book_queue = []; console.log('getting first page of all type'); get_path_and_size_of_all_type().forEach(function(type, index, array) { $.get(type.path + "?page=1", function(data) { var html = remove_img_src(data); type.set_size(parseInt($(html).find('.navSubTabs a.focus').text().match(/\d+/) || 0)); console.log(`subjects_list: ${type.value}, size: ${type.size()}`); var max_page = parseInt(type.size() / 24) + 1; var _temp_list = $(html).find('#browserItemList > li').attr('item_type', type.value); watching_list = $.merge(watching_list, _temp_list); for (var i = 2; i <= max_page; i++) { parse_watching_page(type.path + "?page=" + i, type.value); } }); }); } function parse_watching_page(url, type) { $.get(url, function(data) { var html = remove_img_src(data); var _temp_list = $(html).find('#browserItemList > li').attr('item_type', type); watching_list = $.merge(watching_list, _temp_list); check_get_all_pages_finished(); }); } // 检查解析所有类型的在看条目列表页是否已完成 function check_get_all_pages_finished() { if (typeof this.counter1 === "undefined") this.counter1 = 0; this.counter1++; if (animes_size === -1 || reals_size === -1 || books_size === -1 || this.counter1 < parseInt(animes_size / 24) + parseInt(reals_size / 24) + parseInt(books_size / 24)) { console.log(`current_processing_watching_list_size: ${watching_list.length}`); return false; } this.counter1 = 0; subjects_size = watching_list.length; console.log('gettting all pages finished'); console.log(`watching_list_size: ${watching_list.length}`); if (animes_size + reals_size > 50 || books_size > 50) { $('#ti-alert').show(); $('#ti-alert').text(`Watching ${animes_size} animes, ${reals_size} reals and ${books_size} books, loading extra subjects' progress.(click to close)`); change_mode(); $.each(watching_list, function(index, element) { get_subject_progress($(element).attr('id').split("_")[1], parseInt($(element).attr('item_type'))); }); } else { recover_mode(); $('#ti-alert').show(); $('#ti-alert').text(`Watching ${animes_size} animes, ${reals_size} reals and ${books_size} books.(click to close)`); } } function get_subject_progress(subject_id, type) { // 在50列表里,不用去详情页抓取进度 if (in_origin_queue(subject_id)) { // 解析首页html var prg_list_html, prg_content_html; var html = $(`#subjectPanel_${subject_id}`); var title = $(html).find('.tinyCover').attr('title'); if (type !== 1) { prg_list_html = $(html).find('.prg_list').html(); prg_content_html = null; } else { prg_list_html = $(html).find('.epGird .prgText').map(function(index, element) { return element.outerHTML; }).toArray().join('\n'); prg_content_html = null; } var thumb = ($(html).find('.tinyCover .grid').attr('src') || ''); var subject = new Subject({ id: subject_id, title: title, prg_list_html: prg_list_html, prg_content_html: prg_content_html, thumb: thumb, type: type, extra: false }); watching_subjects[subject_id] = subject; check_get_all_extra_subjects_finished(); return; } if (type === 1) { extra_book_queue.push(subject_id); } else { extra_tv_queue.push(subject_id); } $.get('/subject/' + subject_id, function(data) { var prg_list_html, prg_content_html; var html = remove_img_src(data); var progress = $(html).find('#watchedeps').text().split("/")[0]; var title = $(html).find('.nameSingle > a').text(); if (type !== 1) { prg_list_html = $(html).find('.prg_list').addClass("clearit").html() || ''; prg_content_html = $(html).find('#subject_prg_content').html() || ''; } else { prg_list_html = $(html).find('.prgText').map(function(index, element) { $(element).append('<a href="javascript:void(0)" class="input_plus plus">+</a>'); return element.outerHTML; }).toArray().join('\n'); prg_content_html = null; } var thumb = ($(html).find('a.thickbox.cover').attr('href') || '').replace('/l/', '/g/'); var subject = new Subject({ id: subject_id, title: title, progress: progress, prg_list_html: prg_list_html, prg_content_html: prg_content_html, thumb: thumb, type: type, extra: true }); watching_subjects[subject_id] = subject; check_get_all_extra_subjects_finished(); }); } // 检查解析所有类型的额外的在看条目详情页是否已完成 function check_get_all_extra_subjects_finished() { if (typeof this.counter2 === "undefined") this.counter2 = 0; this.counter2++; if (this.counter2 < subjects_size) { return false; } this.counter2 = 0; add_extra_subjects(); localStorage[LS_SCOPE] = JSON.stringify({ watching_subjects: watching_subjects, extra_book_queue: extra_book_queue, extra_tv_queue: extra_tv_queue, animes_size: animes_size, reals_size: reals_size, books_size: books_size, auto_refresh: auto_refresh }); } function add_extra_subjects() { for (var i = 0; i < extra_book_queue.length; i++) { create_subject_cell(extra_book_queue[i]); } for (var j = 0; j < extra_tv_queue.length; j++) { create_subject_cell(extra_tv_queue[j]); } $('.infoWrapper_tv a.load-epinfo').cluetip({ local: true, dropShadow: false, cursor: 'pointer', sticky: true, closePosition: 'title', arrows: true, closeText: 'X', mouseOutClose: true, positionBy: 'fixed', topOffset: 30, leftOffset: 0, cluezIndex: 79 }); // chiiLib.home.init(); // chiiLib.home.prg(); // chiiLib.home.prgToolTip('#columnHomeA', 25); tb_init('a.thickbox, area.thickbox, input.thickbox'); $('#subject_prg_content a.ep_status').off('click').on('click', function() { chiiLib.home.epStatusClick(this); return false; }); $('form.prgBatchManagerForm').off('submit').on('submit', function() { chiiLib.home.prgBatchManager($(this)); return false; }); $('.prgBatchManagerForm a.input_plus').off('click').on('click', function(e) { var input = $(this).closest('div.prgText').find('input'), count = parseInt(input.val()), form = $(this).closest('form.prgBatchManagerForm'); $(input).val(count + 1); form.submit(); }); if (localStorage[LS_SCOPE] === undefined) { $('#ti-alert').show(); $('#ti-alert').text($('#ti-alert').text().replace(/load.+/, "loading finished.(click to close)")); } if (refresh === true) { $('#ti-pages a.refresh-btn').removeClass('disabled'); $('#ti-pages a.refresh-btn').html('refresh'); $('.infoWrapper_tv').removeClass('disabled'); $('.infoWrapper_book').removeClass('disabled'); refresh = false; } } // 构造首页条目格子 function create_subject_cell(subject_id) { var subject = watching_subjects[subject_id]; if (subject.type !== 1) { $('.infoWrapper_tv').append(` <div id='subjectPanel_${subject.id}' subject_type='${subject.type}' class='clearit infoWrapper tinyMode'> <a href='/subject/${subject.id}' title='${subject.title}' class='grid tinyCover ll'> <img src='${subject.thumb}' class='grid'> </a> <div class='epGird'> <div class='tinyHeader'> <a href='/subject/${subject.id}' title='${subject.title}'>${subject.title}</a> <small class='progress_percent_text'> <a href='/update/${subject.id}?keepThis=false&TB_iframe=true&height=350&width=500' title='修改 ${subject.title} ' class='thickbox l' id='sbj_prg_${subject.id}'>edit</a> </small> </div> <ul class='prg_list clearit'>${subject.prg_list_html}</ul> </div> </div> `); $('#subject_prg_content').append(subject.prg_content_html); } else { $('.infoWrapper_book').append(` <div id='subjectPanel_${subject.id}' subject_type='${subject.type}' class='clearit infoWrapper tinyMode'> <a href='/subject/${subject.id}' title='${subject.title}' class='grid tinyCover ll'> <img src='${subject.thumb}' class='grid'> </a> <div class='epGird'> <div class='tinyHeader'> <a href='/subject/${subject.id}' title='${subject.title}'>${subject.title}</a> <small class='progress_percent_text'> <a href='/update/${subject.id}?keepThis=false&TB_iframe=true&height=350&width=500' title='修改 ${subject.title} ' class='thickbox l' id='sbj_prg_${subject.id}'>edit</a> </small> </div> <div class="tinyManager"> <form method="post" name="batch" class="prgBatchManagerForm" action="/subject/set/watched/${subject.id}"> <input type="hidden" name="home" value="subject"> <div class="btnSubmit rr"><input class="btn" type="submit" name="submit" value="更新"></div> ${subject.prg_list_html} </form> </div> <ul class="prg_list clearit"></ul> </div> </div> `); } } function show_subjects(subject_type) { console.log(`change_tab, subject_type: ${subject_type}`); switch (subject_type) { case "0": //all $('.infoWrapper_tv').show(); $('.infoWrapper_book').hide(); $('.infoWrapper_tv > div').show(); break; case "1": //book $('.infoWrapper_tv').hide(); $('.infoWrapper_book').show(); $('.infoWrapper_book > div').hide(); $('.infoWrapper_book > div[subject_type="1"]').show(); break; case "2": //anime $('.infoWrapper_tv').show(); $('.infoWrapper_book').hide(); $('.infoWrapper_tv > div').hide(); $('.infoWrapper_tv > div[subject_type="2"]').show(); break; case "6": //real $('.infoWrapper_tv').show(); $('.infoWrapper_book').hide(); $('.infoWrapper_tv > div').hide(); $('.infoWrapper_tv > div[subject_type="6"]').show(); break; default: break; } reset_odd_even(); } function reset_odd_even() { $.each($('.infoWrapper_tv > div:visible, .infoWrapper_book > div:visible'), function(index, item) { $(item).removeClass("even odd"); $(item).addClass((index % 2) ? "even" : "odd"); }); } // 上限50是动画和三次元加起来的,这里返回的会包含三次元的条目 function all_ids_on_index(html) { return $(html).find('.infoWrapper_tv > div, .infoWrapper_book > div').map(function(index, element) { return $(element).attr('id').split("_")[1]; }).toArray(); } function tv_subject_ids_on_index(html) { return $(html).find('.infoWrapper_tv > div').map(function(index, element) { return $(element).attr('id').split("_")[1]; }).toArray(); } function book_subject_ids_on_index(html) { return $(html).find('.infoWrapper_book > div').map(function(index, element) { return $(element).attr('id').split("_")[1]; }).toArray(); } function tv_subjects_size_on_index() { return $('.infoWrapper_tv > div').length; } function anime_subjects_size_on_index() { return $('.infoWrapper_tv > div[subject_type="2"]').length; } function real_subjects_size_on_index() { return $('.infoWrapper_tv > div[subject_type="6"]').length; } function book_subjects_size_on_index() { return $('.infoWrapper_book > div').length; } // init $(document).ready(function() { if (location.pathname !== "/") return; $("#cloumnSubjectInfo").prepend("<div id='ti-alert'/>"); $('#cloumnSubjectInfo').prepend(`<div id='ti-pages' class='categoryTab' style='display:none;'> <a type='button' data-page='refresh' class='refresh-btn' href='javascript:void(0);'><span>refresh</span></a> <label>进入首页自动刷新extra项目进度 <input class="auto-refresh-input" name="auto_refresh" type="checkbox"/></label> </div>`); var size1 = anime_subjects_size_on_index(); var size2 = real_subjects_size_on_index(); var size3 = book_subjects_size_on_index(); if (size1 + size2 <= 49 && size3 <= 49) { $('#ti-alert').show(); $('#ti-alert').text(`Watching ${size1} animes, ${size2} reals, ${size3} books.(click to close)`); localStorage.removeItem(LS_SCOPE); return; } // 处理localStorage版本结构不匹配的问题 if (localStorage[LS_SCOPE] !== undefined) { if (JSON.parse(localStorage[LS_SCOPE]).watching_subjects === undefined) { localStorage.removeItem(LS_SCOPE); } } if (auto_refresh == false && localStorage[LS_SCOPE] !== undefined) { $('#ti-alert').show(); var cache = JSON.parse(localStorage[LS_SCOPE]); watching_subjects = cache.watching_subjects; extra_book_queue = cache.extra_book_queue; extra_tv_queue = cache.extra_tv_queue; animes_size = cache.animes_size; reals_size = cache.reals_size; books_size = cache.books_size; auto_refresh = cache.auto_refresh || false; $(`.auto-refresh-input`).prop('checked', auto_refresh); origin_tv_queue = tv_subject_ids_on_index(document); origin_book_queue = book_subject_ids_on_index(document); if(!auto_refresh){ $('#ti-alert').text(`Maybe watching ${animes_size} animes, ${reals_size} reals, ${books_size} books, load form localStorage.(click to close)`); change_mode(); add_extra_subjects(); } else { $('#ti-alert').show(); $('#ti-alert').text(`Maybe watching more than 50 animes and reals, ${size3} books, loading to comfirm.(click to close)`); setTimeout(function() { get_watching_list(); }, 10); } } else { $('#ti-alert').show(); $('#ti-alert').text(`Maybe watching more than 50 animes and reals, ${size3} books, loading to comfirm.(click to close)`); setTimeout(function() { get_watching_list(); }, 10); } }); $('#prgManagerMain').on('click', '#ti-alert', function(e) { $('#ti-alert').hide(); }); $('#prgManagerMain').on('click', 'a.disabled', function(e) { e.preventDefault(); }); $('#prgManagerMain').on('click', '#ti-pages a.refresh-btn', function(e) { $(this).addClass('disabled'); $(this).html('refreshing'); localStorage.removeItem(LS_SCOPE); $('.infoWrapper_tv').addClass('disabled'); $('.infoWrapper_book').addClass('disabled'); $('.infoWrapper_tv').html(''); $('.infoWrapper_book').html(''); // $('#subject_prg_content').html(''); refresh = true; $.get('/', function(data) { var html = data; $('.infoWrapper_tv').html($(html).find('.infoWrapper_tv').html()); $('.infoWrapper_book').html($(html).find('.infoWrapper_book').html()); $('#subject_prg_content').html($(html).find('#subject_prg_content').html()); origin_tv_queue = tv_subject_ids_on_index(html); origin_book_queue = book_subject_ids_on_index(html); setTimeout(function() { get_watching_list(); }, 10); }); }); // $(document).on('click', '#ti-pages a.clear-btn', function(e) { // $(this).addClass('disabled'); // $(this).html('clearing'); // localStorage.removeItem(LS_SCOPE); // $(this).removeClass('disabled'); // $(this).html('clear'); // }); $('#prgManagerMain').on('change', '.auto-refresh-input', function(e) { auto_refresh = e.target.checked; progress_changed = true; }); $('#prgCatrgoryFilter a').off('click').on('click', function(e) { $('#prgCatrgoryFilter a').removeClass('focus'); $(this).addClass('focus'); show_subjects($(this).attr('subject_type')); }); //restore extra subjects' progress $(window).on('pagehide', function(e) { if (localStorage[LS_SCOPE] === undefined || progress_changed === false) return; localStorage[LS_SCOPE] = JSON.stringify({ watching_subjects: watching_subjects, extra_book_queue: extra_book_queue, extra_tv_queue: extra_tv_queue, animes_size: animes_size, reals_size: reals_size, books_size: books_size, auto_refresh: auto_refresh }); console.log('restore localStorage'); }); // 通过ajax请求事件,检查条目进度是否有变更 $(document).on('ajaxSuccess', function(event, xhr, options) { if (localStorage[LS_SCOPE] === undefined) return; var link = document.createElement("a"); link.href = options.url; var tv_match = link.pathname.match(/^\/subject\/ep\/(\d+)\/status/); var book_match = link.pathname.match(/^\/subject\/set\/watched\/\d+/); if (tv_match !== null || book_match !== null) { var ep_id = (tv_match || [])[1] || (book_match || [])[1]; var html = $(`#prg_${ep_id}`).parents('.infoWrapper'); var subject_id = $(html).attr('id').split("_")[1]; var type = parseInt($(html).attr('subject_type')); var subject = watching_subjects[subject_id]; var index; // extra条目进度变更,需要处理队列 if (!in_origin_queue(subject_id)) { console.log(`extra subject ${subject_id} progress change`); subject.extra = false; subject.prg_content_html = null; if (type === 1) { index = extra_book_queue.indexOf(subject_id); extra_book_queue.splice(index, 1); origin_book_queue.unshift(subject_id); var origin_book_queue_last_subject_id = origin_book_queue.pop(); extra_book_queue.push(origin_book_queue_last_subject_id); // 请求详情页,更新进度信息 $.get('/subject/' + subject_id, function(data) { var prg_list_html, prg_content_html; var html = remove_img_src(data); var progress = $(html).find('#watchedeps').text().split("/")[0]; var title = $(html).find('.nameSingle > a').text(); if (type !== 1) { prg_list_html = $(html).find('.prg_list').addClass("clearit").html() || ''; prg_content_html = $(html).find('#subject_prg_content').html() || ''; } else { prg_list_html = $(html).find('.prgText').map(function(index, element) { $(element).append('<a href="javascript:void(0)" class="input_plus plus">+</a>'); return element.outerHTML; }).toArray().join('\n'); prg_content_html = null; } var thumb = ($(html).find('a.thickbox.cover').attr('href') || '').replace('/l/', '/g/'); watching_subjects[subject_id] = new Subject({ id: subject_id, title: title, progress: progress, prg_list_html: prg_list_html, prg_content_html: prg_content_html, thumb: thumb, type: type, extra: true }); }); } else { index = extra_tv_queue.indexOf(subject_id); extra_tv_queue.splice(index, 1); origin_tv_queue.unshift(subject_id); var origin_tv_queue_last_subject_id = origin_tv_queue.pop(); extra_tv_queue.push(origin_tv_queue_last_subject_id); // 请求详情页,更新进度信息 $.get('/subject/' + subject_id, function(data) { var prg_list_html, prg_content_html; var html = remove_img_src(data); var progress = $(html).find('#watchedeps').text().split("/")[0]; var title = $(html).find('.nameSingle > a').text(); if (type !== 1) { prg_list_html = $(html).find('.prg_list').addClass("clearit").html() || ''; prg_content_html = $(html).find('#subject_prg_content').html() || ''; } else { prg_list_html = $(html).find('.prgText').map(function(index, element) { $(element).append('<a href="javascript:void(0)" class="input_plus plus">+</a>'); return element.outerHTML; }).toArray().join('\n'); prg_content_html = null; } var thumb = ($(html).find('a.thickbox.cover').attr('href') || '').replace('/l/', '/g/'); watching_subjects[subject_id] = new Subject({ id: subject_id, title: title, progress: progress, prg_list_html: prg_list_html, prg_content_html: prg_content_html, thumb: thumb, type: type, extra: true }); }); } progress_changed = true; } } });