// ==UserScript== // @name 优书网 <=> 知轩藏书 // @namespace http://tampermonkey.net/ // @description [知轩藏书/早安电子书]添加优书网评分和直链,优书网书籍详情页添加[知轩藏书/早安电子书]下载链接 // @author tianxin // @match *://zxcs8.com/sort/* // @match *://zxcs8.com/post/* // @match *://www.zxcs8.com/sort/* // @match *://www.zxcs8.com/post/* // @match *://www.yousuu.com/book/* // @match *://www.zadzs.com/txt/* // @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 // @version 0.4.4 // @downloadURL none // ==/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, synchronous:options.synchronous, onload: (response) => { if (response.status >= 200 && response.status < 400){ 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.data; options.method = !options.method ? 'GET' : options.method; options.synchronous = !options.synchronous ? false : options.synchronous; 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 '

优书网评分: ' + rate + '

评分人数: ' + rateNum + '

'; }, 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 '   评分:' + rate + '   人数:' + rateNum + '' }, 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 '评分:' + rate + '人数:' + rateNum + ''; }, anchorObj:(item) => { return document.querySelector('.m-bookstatus>table>tbody'); }, anchorPos:"afterbegin", } }; let sourceHandle = { 'zxcs8.post':function(site,callback){ let option = {site:site,item:''}; return callback(option); }, 'zxcs8.sort':function(site,callback){ let bookList = Array.prototype.slice.call(document.querySelectorAll('#plist')); bookList.forEach(function(item){ let option = {site:site,item:item}; callback(option); }); }, 'zadzs':function(site,callback){ let option = {site:site,item:''}; return callback(option); }, }; let sourceRoute = { 'www.zxcs8.com':() => { let tag = location.pathname.split('/')[1]; if(['sort','post'].includes(tag)){ return 'zxcs8.' + tag; } }, 'zxcs8.com':() => { let tag = location.pathname.split('/')[1]; if(['sort','post'].includes(tag)){ return 'zxcs8.' + tag; } }, 'www.zadzs.com':() => { return 'zadzs'; } }; 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; }, }, }; 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); }); } }; let downloadRoute = { 'www.yousuu.com':() => { return 'www.yousuu.com'; } }; let insertDownloadButton = () => { let select = '

'; 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 = '
  • '+ options.siteName + '
  • '; 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('
    '); let matchAuthor = matchAbstract[0].split(':')[1].replace(/<\/?[^>]*>/g,'').trim(); 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'; 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); }); } })();