Skip to content

Commit fd106c2

Browse files
committed
chore: 🔖 Release 10.11.0
1 parent 8955767 commit fd106c2

File tree

5 files changed

+395
-129
lines changed

5 files changed

+395
-129
lines changed

ComicRead-AdGuard.user.js

Lines changed: 187 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// ==UserScript==
22
// @name ComicRead
33
// @namespace ComicRead
4-
// @version 10.10.2
5-
// @description 为漫画站增加双页阅读、翻译等优化体验的增强功能。百合会(记录阅读历史、自动签到等)、百合会新站、动漫之家(解锁隐藏漫画)、E-Hentai(关联 nhentai、快捷收藏、标签染色、识别广告页等)、nhentai(彻底屏蔽漫画、无限滚动)、Yurifans(自动签到)、拷贝漫画(copymanga)(显示最后阅读记录、解锁隐藏漫画)、PonpomuYuri、再漫画、明日方舟泰拉记事社、禁漫天堂、漫画柜(manhuagui)、漫画DB(manhuadb)、动漫屋(dm5)、绅士漫画(wnacg)、mangabz、komiic、MangaDex、無限動漫、新新漫画、熱辣漫畫、hitomi、SchaleNetwork、kemono、nekohouse、welovemanga
4+
// @version 10.11.0
5+
// @description 为漫画站增加双页阅读、翻译等优化体验的增强功能。百合会(记录阅读历史、自动签到等)、百合会新站、动漫之家(解锁隐藏漫画)、E-Hentai(关联 nhentai、快捷收藏、标签染色、识别广告页等)、nhentai(彻底屏蔽漫画、无限滚动)、Yurifans(自动签到)、拷贝漫画(copymanga)(显示最后阅读记录、解锁隐藏漫画)、PonpomuYuri、再漫画、明日方舟泰拉记事社、禁漫天堂、漫画柜(manhuagui)、漫画DB(manhuadb)、动漫屋(dm5)、绅士漫画(wnacg)、mangabz、komiic、MangaDex、NoyAcg、無限動漫、新新漫画、熱辣漫畫、hitomi、SchaleNetwork、kemono、nekohouse、welovemanga
66
// @description:en Add enhanced features to the comic site for optimized experience, including dual-page reading and translation. E-Hentai (Associate nhentai, Quick favorite, Colorize tags, Floating tag list, etc.) | nhentai (Totally block comics, Auto page turning) | hitomi | Anchira | kemono | nekohouse | welovemanga.
77
// @description:ru Добавляет расширенные функции для удобства на сайт, такие как двухстраничный режим и перевод.
88
// @author hymbz
@@ -59,6 +59,7 @@
5959
// @match *://mangabz.com/*
6060
// @match *://komiic.com/*
6161
// @match *://mangadex.org/*
62+
// @match *://noy1.top/*
6263
// @match *://8.twobili.com/*
6364
// @match *://a.twobili.com/*
6465
// @match *://articles.onemoreplace.tw/*
@@ -1177,14 +1178,18 @@ const request = async (url, details, retryNum = 0, errorNum = 0) => {
11771178
};
11781179
}
11791180
if (typeof GM_xmlhttpRequest === 'undefined') throw new Error(helper.t('pwa.alert.userscript_not_installed'));
1181+
let targetUrl = url;
1182+
// https://github.com/hymbz/ComicReadScript/issues/195
1183+
// 在某些情况下 Tampermonkey 无法正确处理相对协议的 url
1184+
// 实际 finalUrl 会变成 \`///xxx.xxx\` 莫名多了一个斜杠
1185+
// 然而在修改代码发出正确的请求后,就再也无法复现了
1186+
// 不过以防万一还是在这里手动处理下
1187+
if (url.startsWith('//')) targetUrl = \`http:\${url}\`;
1188+
// stay 没法处理相对路径,也得转换一下
1189+
else if (url.startsWith('/')) targetUrl = \`\${window.location.origin}\${url}\`;
11801190
const res = await xmlHttpRequest({
11811191
method: 'GET',
1182-
// https://github.com/hymbz/ComicReadScript/issues/195
1183-
// 在某些情况下 Tampermonkey 无法正确处理相对协议的 url
1184-
// 实际 finalUrl 会变成 \`///xxx.xxx\` 莫名多了一个斜杠
1185-
// 然而在修改代码发出正确的请求后,就再也无法复现了
1186-
// 不过以防万一还是在这里手动处理下
1187-
url: url.startsWith('//') ? \`http:\${url}\` : url,
1192+
url: targetUrl,
11881193
headers,
11891194
timeout: 1000 * 10,
11901195
...details
@@ -1193,6 +1198,13 @@ const request = async (url, details, retryNum = 0, errorNum = 0) => {
11931198
helper.log.error(errorText, res);
11941199
throw new Error(errorText);
11951200
}
1201+
1202+
// stay 好像没有正确处理 json,只能再单独判断处理一下
1203+
if (details?.responseType === 'json' && (typeof res.response !== 'object' || Object.keys(res.response).length === 0)) {
1204+
try {
1205+
Reflect.set(res, 'response', JSON.parse(res.responseText));
1206+
} catch {}
1207+
}
11961208
return res;
11971209
} catch (error) {
11981210
if (errorNum >= retryNum) {
@@ -1944,6 +1956,12 @@ const handleDragAnima$1 = () => {
19441956
animationId$2 = requestAnimationFrame(handleDragAnima$1);
19451957
};
19461958

1959+
/** 一段时间没有移动后应该将速率归零 */
1960+
const resetVelocity = helper.debounce(() => {
1961+
velocity.x = 0;
1962+
velocity.y = 0;
1963+
}, 200);
1964+
19471965
/** 是否正在双指捏合缩放中 */
19481966
let pinchZoom = false;
19491967

@@ -1968,10 +1986,13 @@ const handleZoomDrag = ({
19681986
mouse.x += x - lx;
19691987
mouse.y += y - ly;
19701988
if (animationId$2 === null) animationId$2 = requestAnimationFrame(handleDragAnima$1);
1989+
resetVelocity();
19711990
break;
19721991
}
19731992
case 'up':
19741993
{
1994+
resetVelocity.clear();
1995+
19751996
// 当双指捏合结束,一个手指抬起时,将剩余的指针当作刚点击来处理
19761997
if (pinchZoom) {
19771998
pinchZoom = false;
@@ -3987,6 +4008,7 @@ const ComicImgFlow = () => {
39874008
return (() => {
39884009
var _el$ = web.template(\`<div tabindex=-1><div tabindex=-1>\`)(),
39894010
_el$2 = _el$.firstChild;
4011+
_el$.addEventListener("transitionend", handleTransitionEnd);
39904012
var _ref$ = bindRef('mangaBox');
39914013
typeof _ref$ === "function" && web.use(_ref$, _el$);
39924014
_el$2.addEventListener("transitionend", handleTransitionEnd);
@@ -8666,7 +8688,7 @@ const handleVersionUpdate = async () => {
86668688
_el$.firstChild;
86678689
web.insert(_el$, () => GM.info.script.version, null);
86688690
return _el$;
8669-
})(), web.template(\`<h3>修复\`)(), web.template(\`<ul><li>修复部分手机浏览器在禁漫天堂等网站上无法正常显示图片的 bug\`)(), web.createComponent(VersionTip, {
8691+
})(), web.template(\`<h3>新增\`)(), web.template(\`<ul><li>支持 NoyAcg\`)(), web.template(\`<h3>修复\`)(), web.template(\`<ul><li><p>修复放大后拖拽不跟手的 bug </p></li><li><p>修复拷贝漫画解锁隐藏漫画不支持移动端的 bug\`)(), web.createComponent(VersionTip, {
86708692
v1: version,
86718693
v2: '10.8.0',
86728694
get children() {
@@ -11843,7 +11865,7 @@ const handleLastChapter = comicName => {
1184311865
};
1184411866

1184511867
// 生成目录
11846-
const buildChapters = async (comicName, rootDom) => {
11868+
const buildChapters = async (comicName, isMobile) => {
1184711869
// 拷贝有些漫画虽然可以通过 api 获取到数据,但网页上的目录被隐藏了
1184811870
// 举例:https://mangacopy.com/comic/yueguangxiadeyishijiezhilv
1184911871

@@ -11854,7 +11876,8 @@ const buildChapters = async (comicName, rootDom) => {
1185411876
} = await main.request(`/comicdetail/${comicName}/chapters`, {
1185511877
responseType: 'json',
1185611878
errorText: '加載漫畫目錄失敗',
11857-
headers
11879+
headers,
11880+
fetch: false
1185811881
});
1185911882
// 解码 api 返回的数据
1186011883
const decryptData = async (cipher, key, iv) => {
@@ -11879,89 +11902,154 @@ const buildChapters = async (comicName, rootDom) => {
1187911902
id
1188011903
}) => [id, []]));
1188111904
for (const chapter of props.chapters) chapters[chapter.type].push(chapter);
11905+
if (isMobile) {
11906+
// 删掉占位置的分隔线
11907+
for (const dom of helper.querySelectorAll('.van-divider')) dom.remove();
11908+
return (() => {
11909+
var _el$ = web.template(`<div class="detailsTextContentTabs van-tabs van-tabs--line">`)();
11910+
web.insert(_el$, web.createComponent(solidJs.For, {
11911+
each: type,
11912+
children: ({
11913+
id,
11914+
name
11915+
}) => web.createComponent(solidJs.Show, {
11916+
get when() {
11917+
return chapters[id].length;
11918+
},
11919+
get children() {
11920+
return [(() => {
11921+
var _el$2 = web.template(`<div class=van-tabs__wrap><div role=tablist class="van-tabs__nav van-tabs__nav--line"><div role=tab class="van-tab van-tab--active"><span class="van-tab__text van-tab__text--ellipsis"><span></span></span></div><div class=van-tabs__line>`)(),
11922+
_el$3 = _el$2.firstChild,
11923+
_el$4 = _el$3.firstChild,
11924+
_el$5 = _el$4.firstChild,
11925+
_el$6 = _el$5.firstChild,
11926+
_el$7 = _el$4.nextSibling;
11927+
_el$3.style.setProperty("background", "transparent");
11928+
web.insert(_el$6, name);
11929+
_el$7.style.setProperty("width", "0.24rem");
11930+
_el$7.style.setProperty("transform", "translateX(187.5px) translateX(-50%)");
11931+
_el$7.style.setProperty("transition-duration", "0.3s");
11932+
return _el$2;
11933+
})(), (() => {
11934+
var _el$8 = web.template(`<div class=van-tab__pane><div class="chapterList van-grid">`)(),
11935+
_el$9 = _el$8.firstChild;
11936+
_el$9.style.setProperty("padding-left", "0.24rem");
11937+
web.insert(_el$9, web.createComponent(solidJs.For, {
11938+
get each() {
11939+
return chapters[id];
11940+
},
11941+
children: chapter => (() => {
11942+
var _el$10 = web.template(`<div class="chapterItem oneLines van-grid-item"><a class="van-grid-item__content van-grid-item__content--center"><span class=van-grid-item__text>`)(),
11943+
_el$11 = _el$10.firstChild,
11944+
_el$12 = _el$11.firstChild;
11945+
_el$10.style.setProperty("flex-basis", "25%");
11946+
_el$10.style.setProperty("padding-right", "0.24rem");
11947+
_el$10.style.setProperty("margin-top", "0.24rem");
11948+
web.insert(_el$12, () => chapter.name);
11949+
web.effect(_p$ => {
11950+
var _v$ = !!(props.last_chapter.uuid === chapter.id),
11951+
_v$2 = `/comic/${comicName}/chapter/${chapter.id}`;
11952+
_v$ !== _p$.e && _el$10.classList.toggle("red", _p$.e = _v$);
11953+
_v$2 !== _p$.t && web.setAttribute(_el$11, "href", _p$.t = _v$2);
11954+
return _p$;
11955+
}, {
11956+
e: undefined,
11957+
t: undefined
11958+
});
11959+
return _el$10;
11960+
})()
11961+
}));
11962+
return _el$8;
11963+
})()];
11964+
}
11965+
})
11966+
}));
11967+
return _el$;
11968+
})();
11969+
}
1188211970
return [(() => {
11883-
var _el$ = web.template(`<span>`)();
11884-
web.insert(_el$, () => props.name);
11885-
return _el$;
11971+
var _el$13 = web.template(`<span>`)();
11972+
web.insert(_el$13, () => props.name);
11973+
return _el$13;
1188611974
})(), (() => {
11887-
var _el$2 = web.template(`<div class=table-default><div class=table-default-title><ul class="nav nav-tabs"role=tablist></ul><div class=table-default-right><span>更新內容:</span><a target=_blank></a><span>更新時間:</span><span></span></div></div><div class=table-default-box><div class=tab-content>`)(),
11888-
_el$3 = _el$2.firstChild,
11889-
_el$4 = _el$3.firstChild,
11890-
_el$5 = _el$4.nextSibling,
11891-
_el$6 = _el$5.firstChild,
11892-
_el$7 = _el$6.nextSibling,
11893-
_el$8 = _el$7.nextSibling,
11894-
_el$9 = _el$8.nextSibling,
11895-
_el$10 = _el$3.nextSibling,
11896-
_el$11 = _el$10.firstChild;
11897-
web.insert(_el$4, web.createComponent(solidJs.For, {
11975+
var _el$14 = web.template(`<div class=table-default><div class=table-default-title><ul class="nav nav-tabs"role=tablist></ul><div class=table-default-right><span>更新內容:</span><a target=_blank></a><span>更新時間:</span><span></span></div></div><div class=table-default-box><div class=tab-content>`)(),
11976+
_el$15 = _el$14.firstChild,
11977+
_el$16 = _el$15.firstChild,
11978+
_el$17 = _el$16.nextSibling,
11979+
_el$18 = _el$17.firstChild,
11980+
_el$19 = _el$18.nextSibling,
11981+
_el$20 = _el$19.nextSibling,
11982+
_el$21 = _el$20.nextSibling,
11983+
_el$22 = _el$15.nextSibling,
11984+
_el$23 = _el$22.firstChild;
11985+
web.insert(_el$16, web.createComponent(solidJs.For, {
1189811986
each: type,
1189911987
children: ({
1190011988
id,
1190111989
name
1190211990
}) => (() => {
11903-
var _el$12 = web.template(`<li class=nav-item><a class=nav-link data-toggle=tab role=tab aria-selected=false>`)(),
11904-
_el$13 = _el$12.firstChild;
11905-
web.insert(_el$13, name);
11991+
var _el$24 = web.template(`<li class=nav-item><a class=nav-link data-toggle=tab role=tab aria-selected=false>`)(),
11992+
_el$25 = _el$24.firstChild;
11993+
web.insert(_el$25, name);
1190611994
web.effect(_p$ => {
11907-
var _v$ = !!(chapters[id].length === 0),
11908-
_v$2 = `#${props.path_word}${name}`;
11909-
_v$ !== _p$.e && _el$13.classList.toggle("disabled", _p$.e = _v$);
11910-
_v$2 !== _p$.t && web.setAttribute(_el$13, "href", _p$.t = _v$2);
11995+
var _v$3 = !!(chapters[id].length === 0),
11996+
_v$4 = `#${props.path_word}${name}`;
11997+
_v$3 !== _p$.e && _el$25.classList.toggle("disabled", _p$.e = _v$3);
11998+
_v$4 !== _p$.t && web.setAttribute(_el$25, "href", _p$.t = _v$4);
1191111999
return _p$;
1191212000
}, {
1191312001
e: undefined,
1191412002
t: undefined
1191512003
});
11916-
return _el$12;
12004+
return _el$24;
1191712005
})()
1191812006
}));
11919-
web.insert(_el$7, () => props.last_chapter.name);
11920-
web.insert(_el$9, () => props.last_chapter.datetime_created);
11921-
web.insert(_el$11, web.createComponent(solidJs.For, {
12007+
web.insert(_el$19, () => props.last_chapter.name);
12008+
web.insert(_el$21, () => props.last_chapter.datetime_created);
12009+
web.insert(_el$23, web.createComponent(solidJs.For, {
1192212010
each: type,
1192312011
children: ({
1192412012
id,
1192512013
name
1192612014
}) => (() => {
11927-
var _el$14 = web.template(`<div role=tabpanel class="tab-pane fade"><ul>`)(),
11928-
_el$15 = _el$14.firstChild;
11929-
web.insert(_el$15, web.createComponent(solidJs.For, {
12015+
var _el$26 = web.template(`<div role=tabpanel class="tab-pane fade"><ul>`)(),
12016+
_el$27 = _el$26.firstChild;
12017+
web.insert(_el$27, web.createComponent(solidJs.For, {
1193012018
get each() {
1193112019
return chapters[id];
1193212020
},
1193312021
children: chapter => (() => {
11934-
var _el$16 = web.template(`<a target=_blank><li>`)(),
11935-
_el$17 = _el$16.firstChild;
11936-
_el$16.style.setProperty("display", "block");
11937-
web.insert(_el$17, () => chapter.name);
12022+
var _el$28 = web.template(`<a target=_blank><li>`)(),
12023+
_el$29 = _el$28.firstChild;
12024+
_el$28.style.setProperty("display", "block");
12025+
web.insert(_el$29, () => chapter.name);
1193812026
web.effect(_p$ => {
11939-
var _v$3 = `/comic/${comicName}/chapter/${chapter.id}`,
11940-
_v$4 = chapter.name;
11941-
_v$3 !== _p$.e && web.setAttribute(_el$16, "href", _p$.e = _v$3);
11942-
_v$4 !== _p$.t && web.setAttribute(_el$16, "title", _p$.t = _v$4);
12027+
var _v$5 = `/comic/${comicName}/chapter/${chapter.id}`,
12028+
_v$6 = chapter.name;
12029+
_v$5 !== _p$.e && web.setAttribute(_el$28, "href", _p$.e = _v$5);
12030+
_v$6 !== _p$.t && web.setAttribute(_el$28, "title", _p$.t = _v$6);
1194312031
return _p$;
1194412032
}, {
1194512033
e: undefined,
1194612034
t: undefined
1194712035
});
11948-
return _el$16;
12036+
return _el$28;
1194912037
})()
1195012038
}));
11951-
web.effect(() => web.setAttribute(_el$14, "id", `${props.path_word}${name}`));
11952-
return _el$14;
12039+
web.effect(() => web.setAttribute(_el$26, "id", `${props.path_word}${name}`));
12040+
return _el$26;
1195312041
})()
1195412042
}));
11955-
web.effect(() => web.setAttribute(_el$7, "href", `/comic/${comicName}/chapter/${props.last_chapter.comic_id}`));
11956-
return _el$2;
12043+
web.effect(() => web.setAttribute(_el$19, "href", `/comic/${comicName}/chapter/${props.last_chapter.comic_id}`));
12044+
return _el$14;
1195712045
})()];
1195812046
};
1195912047
web.render(() => web.createComponent(solidJs.For, {
1196012048
get each() {
1196112049
return Object.values(groups);
1196212050
},
1196312051
children: Group
11964-
}), rootDom);
12052+
}), isMobile ? helper.querySelector('.detailsTextContent') : helper.querySelector('.upLoop'));
1196512053

1196612054
// 点击每个分组下第一个激活的标签
1196712055
for (const group of helper.querySelectorAll('.upLoop .table-default-title')) group.querySelector('.nav-link:not(.disabled)')?.click();
@@ -12037,10 +12125,31 @@ const buildChapters = async (comicName, rootDom) => {
1203712125
if (!id && window.location.href.includes('/comic/')) {
1203812126
comicName = window.location.href.split('/comic/')[1];
1203912127
if (!comicName) return;
12128+
let isHidden = false;
12129+
const isMobile = window.location.href.includes('/h5/');
12130+
if (isMobile) {
12131+
// 等到加载提示框消失
12132+
await helper.wait(() => helper.querySelector('.van-toast__text')?.parentElement?.style.display === 'none');
12133+
// 再等一秒看有没有屏蔽提示
12134+
if (await helper.wait(() => helper.querySelector('.isBan')?.textContent?.includes('不提供閱覽'), 1000)) {
12135+
isHidden = true;
12136+
}
12137+
} else {
12138+
isHidden =
12139+
// 先检查有没有屏蔽提示
12140+
Boolean(helper.querySelector('.wargin')?.textContent?.includes('不提供閱覽')) ||
12141+
// 再等一秒看目录有没有加载出来
12142+
!(await helper.wait(() => helper.querySelector('.upLoop .table-default-title'), 1000));
12143+
}
1204012144

12041-
// 稍等看有没有目录加载出来,没有就自己生成
12042-
if (!(await helper.wait(() => helper.querySelector('.upLoop .table-default-title'), 1000))) await buildChapters(comicName, helper.querySelector('.upLoop'));
12043-
if (token) handleLastChapter(comicName);
12145+
// 如果漫画被隐藏了,就自己生成目录
12146+
if (isHidden) {
12147+
// 给屏蔽提示加个删除线
12148+
const tip = helper.querySelector('.isBan, .wargin');
12149+
if (tip) tip.style.textDecoration = 'line-through';
12150+
await buildChapters(comicName, isMobile);
12151+
}
12152+
if (!isMobile && token) handleLastChapter(comicName);
1204412153
}
1204512154
})();
1204612155

@@ -12106,13 +12215,7 @@ const buildChapters = async (comicName, rootDom) => {
1210612215
}
1210712216

1210812217
// #[禁漫天堂](https://18comic.vip)
12109-
case 'jmcomic.me':
12110-
case 'jmcomic1.me':
12111-
case 'jmcomic-zzz.one':
12112-
case '18comic-dwo.cc':
12113-
case '18comic.org':
12114-
case '18comic.vip':
12115-
{
12218+
{
1211612219
const main = require('main');
1211712220
const helper = require('helper');
1211812221

@@ -12482,6 +12585,27 @@ const helper = require('helper');
1248212585
break;
1248312586
}
1248412587

12588+
// #[NoyAcg](https://noy1.top)
12589+
case 'noy1.top':
12590+
{
12591+
options = {
12592+
name: 'NoyAcg',
12593+
async getImgList() {
12594+
const [,, id] = window.location.hash.split('/');
12595+
12596+
// 随便拿一个图片来获取 cdn url
12597+
const img = await helper.wait(() => helper.querySelector('.lazy-load-image-background img'));
12598+
const cdn = img.src.split(id)[0];
12599+
const imgNum = await helper.wait(() => helper.querySelectorAll('.lazy-load-image-background').length);
12600+
return helper.range(imgNum, i => `${cdn}${id}/${i + 1}.webp`);
12601+
},
12602+
SPA: {
12603+
isMangaPage: () => window.location.hash.startsWith('#/read/')
12604+
}
12605+
};
12606+
break;
12607+
}
12608+
1248512609
// #[無限動漫](https://www.comicabc.com)
1248612610
case '8.twobili.com':
1248712611
case 'a.twobili.com':

0 commit comments

Comments
 (0)