// ==UserScript== // @name 优书网 <=> 知轩藏书 // @namespace http://tampermonkey.net/ // @description [知轩藏书/早安电子书/书荒网]添加优书网评分和直链,优书网书籍详情页添加[知轩藏书/早安电子书/龙凤互联/书荒网]下载链接 // @require http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js // @require https://greasyfork.org/scripts/40003-pajhome-md5-min/code/PajHome-MD5-min.js // @author tianxin // @match *://zxcs.me/sort/* // @match *://zxcs.me/post/* // @match *://zxcs.me/index.php?keyword=* // @match *://www.zxcs.me/sort/* // @match *://www.zxcs.me/post/* // @match *://www.zxcs.me/author/* // @match *://www.zxcs.me/tag/* // @match *://www.zxcs.me/index.php?keyword=* // @match *://www.yousuu.com/book/* // @match *://www.zadzs.com/txt/* // @match *://www.zadzs.com/plus/search.php?* // @match *://www.nordfxs.com/* // @match *://www.15huang.com/style/*.html // @match *://www.15huang.com/style/* // @match *://www.15huang.com/e/search/result/* // @match *://www.3uww.cc/down/* // @match *://www.3uww.cc/author/* // @match *://www.3uww.cc/soft* // @match *://www.3uww.cc/search.html // @match *://www.3uww.cc/top/* // @match *://www.xuanquge.com/down/* // @match *://www.xuanquge.com/author/* // @match *://www.xuanquge.com/soft* // @match *://www.xuanquge.com/search.html // @match *://www.xuanquge.com/top/* // @grant GM_xmlhttpRequest // @connect www.yousuu.com // @connect www.zxcs.me // @connect www.zadzs.com // @connect www.nordfxs.com // @connect www.15huang.com // @connect www.3uww.cc // @connect www.mianhuatang.la // @connect zhannei.baidu.com // @connect www.ixdzs.com // @connect www.aixdzs.com // @connect www.xuanquge.com // @version 0.6.1 // @downloadURL none // ==/UserScript== /*================================================= 常量 ================================================*/ // 下载链接缓存时间,默认15天 const DOWNLOAD_EXPIRED_TIME = 86400 * 7 * 1000; // 优书网评分缓存时间,默认1天 const SEARCH_EXPIRED_TIME = 86400 * 1000; // 优书网最大搜索数目,默认5个 const MAX_SEARCH_NUM = 5; // 下载链接类型 1:直接获取 2:解析请求bookLink的响应 3:解析原bookList的响应 const DOWNLOAD_TYPE_DIRECT = 1; const DOWNLOAD_TYPE_FETCH = 2; const DOWNLOAD_TYPE_PROCESS = 3; /*======================================================================================================*/ /*================================================ 类 ================================================*/ /** * local storage 存储,支持过期日期 * 没必要用class,但就是想试试 */ class Storage { /** * 构造函数 */ constructor() { if (this._checkStorageStatus) { this._localStorageStatus = true; } } /** * 检查 local storage 状态 */ _checkStorageStatus() { if (!window.localStorage) { return false; } try { window.localStorage.setItem('checkLocalStorage', '1203'); } catch (error) { return false; } if (window.localStorage.getItem('checkLocalStorage') !== '1203') { return false; } window.localStorage.removeItem('checkLocalStorage'); return true; } /** * 写入 * @param key 键名 * @param value 值 */ setValue(key, value) { if (this._localStorageStatus) { let data = JSON.stringify({ value: value, time: new Date().getTime() }); try { window.localStorage.setItem(key, data); } catch (error) { if (error.name === 'QUOTA_EXCEEDED_ERR') { //存储已满,清空所有 window.localStorage.clear(); } console.log(error); } } } /** * 读取 * @param key 键名 * @param expired 到期日 */ getValue(key, expired) { if (this._localStorageStatus) { let value = window.localStorage.getItem(key); if (value !== null) { let dataObj = JSON.parse(value); if (new Date().getTime() - dataObj.time > expired) { window.localStorage.removeItem(key); return null; } else { return dataObj.value; } } else { return null; } } return null; } /** * 删除 * @param key 键名 */ deleteValue(key) { if (this._localStorageStatus) { window.localStorage.removeItem(key); } } /** * 清除所有 */ clear() { if (this._localStorageStatus) { window.localStorage.clear(); } } } //初始化存储 const storage = new Storage(); /*=====================================================================================================*/ /*=============================================== 配置 ===============================================*/ /** * 评分来源网站配置 */ const rateSiteSourceConfig = { 'yousuu': { name: 'yousuu', //url前缀 prefix: 'http://www.yousuu.com/book/', //请求参数 request(bookInfo) { return { method: "GET", url: 'http://www.yousuu.com/api/search/?type=title&value=' + bookInfo.bookName, } }, //解析 parse(bookInfo, response) { let rateInfo = { score: 0, num: 0, url: '', match: false }; let i = 0; for (let item of JSON.parse(response.responseText).data.books) { i++; //超过最大计数,退出 if (i >= bookInfo.maxNum) { break; } if (item.author == bookInfo.bookAuthor && item.title == bookInfo.bookName) { rateInfo.score = Number.parseFloat(item.score / 10).toFixed(1); rateInfo.num = Math.round(Number.parseFloat(item.scorerCount)); rateInfo.url = this.prefix + item.bookId; rateInfo.match = true; break; } } return rateInfo; } }, } /** * 需添加评分网站的路由配置 * 根据页面转换为 rateSiteTargetConfig 的键名 */ const rateSiteTargetRoute = { 'www.zxcs.me': () => { let tag = location.pathname.split('/')[1]; if (tag === 'post') { return 'zxcs8.post'; } if (['sort', 'tag', 'author'].includes(tag)) { return 'zxcs8.sort'; } // 搜索页面 if (location.pathname.includes('index.php')) { return 'zxcs8.sort'; } }, 'www.zadzs.com': () => { let pathname = location.pathname; if (pathname.includes('txt')) { return 'zadzs.detail'; } if (pathname.includes('search')) { return 'zadzs.search'; } }, 'www.15huang.com': () => { let pathname = location.pathname; // 搜索结果 || 作者 if (pathname == '/e/search/result/') { return '15huang.category'; } // 详情页 if (pathname.includes('.html')) { return '15huang.detail'; } return '15huang.category'; }, 'www.3uww.cc': () => { let pathname = location.pathname; // 排行 if (pathname.includes('top')) { return '3uww.category'; } // 详情 if (pathname.includes('down')) { return '3uww.detail'; } // 作者 if (pathname.includes('author')) { return '3uww.author'; } // 分类 if (pathname.search(/soft(\d+)/ig) !== -1) { return '3uww.category'; } // 搜索 if (pathname.includes('search')) { return '3uww.search'; } }, 'www.xuanquge.com': () => { let pathname = location.pathname; // 排行 if (pathname.includes('top')) { return '3uww.category'; } // 详情 if (pathname.includes('down')) { return '3uww.detail'; } // 作者 if (pathname.includes('author')) { return '3uww.author'; } // 分类 if (pathname.search(/soft(\d+)/ig) !== -1) { return '3uww.category'; } // 搜索 if (pathname.includes('search')) { return '3uww.search'; } }, }; /** * 需添加评分网站的配置 */ const rateSiteTargetConfig = { 'zxcs8.post': { name: 'zxcs8.post', bookName(item) { return item.querySelector('h1').innerText.match('《(.*?)》')[1]; }, bookAuthor(item) { return item.querySelector('h1').innerText.split(':').pop(); }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '

优书网评分: ' + rate + '

评分人数: ' + rateNum + '

'; }, anchorObj(item) { let obj = item.querySelector('.yinyong'); return !obj ? item.querySelector('.pagefujian') : obj; }, anchorPos: 'beforebegin', handler(options, callback) { callback({ site: this.name, item: document, ...options }); }, }, 'zxcs8.sort': { name: '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', handler(options, callback) { let bookList = Array.from(document.querySelectorAll('#plist')); bookList.forEach((item) => { callback({ site: this.name, item: item, ...options }); }); }, }, 'zadzs.detail': { name: 'zadzs.detail', bookName(item) { return item.querySelector('h3[title]').title; }, bookAuthor(item) { return item.querySelector('h3[title]>span>a').innerText; }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '评分:' + rate + '人数:' + rateNum + ''; }, anchorObj(item) { return item.querySelector('.m-bookstatus>table>tbody'); }, anchorPos: "afterbegin", handler(options, callback) { callback({ site: this.name, item: document, ...options }); }, }, 'zadzs.search': { name: 'zadzs.search', bookName(item) { return item.querySelector('.book>h5>a').innerText; }, bookAuthor(item) { return item.querySelector('.book>.price').innerText.split(':').pop(); }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '

评分:' + rate + '  人数:' + rateNum + '

'; }, anchorObj(item) { return item.querySelector('.book>.disc'); }, anchorPos: "beforebegin", handler(options, callback) { let bookList = Array.from(document.querySelectorAll('.searchItem')); bookList.forEach((item) => { callback({ site: this.name, item: item, ...options }); }); }, }, '15huang.detail': { name: '15huang.detail', bookName(item) { return item.querySelector('.row>h1').innerText; }, bookAuthor(item) { return item.querySelector('p.book-writer>a').innerText; }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '

优书评分:' + rate + '

评分人数:' + rateNum + '

'; }, anchorObj(item) { return item.querySelector('p.book-writer'); }, anchorPos: "afterend", handler(options, callback) { callback({ site: this.name, item: document, ...options }); }, }, '15huang.category': { name: '15huang.category', bookName(item) { return item.querySelector('h4.ellipsis').innerText.match('《(.*?)》')[1]; }, bookAuthor(item) { return item.querySelector('span.writer').innerText; }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '|' + rate + '分|' + rateNum + '人'; }, anchorObj(item) { return item.querySelector('p.info.hei9.ellipsis'); }, anchorPos: "beforeend", handler(options, callback) { let bookList = Array.from(document.querySelectorAll("li.cate-infobox.col.xs-24.md-12")); bookList.forEach((item) => { callback({ site: this.name, item: item, ...options }); }); }, }, '3uww.detail': { name: '3uww.detail', bookName(item) { return item.querySelector('#downInfoTitle').innerText.match('《(.*?)》')[1]; }, bookAuthor(item) { return item.querySelector('.downInfoRowL>a').innerText; }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '书籍评分:' + rate + '
评价人数:' + rateNum + '
'; }, anchorObj(item) { return item.querySelector('.downInfoRowL>a').parentNode; }, anchorPos: "beforeend", handler(options, callback) { callback({ site: this.name, item: document, ...options }); }, }, '3uww.author': { name: '3uww.author', bookName(item) { return item.querySelector('.txt99>h2>a').innerText; }, bookAuthor(item) { return document.querySelector('#Li1').innerText.replace(/的小说/ig, ""); }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '
书籍评分:' + rate + '
评分人数:' + rateNum + '
'; }, anchorObj(item) { return item.querySelector('.txt99>ul').children[2]; }, anchorPos: "afterbegin", handler(options, callback) { let bookList = Array.from(document.querySelectorAll('.pinglw')); bookList.forEach((item) => { callback({ site: this.name, item: item, ...options }); }); }, }, '3uww.category': { name: '3uww.category', bookName(item) { return item.info.querySelector('span.mainSoftName>a').innerText; }, bookAuthor(item) { return item.bottom.querySelectorAll('.mainRunSystem')[1].innerText.replace(/书籍作者:/ig, "").trim(); }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '
书籍评分:' + rate + '
评分人数:' + rateNum + '
' }, anchorObj(item) { return item.bottom.querySelector('.mainRunSystem'); }, anchorPos: "afterend", handler(options, callback) { let bookInfo = Array.from(document.querySelectorAll('.mainListInfo')); let bookBottom = Array.from(document.querySelectorAll('.mainListBottom')); bookInfo.forEach((value, index) => { callback({ site: this.name, item: { info: value, bottom: bookBottom[index] }, ...options }); }); }, }, '3uww.search': { name: '3uww.search', bookName(item) { return item.info.querySelector('a').innerText.split('/')[0]; }, bookAuthor(item) { return item.info.querySelector('a').innerText.split('/')[1].replace(/作者:/ig, ""); }, maxNum: MAX_SEARCH_NUM, rateItem(rate, rateNum, bookLink) { return '  评分:' + rate + '  人数:' + rateNum; }, anchorObj(item) { return item.bottom.querySelector('.oldDate'); }, anchorPos: "afterend", handler(options, callback) { let bookInfo = Array.from(document.querySelectorAll('.searchTopic')); let bookBottom = Array.from(document.querySelectorAll('.searchInfo')); bookInfo.forEach((value, index) => { callback({ site: this.name, item: { info: value, bottom: bookBottom[index] }, ...options }); }); } }, }; /** * 下载链接来源网站配置 */ const downloadSiteSourceConfig = { 'zxcs8': { name: 'zxcs8', siteName: '知轩藏书', searchConfig(args) { return { url: 'http://www.zxcs.me/index.php?keyword=' + args.bookName, method: "GET" }; }, bookList(item) { return Array.from(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; }, handler(options) { return getDownLoadLink((Object.assign(options, { type: DOWNLOAD_TYPE_FETCH }))); }, parse(bookInfo, handler, response) { return parseRawDownloadResponse(bookInfo, handler, response); }, // type: DOWNLOAD_TYPE_FETCH 需设置 fetchConfig(options) { return { url: options.url, method: 'GET' }; }, }, // 'zadzs': { // name: 'zadzs', // siteName: '早安电子书', // searchConfig(args){ // return { url: 'http://www.zadzs.com/plus/search.php?kwtype=0&q=' + args.bookName }; // }, // bookList(item){ // return Array.from(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; // }, // handler(options){ // return getDownLoadLink((Object.assign(options, { type: DOWNLOAD_TYPE_DIRECT }))); // }, // parse(bookInfo,handler,response){ // return parseRawDownloadResponse(bookInfo,handler,response); // }, // // type: DOWNLOAD_TYPE_FETCH 需设置 // fetchConfig(options){ // return {url:options.url,method:'GET'}; // }, // }, 'nordfxs': { name: 'nordfxs', siteName: '龙凤互联', searchConfig(args) { // let form = new FormData(); // form.append("formhash", "191940c0"); // form.append("srchtxt", args.bookName); // form.append("searchsubmit", "yes"); let data = 'formhash=191940c0&srchtxt=' + args.bookName + '&searchsubmit=yes'; let headers = { "Content-Type": "application/x-www-form-urlencoded" }; return { url: "https://www.nordfxs.com/search.php?mod=forum", data: data, method: "POST", headers: headers }; }, bookList(item) { return Array.from(item.querySelectorAll('.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; }, handler(options) { return getDownLoadLink((Object.assign(options, { type: DOWNLOAD_TYPE_DIRECT }))); }, parse(bookInfo, handler, response) { return parseRawDownloadResponse(bookInfo, handler, response); }, // type: DOWNLOAD_TYPE_FETCH 需设置 fetchConfig(options) { return { url: options.url, method: 'GET' }; }, }, '15huang': { name: '15huang', siteName: '书荒网', searchConfig(args) { let data = 'show=title%2Cwriter%2Ckeyboard&tbname=news&tempid=1&keyboard=' + encodeURIComponent(args.bookName); let headers = { "Content-Type": "application/x-www-form-urlencoded", "Cookie": "alllclastsearchtime=" + (Date.parse(new Date) / 1000 - 480) }; return { url: "http://www.15huang.com/e/search/index.php", data: data, method: "POST", headers: headers, anonymous: true }; }, bookList(item) { return Array.from(item.querySelectorAll("li.cate-infobox.col.xs-24.md-12")); }, bookName(item) { return item.querySelector('h4.ellipsis').innerText.match('《(.*?)》')[1]; }, bookAuthor(item) { return item.querySelector('span.writer').innerText; }, bookLink(item) { return item.querySelector('a.open.bg-hui-hover').href; }, downloadLink(item) { return 'http://www.15huang.com' + item.querySelector('.downurl.col.xs-24.md-5>a').href.replace(location.origin, ''); }, handler(options) { return getDownLoadLink((Object.assign(options, { type: DOWNLOAD_TYPE_FETCH }))); }, parse(bookInfo, handler, response) { return parseRawDownloadResponse(bookInfo, handler, response); }, // type: DOWNLOAD_TYPE_FETCH 需设置 fetchConfig(options) { return { url: options.url, method: 'GET' }; }, }, '3uww': { name: '3uww', siteName: '炫书网', searchConfig(args) { let data = 'searchkey=' + args.bookName; let headers = { "Content-Type": "application/x-www-form-urlencoded" }; return { url: "https://www.xuanquge.com/search.html", data: data, method: "POST", headers: headers }; }, bookList(item) { return Array.from(item.querySelectorAll('.searchTopic')); }, bookName(item) { return item.querySelector('a').innerText.split('/')[0]; }, bookAuthor(item) { return item.querySelector('a').innerText.split('/')[1].replace(/作者:/ig, ""); }, bookLink(item) { return item.querySelector('a').href; }, downloadLink(item) { return item.querySelector('.downAddress_li>a').href; }, handler(options) { return getDownLoadLink((Object.assign(options, { type: DOWNLOAD_TYPE_FETCH }))); }, parse(bookInfo, handler, response) { return parseRawDownloadResponse(bookInfo, handler, response); }, // type: DOWNLOAD_TYPE_FETCH 需设置 fetchConfig(options) { return { url: options.url, method: 'GET' }; }, }, // 'mianhuatang': { // name: 'mianhuatang', // siteName: '棉花糖小说网', // searchConfig(args){ // return { url: 'http://zhannei.baidu.com/cse/search?s=7965856832468911224&q=' + args.bookName }; // }, // bookList(item){ // return Array.from(item.querySelectorAll('.result-item.result-game-item')); // }, // bookName(item){ // return item.querySelector('.result-game-item-detail>h3>a').title; // }, // bookAuthor(item){ // return item.querySelector('.result-game-item-info>p.result-game-item-info-tag').lastElementChild.innerText.trim(); // }, // bookLink(item){ // return item.querySelector('.result-game-item-detail>h3>a').href; // }, // downloadLink(item){ // return 'http://www.mianhuatang.la/down/txt' + item.querySelector('.result-game-item-detail>h3>a').href.match(/(\d+)/ig).pop() + '.html'; // }, // handler(options){ // return getDownLoadLink((Object.assign(options, { type: DOWNLOAD_TYPE_PROCESS }))); // }, // parse(bookInfo,handler,response){ // return parseRawDownloadResponse(bookInfo,handler,response); // }, // // type: DOWNLOAD_TYPE_FETCH 需设置 // fetchConfig(options){ // return {url:options.url,method:'GET'}; // }, // }, 'ixdzs': { name: 'ixdzs', siteName: '爱下电子书', searchConfig(args) { return { url: 'https://www.aixdzs.com/bsearch?q=' + args.bookName, method: "GET" }; }, bookList(item) { return Array.from(item.querySelectorAll('div.box_k>ul>li')); }, bookName(item) { return item.querySelector('h2.b_name>a').innerText; }, bookAuthor(item) { return item.querySelector('p.b_info>span>a').innerText; }, bookLink(item) { return 'https://www.ixdzs.com' + item.querySelector('h2.b_name>a').href.replace(location.origin, ''); }, downloadLink(item) { return 'https://www.ixdzs.com' + item.querySelector('h2.b_name>a').href.replace(location.origin, ''); }, handler(options) { return getDownLoadLink((Object.assign(options, { type: DOWNLOAD_TYPE_DIRECT }))); }, parse(bookInfo, handler, response) { return parseRawDownloadResponse(bookInfo, handler, response); }, // type: DOWNLOAD_TYPE_FETCH 需设置 fetchConfig(options) { return { url: options.url, method: 'GET' }; }, }, }; /** * 需要添加下载链接的网站路由 * 转换为 downloadSiteTargetConfig 的键名 */ const downloadSiteTargetRoute = { 'www.yousuu.com': () => { return 'yousuu'; } }; /** * 需要添加下载链接的网站配置 */ const downloadSiteTargetConfig = { 'yousuu': { name: 'yousuu', _utils: {}, //预处理 prepare() { //获取dataV的值 let node = document.querySelector('div.common-card-layout.main-left-header'); let dataV = node.outerHTML.match(/data-v-(\w+)/g); this._utils.dataV = dataV; //插入下载容器 let content = ''; document.querySelector('div.common-card-layout.main-left-header').insertAdjacentHTML('beforebegin', content); }, bookName() { return document.querySelector('div.book-info-wrap>div.book-info-detail>h1.book-name').innerText; }, bookAuthor() { return document.querySelector('div.book-info-wrap>div.book-info-detail>p.book-author>a').innerText; }, //获取下载链接后的处理 task(info) { let obj = document.querySelector('#gm-insert-download-content'); let item = ''; //如果第一次插入,则显示父容器,同时插入标识 if (obj.parentElement.style.display === 'none') { obj.parentElement.setAttribute('style', 'display:run-in'); item = ''; } item += ''; obj.insertAdjacentHTML('beforeend', item); }, }, } /*======================================================================================================*/ /*=============================================== 方法 ================================================*/ /*=============================================== base ===============================================*/ /** * xhr * @param options 须满足 GM_xmlhttpRequest 参数 */ let fetch = async (options) => { return new Promise((resolve, reject = (response, url = options.url) => { console.log( 'Error getting ' + url + ' (' + response.status + ' ' + response.statusText + ')' ); }) => { GM_xmlhttpRequest({ onload(response) { if (response.status >= 200 && response.status < 400) { resolve(response); } else { reject(response); } }, onerror(response) { reject(response); }, ...options }); }); }; /*=====================================================================================================*/ /*=============================================== 评分 ===============================================*/ /** * 获取评分信息 * @param handler * @param bookInfo {bookName:'',bookAuthor:''} */ let getRateInfo = async (handler, bookInfo) => { let cacheKey = 'GET:RATE:' + handler.name.toUpperCase() + ':NAME:' + bookInfo.bookName + ':AUTHOR:' + bookInfo.bookAuthor; //查询缓存 let cacheValue = storage.getValue(cacheKey, SEARCH_EXPIRED_TIME); if (cacheValue !== null) { return cacheValue; } let response = await fetch(handler.request(bookInfo)); let data = handler.parse(bookInfo, response); storage.setValue(cacheKey, data); return data; }; /** * 将评分插入目标网站 * @param options */ let insertRate = async (options) => { let siteConfig = rateSiteTargetConfig[options.site]; let args = { bookName: siteConfig.bookName(options.item), bookAuthor: siteConfig.bookAuthor(options.item), maxNum: siteConfig.maxNum }; let data = await getRateInfo(rateSiteSourceConfig[options.rateSourceSite], args); if (data.match) { siteConfig.anchorObj(options.item).insertAdjacentHTML(siteConfig.anchorPos, siteConfig.rateItem(data.score, data.num, data.url)); } }; /** * 插入评分(入口) * @param hostname */ let insertBookRate = (hostname) => { if (Object.keys(rateSiteTargetRoute).includes(hostname)) { let site = rateSiteTargetRoute[hostname](); let siteConfig = rateSiteTargetConfig[site]; let options = { site: site, rateSourceSite: 'yousuu' }; siteConfig.handler(options, insertRate); } } /*=====================================================================================================*/ /*=============================================== 下载 ===============================================*/ /** * 解析下载链接 * @param options */ let getDownLoadLink = async (options) => { let type = options.type; let siteConfig = downloadSiteSourceConfig[options.site]; if (type === DOWNLOAD_TYPE_DIRECT) { //直接获取 return { downloadLink: options.bookLink, siteName: siteConfig.siteName }; } else if (type === DOWNLOAD_TYPE_FETCH) { //从链接中再次解析 //缓存 let cacheKey = 'GET:DOWNLOADLINK:' + siteConfig.name.toUpperCase() + ':' + hex_md5(options.bookLink); let cacheValue = storage.getValue(cacheKey, DOWNLOAD_EXPIRED_TIME); if (cacheValue !== null) { return { downloadLink: cacheValue, siteName: siteConfig.siteName }; } let response = await fetch(siteConfig.fetchConfig({ url: options.bookLink })); let html = new DOMParser().parseFromString(response.responseText, "text/html"); // let html = GM_safeHTMLParser(response); let downloadLink = siteConfig.downloadLink(html); storage.setValue(cacheKey, downloadLink); return { downloadLink: downloadLink, siteName: siteConfig.siteName }; } else if (type === DOWNLOAD_TYPE_PROCESS) { return { downloadLink: siteConfig.downloadLink(options.bookItem), siteName: siteConfig.siteName }; } }; /** * 从原始响应返回解析下载信息 * @param bookInfo * @param response */ let parseRawDownloadResponse = (bookInfo, handler, response) => { let html = new DOMParser().parseFromString(response.responseText, "text/html"); // let html = GM_safeHTMLParser(response); let bookList = handler.bookList(html); let bookLink = ''; let bookItem = ''; let match = bookList.some((item) => { if (handler.bookName(item) === bookInfo.bookName && handler.bookAuthor(item) === bookInfo.bookAuthor) { bookItem = item; bookLink = handler.bookLink(item); return true; } }); let data = { bookLink: bookLink, bookItem: bookItem, match: match }; let cache = { bookLink: bookLink, bookItem: (match ? bookItem.innerHTML : ''), match: match }; return [data, cache]; }; /** * 获取下载信息 * @param handler * @param bookInfo */ let getDownloadInfo = async (handler, bookInfo) => { //查缓存 let cacheKey = 'GET:BOOKLINK:' + handler.name.toUpperCase() + ':NAME:' + bookInfo.bookName + ':AUTHOR:' + bookInfo.bookAuthor; let cacheValue = storage.getValue(cacheKey, DOWNLOAD_EXPIRED_TIME); if (cacheValue !== null) { return { bookLink: cacheValue.bookLink, bookItem: new DOMParser().parseFromString(cacheValue.bookItem, "text/html"), match: cacheValue.match }; // return { bookLink: cacheValue.bookLink, bookItem: GM_safeHTMLParser(cacheValue.bookItem) }; } let response = await fetch(handler.searchConfig({ bookName: bookInfo.bookName })); let [data, cache] = handler.parse(bookInfo, handler, response); storage.setValue(cacheKey, cache); return data; }; /** * 将下载链接插入目标网站 * @param options */ let insertDownload = async (options) => { let target = downloadSiteTargetConfig[options.downloadTargetSite]; let bookInfo = { bookName: target.bookName(), bookAuthor: target.bookAuthor() }; let source = downloadSiteSourceConfig[options.site]; //获取下载信息 let downloadInfo = await getDownloadInfo(source, bookInfo); if (downloadInfo.match) { //解析下载链接 let data = await source.handler({ site: options.site, ...downloadInfo }); //处理下载链接 return target.task(data); } }; /** * 插入下载链接(入口) * @param hostname */ let insertBookDownloadLink = async (hostname) => { if (Object.keys(downloadSiteTargetRoute).includes(hostname)) { let sites = Object.keys(downloadSiteSourceConfig); let downloadTargetSite = downloadSiteTargetRoute[hostname](); let targetConfig = downloadSiteTargetConfig[downloadTargetSite]; targetConfig.prepare(); let promises = sites.map((site) => insertDownload({ site: site, downloadTargetSite: downloadTargetSite }).catch(e => console.log(e))); await Promise.all(promises); //sites.forEach( site => { // insertDownload({site:site,downloadTargetSite:downloadTargetSite}).catch(e => console.log(e)); //}) } } /*=====================================================================================================*/ /** * 检查插件兼容性 */ let checkCanUse = () => { let message = '脚本 [优书网 <=> 知轩藏书] '; let canUse = true; if (typeof GM_xmlhttpRequest === "undefined") { message += "暂不支持 Greasemonkey 4.x, 请使用 Tampermonkey 或 Violetmonkey 。"; canUse = false; } return { canUse: canUse, message: message }; }; /*======================================================================================================*/ /** * 入口 */ $(document).ready(() => { window.setTimeout(() => { 'use strict'; //检查兼容性 let checkResult = checkCanUse(); if (!checkResult.canUse) { alert(checkResult.message); return; } //插入评分 insertBookRate(location.hostname); //插入下载链接 insertBookDownloadLink(location.hostname); }, 1000) });