bangumi过滤搜索结果

自动去除标签搜索结果中错误的结果,手动去除你认为错误的标签或关键词搜索结果,下次搜索时将自动过滤

// ==UserScript==
// @name         bangumi过滤搜索结果
// @namespace    https://github.com/bangumi/scripts/tree/master/liaune
// @version      0.3.3
// @description  自动去除标签搜索结果中错误的结果,手动去除你认为错误的标签或关键词搜索结果,下次搜索时将自动过滤
// @author       Liaune
// @license      MIT
// @include     /^https?://(bgm\.tv|chii\.in|bangumi\.tv)/*
// @grant        none
// ==/UserScript==

(function() {
	// 检测 indexedDB 兼容性,因为只有新版本浏览器支持
    let indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB;
    // 初始化 indexedDB
    const dbName = 'Bangumi_Subject_Tags';
    const tableName = 'tags';
    const indexName = 'id';
    if (indexedDB) {
        let request = indexedDB.open(dbName, 1);
        request.onupgradeneeded = evt => {
            let db = evt.target.result;
            let objectStore = db.createObjectStore(tableName, {keyPath: indexName});
        }
        request.onsuccess = evt => {
            //removeCache();
        }
    }
    // 用来记录已经被使用的缓存列表
    let cacheLists = [];
    // 获取本地缓存
    function getCache(itemId, callback) {
        let request = indexedDB.open(dbName, 1);
        request.onsuccess = evt => {
            let db = evt.target.result;
            let transaction = db.transaction([tableName], 'readonly');
            let objectStore = transaction.objectStore(tableName);
            let reqInfo = objectStore.get(itemId);
            reqInfo.onsuccess = evt => {
                let result = evt.target.result;
                if(!!result) {
                    cacheLists.push(itemId);
                    callback(true, result.value.content);
                } else {
                    callback(false);
                }
            }
            reqInfo.onerror = evt => {
                callback(false);
            }
        };
    }
    // 记录到本地缓存
    function setCache(itemId, data) {
        let request = indexedDB.open(dbName, 1);
        request.onsuccess = evt => {
            let db = evt.target.result;
            let transaction = db.transaction([tableName], 'readwrite');
            let objectStore = transaction.objectStore(tableName);
            let cache = {
                content: data,
                created: new Date()
            };
            let reqInfo = objectStore.put({id: itemId, value: cache})
            reqInfo.onerror = evt => {
                // console.log('Error', evt.target.error.name);
            }
            reqInfo.onsuccess = evt => {}
        };
    }
    // 清除和更新缓存
    function removeCache() {
        let request = indexedDB.open(dbName, 1);
        request.onsuccess = evt => {
            let db = evt.target.result;
            let transaction = db.transaction([tableName], 'readwrite'),
                store = transaction.objectStore(tableName),
                cacheTime = 1000*3600*24*7*4; //4周
            store.openCursor().onsuccess = evt => {
                let cursor = evt.target.result;
                if (cursor) {
                    if (cacheLists.indexOf(cursor.value.name) !== -1) {
                        cursor.value.created = new Date();
                        cursor.update(cursor.value);
                    } else {
                        let now = new Date(),
                            last = cursor.value.created;
                        if (now - last > cacheTime) {
                            cursor.delete();
                        }
                    }
                    cursor.continue();
                }
            }
        };
    }



    let itemsList,blacklist,type,key,count=0,see=0;
	const hotTags = ['TV','剧场版','漫画改','原创','搞笑','OVA','轻小说改','里番'];

    if(localStorage.getItem('bangumi_result_blacklist'))
        blacklist = JSON.parse(localStorage.getItem('bangumi_result_blacklist'));
    else
        blacklist = {"tag":{},"subject_search":{}};
    //let match = decodeURI(location.href).match(/(tag|subject_search)\/(\S+)(\/|.?).*/);
    let match = decodeURI(location.pathname).match(/(tag|subject_search)/);
    if(match){
        type = match[1];
		let arr = decodeURI(location.pathname).split('/');
		let index = arr.findIndex((e)=> e == type);
        key = arr[index+1];
        let showBtn = document.createElement('li');
        let select = document.createElement('a'); $(select).css({"background-image": "url(https://i.loli.net/2018/11/04/5bdef15ba9076.png)","background-size": "1600px 2444px","background-position": "-405px -1045px"});
        select.href='javascript:;';
        if(document.querySelectorAll('#browserTypeSelector li')[0]) document.querySelector('#browserTypeSelector').insertBefore(showBtn, document.querySelectorAll('#browserTypeSelector li')[0]);
        showBtn.appendChild(select);
        select.addEventListener('click', filter);

        filter();
        see = 0;
    }
    function filter(){
        count = 0;
        itemsList = document.querySelectorAll('#browserItemList li.item');
		if(!itemsList.length) return 0;
        see = (see==1)? 0 :1;
        if(!blacklist[type][key]) blacklist[type][key] = [];
        let fetchList = [];
        itemsList.forEach( (elem) => {
            let href = elem.querySelector('a.subjectCover').href;
            let ID = href.split('/subject/')[1];

			let hideBtn = document.createElement('a');  hideBtn.href='javascript:;';  hideBtn.className = 'delet-icon'; hideBtn.textContent = '☒'; hideBtn.style.float='right';
            hideBtn.addEventListener('click', function(){
                if(blacklist[type][key].includes(ID)){
                    blacklist[type][key].splice(blacklist[type][key].indexOf(ID),1);
                    alert("已将此条目从黑名单中移除");
                    localStorage.setItem('bangumi_result_blacklist',JSON.stringify(blacklist));
                }
                else{
                    $(elem).hide();
                    blacklist[type][key].push(ID);
                    localStorage.setItem('bangumi_result_blacklist',JSON.stringify(blacklist));
                }
            });
            if(!$(elem).find('.delet-icon').length) elem.appendChild(hideBtn);

            if(blacklist[type][key].includes(ID)){
                if(see) $(elem).hide();
                else $(elem).show();
                count++;
            }
            else if(type == 'tag'){
				getCache(ID, function(success, result) {
                    if (success) {
                        if(!result.includes(key)){
							blacklist[type][key].push(ID);
							localStorage.setItem('bangumi_result_blacklist',JSON.stringify(blacklist));
							$(elem).hide();
						}
                    }
                    else{
                        fetchList.push(elem);
                    }
                });
				fetchList.push(elem);
			}
            else count++;
        });
		let i = 0;
        let getitemsList= setInterval(function(){
            let elem = fetchList[i];
            if(elem){
                let href = elem.querySelector('a.subjectCover').href;
                getStatus(href,elem);
                i++;
            }
            if(count >= itemsList.length){
                clearInterval(getitemsList);
            }
        },300);
    }

    function getStatus(href,elem){
        let xhr = new XMLHttpRequest();
        xhr.open( "GET", href );
        xhr.withCredentials = true;
        xhr.responseType = "document";
        xhr.send();
        xhr.onload = function(){
            let d = xhr.responseXML;
            let ID = href.split('/subject/')[1];
            let tagList = d.querySelectorAll('#subject_detail .subject_tag_section .inner a.l');
            let tagsAll = {"tag":[],"vote":[]};
            for(let i=0;i<tagList.length;i++){
                tagsAll.tag.push(tagList[i].querySelector('span').textContent);
                tagsAll.vote.push(tagList[i].querySelector('small').textContent);
            }
            let Tags = [];
            for(let i=0;i<tagsAll.tag.length;i++){
                if(checkTag(tagsAll.tag[i]) && parseInt(tagsAll.vote[i])>= Math.min(10,parseInt(tagsAll.vote[0])/10))
                    Tags.push(tagsAll.tag[i]);
            }
			Tags = Tags.slice(0,Math.min(10,Tags.length));
            console.log('check '+ID+':'+Tags);
            setCache(ID,Tags);
			let TagsN = Tags;
			if(hotTags.includes(key)){
				TagsN = Tags.slice(0,5);
			}
            if(!TagsN.includes(key)){
                blacklist[type][key].push(ID);
                localStorage.setItem('bangumi_result_blacklist',JSON.stringify(blacklist));
                $(elem).hide();
            }
            count++;
        }
    }

	function checkTag(Tag){
        function parseDate(Datestring){
            let yy=Datestring.match(/(\d{4})/)? Datestring.match(/(\d{4})/)[1].toString():'';
            let year = Datestring.match(/(\d{4})(年|-)(\d{1,2})(月|-)(\d{1,2})/)? Datestring.match(/(\d{4})(年|-)(\d{1,2})(月|-)(\d{1,2})/)[1].toString(): yy;
            let month = Datestring.match(/(\d{4})(年|-)(\d{1,2})(月|-)(\d{1,2})/)? Datestring.match(/(\d{4})(年|-)(\d{1,2})(月|-)(\d{1,2})/)[3].toString(): '';
            let day = Datestring.match(/(\d{4})(年|-)(\d{1,2})(月|-)(\d{1,2})/)?Datestring.match(/(\d{4})(年|-)(\d{1,2})(月|-)(\d{1,2})/)[5].toString(): '';
            let time = year? (month? (year+'/'+month+'/'+day):year):'';
            return time;
        }
        if(!Tag) return false;
        else if(parseDate(Tag)!='') return false;
        else return true;
    }

    //设置
    if(document.location.href.match(/settings/)){
        $("#header > ul").append('<li><a id="blacklist" href="javascript:void(0);"><span>blacklist</span></a></li>');
        $("#blacklist").on("click", function() {
            $("#header").find("[class='selected']").removeClass("selected");
            $("#blacklist").addClass("selected");
            let data= localStorage.getItem('bangumi_result_blacklist');
            let  html = '<form>' +
                '<span class="text">以下是你所保存的搜索结果过滤黑名单,你可以编辑和替换,点击"确定"即可保存修改</span>'+
                '<textarea id="data_content" name="content" cols="45" rows="15" style="width: 1000px;" class="quick">'+data+'</textarea>'+
                '<input id="submitBtn" class="inputBtn" value="确定" readonly unselectable="on" style="width:26px">' +
                '<a id="alert_submit" style="color: #F09199; font-size: 14px; padding: 20px"></a>'+
                '</form>';
            $("#columnA").html(html);
            $("#submitBtn").on("click", function() {
                data = $("#data_content").attr("value");
                localStorage.setItem('bangumi_result_blacklist',data);
                alert('保存成功!');
            });
        });
    }
})();