Greasy Fork

Greasy Fork is available in English.

起点小说优化|VIP章节免费阅读|阅读体验优化

提供多功能的起点小说网站优化插件,支持多书源、净化等功能

当前为 2024-02-18 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         起点小说优化|VIP章节免费阅读|阅读体验优化
// @version      1.4.11
// @description  提供多功能的起点小说网站优化插件,支持多书源、净化等功能
// @author       JiGuang
// @namespace    www.xyde.net.cn
// @homepageURL  https://51coolplay.cc
// @match        https://www.qidian.com/chapter/*
// @match        https://51coolplay.cc/service/*
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11
// @require https://cdn.staticfile.org/jquery/2.0.3/jquery.min.js
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_openInTab
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @license MIT
// ==/UserScript==

(function() {
    const default_config = `[{"id":1,"name":"读书阁书源","author":"Hunter David","offical":false,"version":"1.0.2","description":"文章正文换成读书阁的书源,修复已购买仍然加载的问题","code":"async function onLoad() {function setStatusText(txt){try{document.querySelector('#reader-content > div.min-h-100vh.relative.z-1.bg-inherit > div > div.relative > div > div.text-s-gray-500.mt-4px.text-bo4.flex.items-center.flex-wrap').innerHTML = txt;}catch(err){console.warn('设置失败');}}if(isBuy()){setStatusText('起点小说优化|您已购买本章');return;}setStatusText('起点小说优化|正在加载内容中...');const DOMAIN = 'http://www.dushuge.com/';const book_res_doc = await parseDocFromAjax('get','http://www.dushuge.com/hsdgiohsdigohsog.php?ie=gbk&q=' + readBookName());let books = [];book_res_doc.querySelectorAll('div.bookinfo > h4 > a').forEach((item, index) => {if(item !== undefined){books.push({name:item.innerText,url:item.href,val:calculateTextSimilarity(readBookName(),item.innerText)});}});books.sort((a, b) => b.val - a.val);if(books.length === 0){notify('未找到该书','error');return;}let book = books[0];let chapters = [];const chapter_res_doc = await parseDocFromAjax('get',book.url.replace('https://www.qidian.com/', DOMAIN));chapter_res_doc.querySelectorAll('dl > dd > a').forEach((item, index)=>{if(item !== undefined){chapters.push({name:item.innerText,url:item.href,val:calculateTextSimilarity(readChapterName(),item.innerText)});}});chapters.sort((a, b) => b.val - a.val);if(books.length === 0){notify('未找到该书有效的目录','error');return;}let chapter = chapters[0];const content_res_doc = await parseDocFromAjax('get',chapter.url.replace('https://www.qidian.com/', DOMAIN));const targetContent = content_res_doc.querySelector('#content').innerText;writeContent(targetContent);notify('读书阁书源读取成功');setStatusText('起点小说优化|正在使用读书阁书源阅读');}","open":true}]`
    // 脚本专用:读取配置到51
    function read51Config(){
        // 如果空,就默认装一下插件
        //console.log('config',GM_getValue('config',default_config))
        document.querySelector("#config").value = GM_getValue('config',default_config)
    }
    // 脚本专用:从51写配置
    function save51Config(){
        GM_setValue('config',document.querySelector("#config").value)
    }
    // 脚本专用:运行开启的配置
    function readConfigOpen(){
        window.onLoad = ()=>{
            notify('您没有开启任何书源插件!!','error')
            let div = document.createElement('div')
            div.innerHTML = '<div style="position:fixed;top:10px;right:10px;"><button id="b56">点我设置书源</button></div>'
            document.body.appendChild(div);
            document.querySelector("#b56").onclick = ()=>{
                GM_openInTab('https://51coolplay.cc/service/book/settings.php')
            }
        }
        const config_str = GM_getValue('config',default_config)
        // console.log(config_str)
        const config_items = JSON.parse(config_str)
        // console.log(config_items)
        //筛选插件代码
        const codes = config_items.filter(e => e.open).map(e => e.code).join(';')
        //注入插件
        console.log(codes)
        try{
            eval(codes)
            //执行启动函数(书源专用)注意,设置中的自定义插件会默认添加onload函数包裹
            onLoad()
        }catch(err){
            console.warn('加载配置失败',err)
            notify('加载配置失败,请去设置页面检查','error')
        }
    }
    // 内置函数:读取页面书名
    function readBookName(){
        const bookNameElement = document.querySelector("#r-breadcrumbs > a.text-s-gray-900");
        if (bookNameElement) {
            // 使用正则表达式去掉括号内的内容
            const rawName = bookNameElement.innerText;
            const cleanedName = rawName.replace(/\([^)]*\)/g, '').trim();
            console.log(`BookName:${cleanedName}`)
            return cleanedName;
        } else {
            return '未知'
            // 或者返回一个默认的名称,或者抛出错误,具体根据需求来定
        }
    }
    // 内置函数:读取章节名
    function readChapterName(){
        let ele = document.querySelector("#reader-content > div.min-h-100vh.relative.z-1.bg-inherit > div > div.relative > div > h1")
        if (ele) {
            let res = '' + ele.innerText
            res = res.replace(' ', '')
            console.log(`BookChapter:${res}`)
            return res
        }
        return '未知'
    }
    // 内置函数:读取正文
    function readContent(){
        return document.querySelector("#reader-content > div.min-h-100vh.relative.z-1.bg-inherit > div > div.relative > div > main").innerText
    }
    // 内置函数:写入正文
    function writeContent(content = '',html = false){
        if(!html){
            document.querySelector("#reader-content > div.min-h-100vh.relative.z-1.bg-inherit > div > div.relative > div > main").innerText = content
        }else{
            document.querySelector("#reader-content > div.min-h-100vh.relative.z-1.bg-inherit > div > div.relative > div > main").innerHTML = content
        }
    }
    // 内置函数:是否已订阅
    function isBuy(){
        return readContent().length > 200
    }
    // 内置函数:将请求的url的html内容转化成document对象
    async function parseDocFromAjax(method,url){
      console.log('请求url:',url)
      return new Promise((resolve,reject) => {
          GM_xmlhttpRequest({
              method,
              url,
              onload:(res) => {
                //console.log(res)
                  let htmldoc = document.createElement('html')
                  htmldoc.innerHTML = res.response
                  resolve(htmldoc)
              },
              onerror:(err) => {
                  reject(err)
              }
          })
      })
    }
    // 内置函数:计算文本相似度,返回0-1之间的数值,0.5以上可以采信
    function calculateTextSimilarity(text1, text2) {
    // 将文本转换成小写并去除空格
    text1 = text1.toLowerCase().replace(/\s/g, "");
    text2 = text2.toLowerCase().replace(/\s/g, "");
    // 计算两个文本的交集
    const intersection = text1.split("").filter(char => text2.includes(char));
    // 计算相似度
    const similarity = intersection.length / (text1.length + text2.length - intersection.length);
    return similarity;
}
    //内置函数:提示用户
    function notify(title = '操作成功', type = 'success', show = true) {
        console.log(title)
        const Toast = Swal.mixin({
            toast: true,
            position: 'top-end',
            showConfirmButton: false,
            timer: 2000,
            timerProgressBar: true,
            didOpen: (toast) => {
                toast.addEventListener('mouseenter', Swal.stopTimer)
                toast.addEventListener('mouseleave', Swal.resumeTimer)
            }
        })
        if (show)
            Toast.fire({
                icon: type,
                title: title
            })
        return Toast
    }
    // 配置网站就读取配置到网站上,1秒保存一次
    if(location.href.indexOf('51coolplay.cc')!= -1){
        read51Config()
        setInterval(()=>{ save51Config() },1000)
    }
    // 应用网站就把配置运行好
    if(location.href.indexOf('qidian.com')!= -1){
        readConfigOpen()
    }
    GM_registerMenuCommand('⚙️打开设置', ()=>{GM_openInTab('https://51coolplay.cc/service/book/settings.php', {active: !0})})
    GM_registerMenuCommand('♻️重置设置', ()=>{GM_deleteValue('config');notify('重置成功')})
})();