// ==UserScript==
// @name 番茄小说阅读辅助器
// @namespace http://tampermonkey.net/
// @version 1.530
// @description 可以下载番茄小说内容,记录阅读位置(滚动位置),可以自动滚动,超好用!
// @author twjx
// @match *://fanqienovel.com/*
// @require https://cdn.jsdelivr.net/npm/lil-gui@0.16
// @require https://update.greasyfork.org/scripts/522780/1514721/dialog.js
// @require https://update.greasyfork.org/scripts/521360/1514728/unicode1.js
// @license GNU AGPLv3
// @resource swalStyle https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.min.css
// @icon data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE4Ljg3MjcgMEg1LjEyNzI3QzIuMjkwOTEgMCAwIDIuMjkwOTEgMCA1LjEyNzI3VjE4Ljg3MjdDMCAyMS43MDkxIDIuMjkwOTEgMjQgNS4xMjcyNyAyNEgxOC44NzI3QzIxLjcwOTEgMjQgMjQgMjEuNzA5MSAyNCAxOC44NzI3VjUuMTI3MjdDMjQgMi4yOTA5MSAyMS43MDkxIDAgMTguODcyNyAwWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjEyNzI3IDBIMTguODcyN0MyMS43MDkxIDAgMjQgMi4yOTA5MSAyNCA1LjEyNzI3VjE4Ljg3MjdDMjQgMjEuNzA5MSAyMS43MDkxIDI0IDE4Ljg3MjcgMjRINS4xMjcyN0MyLjI5MDkxIDI0IDAgMjEuNzA5MSAwIDE4Ljg3MjdWNS4xMjcyN0MwIDIuMjkwOTEgMi4yOTA5MSAwIDUuMTI3MjcgMFpNMjMuNDc1NyA1LjEyNzI3QzIzLjQ3NTcgMi41OTYzNiAyMS40MDMgMC41MjM2MzYgMTguODcyIDAuNTIzNjM2SDUuMTI2NTlDMi41OTU2OCAwLjUyMzYzNiAwLjUyMjk0OSAyLjU5NjM2IDAuNTIyOTQ5IDUuMTI3MjdWMTguODcyN0MwLjUyMjk0OSAyMS40MDM2IDIuNTk1NjggMjMuNDc2NCA1LjEyNjU5IDIzLjQ3NjRIMTguODcyQzIxLjQwMyAyMy40NzY0IDIzLjQ3NTcgMjEuNDAzNiAyMy40NzU3IDE4Ljg3MjdWNS4xMjcyN1oiIGZpbGw9IiNFNkU2RTYiLz4KPHBhdGggZD0iTTE1LjA3NjIgMFY1LjA0TDE3LjAxOCAzLjkyNzI3TDE4Ljk1OTggNS4wNFYwSDE1LjA3NjJaIiBmaWxsPSIjRUU1NTI4Ii8+CjxwYXRoIGQ9Ik0yNCAxMy45NjM2QzIxLjI1MDkgMTAuNjkwOCAxNi45MDkxIDguNTc0NDYgMTIuMDIxOCA4LjU3NDQ2QzcuMDkwOTEgOC41NzQ0NiAyLjcyNzI3IDEwLjcxMjYgMCAxNC4wMjlWMTguODcyNkMwIDIxLjcwOSAyLjI5MDkxIDIzLjk5OTkgNS4xMjcyNyAyMy45OTk5SDE4Ljg3MjdDMjEuNzA5MSAyMy45OTk5IDI0IDIxLjcwOSAyNCAxOC44NzI2VjEzLjk2MzZaIiBmaWxsPSJ1cmwoI3BhaW50MF9yYWRpYWxfNjA3XzEyNTA1KSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEyLjc4NTYgMTMuODk4MkMxMi43NjM4IDEzLjAwMzcgMTIuNDE0NyAxMi41ODkxIDEyLjAwMDIgMTIuNTg5MUMxMS41NjM4IDEyLjYxMDkgMTEuMjM2NSAxMy4wMjU1IDExLjI1ODQgMTMuODk4MkMxMS4yNTg0IDE0LjgxNDYgMTIuMDQzOCAxNS44NjE4IDEyLjA0MzggMTUuODYxOEMxMi4wNDM4IDE1Ljg2MTggMTIuNzg1NiAxNC44MTQ2IDEyLjc4NTYgMTMuODk4MlpNNi4zNDk0NiAxOC42NzYzQzcuMjY1ODMgMTguNjc2MyA4LjMxMzEgMTkuNDE4MSA4LjMxMzEgMTkuNDE4MUM4LjMxMzEgMTkuNDE4MSA3LjI2NTgzIDIwLjIwMzUgNi4zNDk0NiAyMC4yMDM1QzUuNDMzMSAyMC4yMDM1IDUuMDE4NTUgMTkuODc2MyA1LjAxODU1IDE5LjQzOTlDNS4wNDAzNyAxOS4wNDcyIDUuNDU0OTIgMTguNjk4MSA2LjM0OTQ2IDE4LjY3NjNaTTE4Ljk2MSAxOS40NjE5QzE4Ljk2MSAxOS44NzY0IDE4LjU0NjUgMjAuMjI1NSAxNy42MzAxIDIwLjIyNTVDMTYuNzEzOCAyMC4yMjU1IDE1LjY2NjUgMTkuNDQwMSAxNS42NjY1IDE5LjQ0MDFDMTUuNjY2NSAxOS40NDAxIDE2LjczNTYgMTguNjc2NCAxNy42MzAxIDE4LjY5ODJDMTguNTQ2NSAxOC42OTgyIDE4Ljk2MSAxOS4wMjU1IDE4Ljk2MSAxOS40NjE5Wk0xNy4zMDIyIDE0Ljg1ODFDMTcuNjA3NiAxNS4xNjM1IDE3LjU0MjIgMTUuNjg3MiAxNi44ODc2IDE2LjM0MTdDMTYuMjMzMSAxNi45NzQ1IDE0Ljk0NTggMTcuMTcwOCAxNC45NDU4IDE3LjE3MDhDMTQuOTQ1OCAxNy4xNzA4IDE1LjE2NCAxNS44ODM1IDE1LjgxODUgMTUuMjUwOEMxNi40NzMxIDE0LjU5NjMgMTcuMDE4NSAxNC41NTI2IDE3LjMwMjIgMTQuODU4MVpNOS4wNTU2NCAxNy4xNDkyQzkuMDU1NjQgMTcuMTQ5MiA4LjgzNzQ2IDE1Ljg2MiA4LjE4MjkxIDE1LjIyOTJDNy41MjgzNiAxNC41OTY1IDYuOTgyOTEgMTQuNTUyOSA2LjY5OTI3IDE0LjgzNjVDNi40MTU2NCAxNS4xNDIgNi40NTkyNyAxNS42ODc0IDcuMTEzODIgMTYuMzIwMUM3Ljc2ODM2IDE2Ljk1MjkgOS4wNTU2NCAxNy4xNDkyIDkuMDU1NjQgMTcuMTQ5MloiIGZpbGw9IndoaXRlIi8+CjxkZWZzPgo8cmFkaWFsR3JhZGllbnQgaWQ9InBhaW50MF9yYWRpYWxfNjA3XzEyNTA1IiBjeD0iMCIgY3k9IjAiIHI9IjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLjA5ODkgMjQuMjEyKSBzY2FsZSgxNC41OTg0IDkuMzgyNzcpIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0NDMDUwMCIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRjVGMDAiLz4KPC9yYWRpYWxHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K
// @grant none
// ==/UserScript==
(function() {
'use strict';
window.data=''
window.num=0
window.alldata=[]
window.onstop=false
window.movep=[]
window.img=[]
window.thedata
window.unicode_data()
window.sleep=async function(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
function xml(type, src,idata,num,num1,aa) {
const xhr = new XMLHttpRequest();
xhr.open(type, src);
xhr.overrideMimeType('text/plain; charset=utf-8');
xhr.onload = function () {
if (xhr.status === 200) {
const responseText = xhr.responseText;
let content = responseText.split('content noselect"><div>')[1]
.split('</div><p></p>')[0]
.replaceAll('<p>', '')
.replaceAll('</p>', '\n');
var decoded = decode(content);
var text=find_img(decoded)
if(text!==false){
var f=decoded.split('<div data-fanqie-type="image" ')
var textd=''
for(let x of f){
if(x.startsWith('source')){
textd+='\n此处有一张图片已去除,请于下载配套中查看\n名称:'+x.split('1">')[2].split('\n')[0]+'\n'+x.split('</div>')[1]
}else textd+=x
}
for(let x=0;x<text.length;x++){
img.push({
chapter:responseText.split('<title>')[1].split('在线免费阅读_番茄小说官网<')[0].split(' ')[0].split('第')[1].replace('章',''),
chapter1:num1,
chapter2:num,
name:responseText.split('<title>')[1].split('在线免费阅读_番茄小说官网<')[0].split(' ')[1],
src:text[x][1],
title:text[x][0],
})
}
decoded=textd
}
idata.data.push({
chapter:responseText.split('<title>')[1].split('在线免费阅读_番茄小说官网<')[0].split(' ')[0].split('第')[1].replace('章',''),
chapter1:num1,
chapter2:num,
name:responseText.split('<title>')[1].split('在线免费阅读_番茄小说官网<')[0].split(' ')[1],
data:decoded,
})
if(decoded==undefined){onstop=true;window.d={a:responseText,b:decoded,c:text,d:textd}}
console.log(aa+' 机改1:'+num1+' 机改2:'+num+'下载完成')
}
};
xhr.send();
}
function decode(content) {
var newdata = '';
for (let x of content) {
if (String(x).charCodeAt(0) in unicode_data == true) {
newdata += unicode_data[String(x).charCodeAt(0)];
} else {
newdata += String(x);
}
}
return newdata;
}
async function dispose(children,type){
if(onstop==true)return;
var jdata=children.children[0].innerHTML.split('<span class="volume-dot"></span>')
var num=1
alldata.push({
name:jdata[0],
volume:jdata[0],
allchapter:jdata[1],
data:[]})
console.log('卷创建完毕')
for(let x of children.children[1].children){
if(onstop==true)return;
xml('GET',x.children[0].href,alldata[alldata.length-1],num,num1,x.innerText.split(' ')[0])
num+=1
num1+=1
await sleep(Number(document.querySelectorAll('.widget')[2].children[0].value))//50毫秒一下最好不要,卡爆
}
}
function find_img(text){
if(text.includes('<div data-fanqie-type="image" ')){
var returntext=[]
var texta=text.split('<div data-fanqie-type="image" ')
for(let x of texta){
if(x.startsWith('source="')){
var textb=x.split('Desc" group')
returntext[texta.indexOf(x)-1]=[textb[1].split('\n')[0].split('>')[1],textb[0].split('<img src="')[1].split('" width="')[0]]
}
}
return returntext
}else return false
}
function download(name, text,type) {
var dld = document.createElement('a');
dld.setAttribute('href', 'data:text/plain;charset=utf-8,'+encodeURIComponent(text));
dld.setAttribute('download', name);
dld.click();
}
async function downloadd(type){
data=''
console.log('正在排序...')
window.d=0
for(let x=0;x<alldata.length;x++){
data+=alldata[x].name+' '+alldata[x].allchapter+'\n'
for(let x1=0;x1<alldata[x].data.length;x1++){
d+=1
for(let x2 of alldata[x].data){
if(x2.chapter1==d){
data+='第'+[x2.chapter,x2.chapter1,x2.chapter2][type]+'章 '+x2.name+'\n'+x2.data
}
}
}
}
download(window.__INITIAL_STATE__.page.bookName,window.__INITIAL_STATE__.page.bookName+"\n此文件由番茄小说阅读辅助器下载https://greasyfork.org/zh-CN/scripts/521377-番茄小说阅读辅助器\n请支持正版番茄小说\n作者:"+window.__INITIAL_STATE__.page.author+'\n'+data,'text')
alert('下载完成')
/*var imgtext=''
for(let x of img){
imgtext+='图片名称'+x.title+' 来自章节 第'+[x.chapter,x.chapter1,x.chapter2][type]+'章 '+x.name+'\n'
download(x.title,x.src,'img')
}*/
await sleep(100)
//download(window.__INITIAL_STATE__.page.bookName,window.__INITIAL_STATE__.page.bookName+' 图片来源',imgtext,'text')
gui.domElement.children[1].children[0].children[1].children[2].remove()
await sleep(1000)
data=''
alldata=[]
}
function move(){//移动模块
var guid=gui.domElement
gui.domElement.children[0].onmousedown=function(e) {
if(guid.style.left==''){
movep=[e.clientX-(window.innerWidth-275),e.clientY-0]//首次移动
}else{
movep=[e.clientX-Number(guid.style.left.replace('px','')),e.clientY-Number(guid.style.top.replace('px',''))]
}
window.onmove=true
}
document.onmouseup=function(e) {
if(Number(guid.style.left.replace('px',''))<0)guid.style.left='0px';
if(Number(guid.style.top.replace('px',''))<0)guid.style.top='0px';
if(Number(gui.domElement.style.left.replace('px',''))+260>=windowWidth){
gui.domElement.style.left=(windowWidth-260)+'px'
}
movep=[]
window.onmove=false
}
document.onmousemove=function(e){
if(window.onmove==true){
guid.style.top=e.clientY-movep[1]+'px';
guid.style.left=e.clientX-movep[0]+'px'
}
}
guid.onmouseover=function(){
if(!guid.children[0].innerText.includes('右'))guid.children[0].innerText+=' (右键可移动)';
}
guid.onmouseout=function(){
guid.children[0].innerText='番茄阅读辅助器'
}
}
window.reader={
record:async function(){//记录阅读位置
window.time=String(new Date).split(' ')
var datax=thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2])
if(datax.length==1){
//回忆了以前的知识
if(thescroll.scrollTop==0){await sleep(500)}
Object.assign(thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2])[0],{
date:{
year:time[3],
month:time[2],
time:time[4],
area:time[6],
},
chapterName:document.querySelector('.muye-reader-title').innerText,
chapterid:location.pathname.split('/')[2],
scrolltop:thescroll.scrollTop,
scrollHeight:thescroll.scrollHeight,
})
}else if(datax.length==0){
thedata.read.read_record.push({
date:{
year:time[3],
month:time[2],
time:time[4],
area:time[6],
},
bookName:document.querySelector('.muye-reader-nav-title').innerText,
chapterName:document.querySelector('.muye-reader-title').innerText,
chapterid:location.pathname.split('/')[2],
scrolltop:thescroll.scrollTop,
scrollHeight:thescroll.scrollHeight,
})
}
},
onload:function(){//加载阅读位置
if(thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2]).length==1){
thescroll.scrollTop=thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2])[0].scrolltop
console.log('记录加载')
}
},
loadrecord:function(){//加载目录记录
for(let x of document.querySelector('.reader-catalog-chapters').children){
for(let xx of x.children){
if(xx.className!=='volume-header'){
var xxx=thedata.read.read_record.filter(e=>e.chapterid==xx.children[0].attributes[0].value)
if(xxx.length==1){
xx.children[0].innerHTML+='<p> 已看'+Math.round((xxx[0].scrolltop/xxx[0].scrollHeight)*100)+'%</p>'
}}
}
}
},
scroll:{
load:function(theparent){
this.scrollInterval;
this.scrollStatus = theparent.add({ status: '已停止' }, 'status').name('滚动状态');
this.scrollStatus.domElement.style.color = 'red';
this.scrollSpeed = theparent.add({ speed: 1 }, 'speed').name('滚动速度');
this.scrollSpeed.setValue(thedata.read.scroll_speed)
this.scrollSpeedsave = theparent.add({ speedsave: false }, 'speedsave').name('保存速度').onChange(function(value) {
if (value==true) {
thedata.read.scroll_speed=reader.scroll.scrollSpeed.getValue()
console.log('保存速度:'+thedata.read.scroll_speed)
fqxsydqdata.savedata()
}
});
this.stopButton = theparent.add(this, 'start').name('开始自动滚动');
},
autoScroll:function() {
if (thescroll.scrollTop >= thescroll.scrollHeight - thescroll.clientHeight) {
console.log('滚动以至底部')
window.reader.scroll.stopAutoScroll();
}else{
thescroll.scrollTop += Math.round(reader.scroll.scrollSpeed.getValue())
}
},
startAutoScroll:function() {
this.scrollInterval = setInterval(this.autoScroll, 200);
this.scrollStatus.setValue('进行中');
this.stopButton.name('停止自动滚动');
this.scrollStatus.domElement.style.color = 'green';
},
stopAutoScroll:function() {
clearInterval(this.scrollInterval);
this.scrollStatus.setValue('已停止');
this.stopButton.name('开始自动滚动');
this.scrollStatus.domElement.style.color = 'red';
},
"start":()=>{
var x=reader.scroll
if(x.scrollStatus.getValue()=='已停止'){
if(String(Number(x.scrollSpeed.getValue()))=='NaN'){
alert('滚动速度输入非数字')
return
}
if(x.scrollSpeed.getValue()>=1000){
alert('滚动速度输入过大\n如有需要请在脚本后台修改上限\n如有错误作者概不负责')
return
}
console.log('滚动速度:'+Math.round(x.scrollSpeed.getValue()))
x.startAutoScroll();
}else{
x.stopAutoScroll();
}
}
}
}
window.fqxsydqdata={
getdata:function(){
if(!localStorage.fqxsydq){
window.thedata={
name:'番茄阅读辅助器',
version:'1.520',
read:{
read_record:[],
last_read:{},
scroll_speed:1,
},
download:{
},
}
localStorage.fqxsydq=JSON.stringify(thedata)
}else{
window.thedata=JSON.parse(localStorage.fqxsydq)
if(thedata.version!=='1.520'){
window.thedata={
name:'番茄阅读辅助器',
version:'1.520',
read:{
read_record:thedata.read.read_record,
last_read:{},
scroll_speed:thedata.read.scroll_speed,
},
download:{
},
}
localStorage.fqxsydq=JSON.stringify(thedata)
alert('版本过低,数据格式已更新')
}
}
},
savedata:function(){
localStorage.fqxsydq=JSON.stringify(thedata)
},
}
window.q=function(){
alert('原版:下载原版章节\n机翻1:下载机翻1章节\n机翻2:下载机翻2章节\n机翻1效果如下\n第一卷\n第1章\n第2章\n......\n第二卷\n第100章...\n机翻2\n第一卷\n第1章\n第2章\n......\n第二卷\n第1章')
}
var main = {
"copybook" : async()=>{
data=''
img=[]
if(Number(document.querySelectorAll('.widget')[2].children[0].value)<60){
var b=confirm('小于60毫秒作者建议请一下后台\n开的时候玩手机就行了\n作者亲测50毫秒间隔下载也不会出错')
if(!b==true)return;
}
console.log('下载模式:'+document.querySelectorAll('.widget')[1].children[0].value)
var type=['原版','机改1','机改2'].indexOf(document.querySelectorAll('.widget')[1].children[0].value)
page1.add(main,'stop').name('暂停下载')
alert('请等待提示,现开始复制\n可通过控制台查看进度')
globalThis.a=document.querySelector('.page-directory-content')
globalThis.num1=1
for(let x of a.children){
if(onstop==true)return;
await dispose(x,'computer')
await sleep(150)
}
await downloadd(type)
},
"a":100,
"stop":async()=>{
onstop=true
alert('已暂停')
gui.domElement.children[1].children[0].children[1].children[2].innerText='已暂停'
await sleep(5000)
gui.domElement.children[1].children[0].children[1].children[2].remove()
},
"setting":1,
};
window.gui = new lil.GUI({ title: '番茄阅读辅助器' });
window.gui.domElement.style.userSelect = 'none';
move()
fqxsydqdata.getdata()
if(location.href.includes('force_mobile=1')){
alert('暂不支持手机排版的下载\n如使用电脑请保证长宽比例不低于1\n防止排版进入手机格式')
return
}
var page1
if(location.href.includes('/page/')){
page1 = gui.addFolder('复制')
page1.add(main,'copybook').name('复制本书全文 (仅支持电脑)')
page1.add(main,'setting',{'原版':1,'机改1':2,'机改2':3}).name('下载设置')
page1.add(main,"a").min(1).name('下载速度')
document.querySelectorAll('.controller')[1].innerHTML+='<div class="question">?</div>'
document.querySelector('.question').addEventListener('click',()=>{window.q()})
}
else if(location.href.includes('/reader/')){
window.thescroll=document.querySelector('.muye-reader')
reader.onload()
window.scrollhref=location.pathname
thescroll.onscroll=function(e){
if(scrollhref!==location.pathname){
reader.onload()
window.scrollhref=location.pathname
return
}
reader.record()
fqxsydqdata.savedata()
}
document.querySelectorAll('.reader-toolbar-item')[1].addEventListener('click',async()=>{
await sleep(1500)
reader.loadrecord()
})
page1 = gui.addFolder('阅读')
var page1_1 = page1.addFolder('滚动')
reader.scroll.load(page1_1)
}
})();