Greasy Fork

Greasy Fork is available in English.

优书网 <=> 知轩藏书

[知轩藏书/早安电子书/书荒网]添加优书网评分和直链,优书网书籍详情页添加[知轩藏书/早安电子书/龙凤互联/书荒网]下载链接

当前为 2018-07-20 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         优书网 <=> 知轩藏书
// @namespace    http://tampermonkey.net/
// @description  [知轩藏书/早安电子书/书荒网]添加优书网评分和直链,优书网书籍详情页添加[知轩藏书/早安电子书/龙凤互联/书荒网]下载链接
// @require      http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js
// @require      http://greasyfork.icu/scripts/368137-encodetogb2312/code/encodeToGb2312.js
// @author       tianxin
// @match        *://zxcs8.com/sort/*
// @match        *://zxcs8.com/post/*
// @match        *://zxcs8.com/index.php?keyword=*
// @match        *://www.zxcs8.com/sort/*
// @match        *://www.zxcs8.com/post/*
// @match        *://www.zxcs8.com/index.php?keyword=*
// @match        *://www.yousuu.com/book/*
// @match        *://www.zadzs.com/txt/*
// @match        *://www.nordfxs.com/*
// @match        *://www.15huang.com/style/*.html
// @match        *://www.15huang.com/style/*
// @match        *://www.15huang.com/e/search/result/*
// @match        *://www.15huang.com/tags-etagid*.html
// @grant        GM.xmlHttpRequest
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @connect      www.yousuu.com
// @connect      www.zxcs8.com
// @connect      www.zadzs.com
// @connect      www.nordfxs.com
// @connect      www.15huang.com
// @version      0.5
// ==/UserScript==

// 请求类型 1:获取评分 2:获取下载
const REQUEST_TYPE_SOURCE = 1;
const REQUEST_TYPE_DOWNLOAD = 2;
// 下载链接缓存时间,默认7天
const DOWNLOAD_EXPIRED_TIME = 86400 * 7 * 1000;
// 优书网评分缓存时间,默认两小时
const SEARCH_EXPIRED_TIME = 2 * 3600 * 1000;
// 优书网最大搜索数目,默认5个
const MAX_SEARCH_NUM = 5;

// 简单封装GM_getValue和GM_setValue,支持过期时间
let storage = {
    setValue:(key,value) => {
        let data = JSON.stringify({value:value,time:new Date().getTime()});
        return GM_setValue(key, data);
    },
    getValue:(key,expired) => {
        let value = GM_getValue(key);
        if(value !== undefined){
            let dataObj = JSON.parse(value);
            if(new Date().getTime() - dataObj.time > expired){
                return undefined;
            }else{
                return dataObj.value;
            }
        }else{
            return undefined;
        }
    },
}
let getResponse = (options) => {
    return new Promise((resolve,reject) => {
       GM_xmlhttpRequest({
           method: options.method,
           url: options.url,
           data:options.data,
           headers:options.headers,
           synchronous:options.synchronous,
           anonymous :options.anonymous,
           onload: (response) => {
               if (response.status >= 200 && response.status < 400){
                   console.log(response);
                   resolve(response.responseText);
               }
               else{
                   console.log(
                       'Error getting ' + options.url + ' (' + this.status + ' ' + this.statusText +
                       '): ' + this.responseText);
               }
           },
           onerror: (response) => {
               console.log('Error during GM_xmlhttpRequest to ' + options.url + ': ' + response.statusText);
           }
       });
    });
}
let getResult = (options) => {
    return new Promise((reslove,reject) => {
        options.data = options.data || '';
        options.method = options.method || 'GET';
        options.headers = options.headers || '' ;
        options.synchronous = options.synchronous || false;
        options.anonymous = options.anonymous || false;
        let key = JSON.stringify(options);
        let value = storage.getValue(key,options.type === REQUEST_TYPE_DOWNLOAD ? DOWNLOAD_EXPIRED_TIME : SEARCH_EXPIRED_TIME);
        if(value !== undefined){
            reslove(value);
        }else{
           getResponse(options).then(response => { storage.setValue(key,response); reslove(response)});
        }
    });
}
let sourceConfig = {
    'zxcs8.post':{
        bookName:(item) => {
            return document.querySelector('h1').innerText.match('《(.*?)》')[1];
        },
        bookAuthor:(item) => {
            return document.querySelector('h1').innerText.split(':').pop();
        },
        maxNum:MAX_SEARCH_NUM,
        rateItem:(rate,rateNum,bookLink) => {
            return '<p class="yinyong"><span style="font-size:14px;color:#FF0000;font-weight:bold">优书网评分: <a href = "' + bookLink + '" target="_blank">' + rate + '</a></span><p><p class="yinyong"><span style="font-size:14px;color:#FF0000;font-weight:bold">评分人数: ' + rateNum + '</span><p>';
        },
        anchorObj:(item) => {
            let obj = document.querySelector('.yinyong');
            return !obj ? document.querySelector('.pagefujian') : obj;
        },
        anchorPos:'beforebegin',
    },
    'zxcs8.sort':{
        bookName:(item) => {
            return item.firstElementChild.innerText.match('《(.*?)》')[1];
        },
        bookAuthor:(item) => {
            return item.firstElementChild.innerText.split(':').pop();
        },
        maxNum:MAX_SEARCH_NUM,
        rateItem:(rate,rateNum,bookLink) => {
            return '<a href= "' + bookLink + '" target = "_blank">&nbsp;&nbsp;&nbsp;评分:' + rate + '&nbsp;&nbsp;&nbsp;人数:' + rateNum + '</a>'
        },
        anchorObj:(item) => {
            return item.lastElementChild.querySelector('div');
        },
        anchorPos:'beforebegin',
    },
    'zadzs':{
        bookName:(item) => {
            return document.querySelector('h3[title]').title;
        },
        bookAuthor:(item) => {
            return document.querySelector('h3[title]>span>a').innerText;
        },
        maxNum:MAX_SEARCH_NUM,
        rateItem:(rate,rateNum,bookLink) => {
            return '<tr><td width="42px">评分:</td><td><a href="'+ bookLink + '" target = "blank">'+ rate + '</a></td></tr><tr><td width="42px">人数:</td><td>' + rateNum + '</td></tr>';
        },
        anchorObj:(item) => {
            return document.querySelector('.m-bookstatus>table>tbody');
        },
        anchorPos:"afterbegin",
    },
    '15huang.detail':{
        bookName:(item) => {
            return document.querySelector('h1.postss-title').innerText.match('《(.*?)》')[1];
        },
        bookAuthor:(item) => {
            return document.querySelector('.novelright>a').innerText;
        },
        maxNum:MAX_SEARCH_NUM,
        rateItem:(rate,rateNum,bookLink) => {
            return '<div class="novelright">优书评分:<a href="'+ bookLink + '" target="_blank">' + rate + '</a></div><div class="novelright">评分人数:' + rateNum + '</div>';
        },
        anchorObj:(item) => {
            return document.querySelector('.novelright>em').parentNode;
        },
        anchorPos:"afterend",
    },
    '15huang.category':{
        bookName:(item) => {
            return item.querySelector('h2.posts-title>a').innerText.match('《(.*?)》')[1];
        },
        bookAuthor:(item) => {
            return item.querySelector('h2.posts-title>a').innerText.split('_').pop();
        },
        maxNum:MAX_SEARCH_NUM,
        rateItem:(rate,rateNum,bookLink) => {
            return '<li><i class="fa fa-star" style="color: #691b15;"></i> <a title="" target="_blank" href="' + bookLink + '">' + rate + '分</a></li><li><i class="fa fa-user-circle" style="color: #691b15;"></i> ' + rateNum + '人</li>';
        },
        anchorObj:(item) => {
            return item.querySelector('ul.posts-meta');
        },
        anchorPos:"beforeend",
    },
};
let sourceHandle = {
    'zxcs8.post':(site,callback) => {
        let option = {site:site,item:''};
        return callback(option);
    },
    'zxcs8.sort':(site,callback) => {
        let bookList = Array.prototype.slice.call(document.querySelectorAll('#plist'));
        bookList.forEach((item) => {
             let option = {site:site,item:item};
             callback(option);
         });
    },
    'zadzs':(site,callback) => {
         let option = {site:site,item:''};
         return callback(option);
    },
    '15huang.detail':(site,callback) => {
        let option = {site:site,item:''};
        return callback(option);
    },
    '15huang.category':(site,callback) => {
        let bookList = Array.prototype.slice.call(document.querySelectorAll('article'));
        bookList.forEach((item) => {
             let option = {site:site,item:item};
             callback(option);
         });
    },
};
let sourceRoute = {
    'www.zxcs8.com':() => {
        let tag = location.pathname.split('/')[1];
        if(['sort','post'].includes(tag)){
            return 'zxcs8.' + tag;
        }
        // 搜索页面
        if(location.pathname.indexOf('index.php') !== -1){
            return 'zxcs8.sort';
        }
    },
    'zxcs8.com':() => {
        let tag = location.pathname.split('/')[1];
        if(['sort','post'].includes(tag)){
            return 'zxcs8.' + tag;
        }
        // 搜索页面
        if(location.pathname.indexOf('index.php') !== -1){
            return 'zxcs8.sort';
        }
    },
    'www.zadzs.com':() => {
        return 'zadzs';
    },
    'www.15huang.com':() => {
        let pathname = location.pathname;
        // 分类页面
        if(pathname.search(/index(_\d+)?\.html/ig) !== -1){
            return '15huang.category';
        }
        // 搜索结果
        if(pathname === '/e/search/result/'){
            return '15huang.category';
        }
        // 作者
        if(pathname.indexOf('tags-etagid') !== -1){
            return '15huang.category';
        }
        // 详情页
        if(pathname.indexOf('.html') !== -1){
            return '15huang.detail';
        }
        return '15huang.category';
    },
};
let downloadConfig = {
    "zxcs8":{
        'siteName':'知轩藏书',
        'searchConfig':(args) => {
            return {url:'http://www.zxcs8.com/index.php?keyword=' + args.bookName};
        },
        'bookList':(item) => {
            return Array.prototype.slice.call(item.getElementsByTagName('dl'));
        },
        'bookName':(item) => {
            return item.children["0"].innerText.match('《(.*?)》')[1];
        },
        'bookAuthor':(item) => {
            return item.children["0"].innerText.split(':').pop();
        },
        'bookLink':(item) => {
            return item.children["0"].getElementsByTagName('a')[0].href;
        },
        'downloadLink':(item) => {
            return item.querySelector('.down_2>a').href;
        },
    },
    "zadzs":{
        'siteName':'早安电子书',
        'searchConfig':(args) => {
            return {url:'http://www.zadzs.com/plus/search.php?kwtype=0&q=' + args.bookName};
        },
        'bookList':(item) => {
            return Array.prototype.slice.call(item.getElementsByClassName('searchItem'));
        },
        'bookName':(item) => {
            return item.querySelector('.book>h5>a').innerText;
        },
        'bookAuthor':(item) => {
            return item.querySelector('.book>.price').innerText.split(':').pop();
        },
        'bookLink':(item) => {
            return 'http://www.zadzs.com' + item.querySelector('.book>.cover').pathname;
        },
        'downloadLink':(item) => {
            return 'http://www.zadzs.com' + item.querySelector('.book>cover').href;
        },
    },
    "nordfxs":{
        'siteName':'龙凤互联',
        'searchConfig':(args) => {
            let form = new FormData();
            form.append("formhash","dfae824e");
            form.append("srchtxt",args.bookName);
            form.append("searchsubmit","yes");
            return {url:"http://www.nordfxs.com/search.php?mod=forum",data:form,method:"POST",'bookName':args.bookName};
        },
        'bookList':(item) => {
            return Array.prototype.slice.call(item.getElementsByClassName('pbw'));
        },
        'bookName':(item) => {
            return item.querySelector('.xs3>a').innerText.split('(').shift().replace(/[《,》]/g,'');
        },
        'bookAuthor':(item) => {
            return item.querySelector('.xs3>a').innerText.split(':').pop();
        },
        'bookLink':(item) => {
            return item.querySelector('.xs3>a').href;
        },
        'downloadLink':(item) => {
            return item.querySelector('.xs3>a').href;
        },
    },
    "15huang":{
        'siteName':'书荒网',
        'searchConfig':(args) => {
            let data = 'show=title%2Cwriter&tbname=news&tempid=1&keyboard=' + encodeToGb2312(args.bookName,true) + '&Submit22=%CB%D1%CB%F7';
            let headers = {"Content-Type": "application/x-www-form-urlencoded","Cookie":"olqyclastsearchtime=" + (Date.parse(new Date) / 1000 - 48)};
            return {url:"http://www.15huang.com/e/search/index.php",data:data,method:"POST",headers:headers,bookName:args.bookName};
        },
        'bookList':(item) => {
            return Array.prototype.slice.call(item.getElementsByClassName('posts type-post'));
        },
        'bookName':(item) => {
            return item.querySelector('h2.posts-title>a').innerText.match('《(.*?)》')[1];
        },
        'bookAuthor':(item) => {
            return item.querySelector('h2.posts-title>a').innerText.split('_').pop();
        },
        'bookLink':(item) => {
            return item.querySelector('h2.posts-title>a').href;
        },
        'downloadLink':(item) => {
            return item.querySelector('.showDown>li>a').href;
        },
    },
};
let downloadHandle = {
    'zxcs8':(options) => {
        let siteConfig = downloadConfig[options.site];
        return new Promise((resolve,reject) => {
            getResult({url:options.bookLink,type:REQUEST_TYPE_DOWNLOAD}).then((response) => {
                let html = document.createElement( 'html' );
                html.innerHTML = response;
                let downloadLink = siteConfig.downloadLink(html);
                resolve({downloadLink:downloadLink,siteName:siteConfig.siteName})
            });
        });
    },
    'zadzs':(options) => {
        return new Promise((resolve,reject) => {
            let args = {downloadLink:options.bookLink,siteName:downloadConfig[options.site].siteName};
            resolve(args);
        });

    },
    'nordfxs':(options) => {
        return new Promise((resolve,reject) => {
            let args = {downloadLink:options.bookLink,siteName:downloadConfig[options.site].siteName};
            resolve(args);
        });
    },
    '15huang':(options) => {
        let siteConfig = downloadConfig[options.site];
        return new Promise((resolve,reject) => {
            getResult({url:options.bookLink,type:REQUEST_TYPE_DOWNLOAD}).then((response) => {
                let html = document.createElement( 'html' );
                html.innerHTML = response;
                let downloadLink = siteConfig.downloadLink(html);
                resolve({downloadLink:downloadLink,siteName:siteConfig.siteName})
            });
        });
    },
};
let downloadRoute = {
    'www.yousuu.com':() => {
        return 'www.yousuu.com';
    }
};
let insertDownloadButton = () => {
    let select = '<div class="btn-group" id="download-list" style="display:none"><button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-warning dropdown-toggle"><span>去下载</span>&nbsp;<span class="caret"></span></button><ul class="dropdown-menu" id="download-items"></ul></div>';
    let obj = document.getElementsByClassName('sokk-book-button-groups')[0];
    obj.insertAdjacentHTML('beforeend',select);
}
let removeElement = element => {
    if(element){
        let parent = element.parentNode;
        if(parent){
            parent.removeChild(element);
        }
    }
}
let addDownLoadLink = (options,config) => {
    let siteConfig = config[options.site];
    let youBookName = document.getElementsByClassName('col-sm-7')[0].children[0].innerText;
    let youBookAuthor = document.getElementsByClassName('list-unstyled list-sm')["0"].firstChild.children["0"].innerText;
    getResult(Object.assign(siteConfig.searchConfig({bookName:youBookName}),{type:REQUEST_TYPE_DOWNLOAD})).then((response) => {
        let html = document.createElement( 'html' );
        html.innerHTML = response;
        let bookList = siteConfig.bookList(html)
        if(bookList.length > 0){
             bookList.some((item) => {
                 let bookLink = siteConfig.bookLink(item);
                 let matchBookName = siteConfig.bookName(item);
                 let matchBookAuthor = siteConfig.bookAuthor(item);
                 console.log(matchBookName + ':' + youBookName + ';' + matchBookAuthor + ':' + youBookAuthor)
                 if(matchBookName === youBookName && matchBookAuthor === youBookAuthor){
                     downloadHandle[options.site]({site:options.site,bookLink:bookLink}).then(insertDownLink);
                 }
             });
        }
    })
};
let insertDownLink = options => {
    let obj = document.querySelector('#download-items');
    let item = '<li><a href="'+ options.downloadLink +'" target="_blank">'+ options.siteName + '</a></li>';
    obj.insertAdjacentHTML('beforeend',item);
    if(obj.parentElement.style.display === 'none'){
        obj.parentElement.setAttribute('style', 'display:run-in');
    }
}
let getRate = args => {
    let bookName = args.bookName;
    let bookAuthor = args.bookAuthor;
    let maxNum = (args.maxNum === undefined) ? 1 : args.maxNum;
    return new Promise((resolve,reject) => {
        getResult({url:'http://www.yousuu.com/search/' + bookName + bookAuthor + '?type=all',type:REQUEST_TYPE_SOURCE}).then((response) => {
            let rate = 0;
            let rateNum = 0;
            let bookLink = '';
            let html = document.createElement( 'html' );
            html.innerHTML = response;
            //let matchBook = Array.slice(Array.prototype.slice.call(html.getElementsByClassName('col-lg-4 col-md-6 col-xs-12')),0,maxNum);
            let matchBook = Array.prototype.slice.call(html.getElementsByClassName('col-lg-4 col-md-6 col-xs-12')).slice(0,maxNum);
            matchBook.some((item) => {
                let matchTitle = item.querySelector('.title');
                let matchName = matchTitle.innerText;
                let matchAbstract = item.querySelector('.abstract').innerHTML.split('<br>');
                let matchAuthor = matchAbstract[0].split(':')[1].replace(/<\/?[^>]*>/g,'').trim();
                console.log(matchAuthor + ':' + bookAuthor + ';' + matchName + ':' + bookName);
                if(matchAuthor === bookAuthor && matchName === bookName){
                    rate = item.querySelector('.num2star').innerHTML;
                    rateNum = item.querySelector('.rating').innerText.replace(/[^0-9]/ig,"");
                    bookLink = 'http://www.yousuu.com' + matchTitle.querySelector('a').pathname;
                    return true;
                }
            });
            resolve({rate:rate,rateNum:rateNum,bookLink:bookLink});
        });
    });
}
let insertRate = options => {
    let siteConfig = sourceConfig[options.site];
    let args = {bookName:siteConfig.bookName(options.item),bookAuthor:siteConfig.bookAuthor(options.item),maxNum:siteConfig.maxNum};
    getRate(args).then((data) => {
        let rate = data.rate;
        let rateNum = data.rateNum;
        let bookLink = data.bookLink;
        if(rate !== 0 || rateNum !== 0){
            let rateItem = siteConfig.rateItem(rate,rateNum,bookLink);
            siteConfig.anchorObj(options.item).insertAdjacentHTML(siteConfig.anchorPos,rateItem);
        }
    });
}
(() => {
    'use strict';
    console.log(document.cookie);
    if(Object.keys(sourceRoute).includes(location.hostname)){
        let site = sourceRoute[location.hostname]();
        sourceHandle[site](site,insertRate);
    }
    if(Object.keys(downloadRoute).includes(location.hostname)){
        let sites = Object.keys(downloadConfig);
        insertDownloadButton();
        sites.forEach((item) => {
            let options = {site:item};
            addDownLoadLink(options,downloadConfig);
        });
    }
})();