diff --git a/assets/radar-rules.js b/assets/radar-rules.js
index cc3690f48..48c8667bc 100644
--- a/assets/radar-rules.js
+++ b/assets/radar-rules.js
@@ -71,7 +71,6 @@
'ishuhui.com': { _name: '鼠绘漫画', www: [{ title: '鼠绘漫画', docs: 'https://docs.rsshub.app/anime.html#shu-hui-man-hua', source: '/comics/anime/:id', target: '/shuhui/comics/:id' }] },
'www.chicagotribune.com': { _name: 'Chicago Tribune', www: [{ title: 'Chicago Tribune', docs: 'https://docs.rsshub.app/traditional_media.html#chicago-tribune', source: '/' }] },
'haimaoba.com': { _name: '海猫吧', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#hai-mao-ba', source: '/catalog/:id', target: '/haimaoba/:id' }] },
- 'copymanga.com': { _name: '拷贝漫画', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#kao-bei-man-hua', source: '/comic/:id/', target: '/manhuagui/comic/:id/5' }] },
'pgyer.com': { _name: '蒲公英应用分发', www: [{ title: 'app更新', docs: 'https://docs.rsshub.app/program-update.html#pu-gong-ying-ying-yong-fen-fa', source: '/:app', target: '/pgyer/:app' }] },
'wineyun.com': { _name: '酒云网', www: [{ title: '最新商品', docs: 'https://docs.rsshub.app/other.html#jiu-yun-wang', source: ['/:category'], target: '/wineyun/:category' }] },
'epicgames.com': { _name: 'Epic Games', www: [{ title: '每周免费游戏', docs: 'https://docs.rsshub.app/game.html#epicgames-freegame', source: '/store/zh-CN/free-games', target: '/epicgames/freegames' }] },
diff --git a/docs/anime.md b/docs/anime.md
index e39f3f40f..3a75aa7ec 100644
--- a/docs/anime.md
+++ b/docs/anime.md
@@ -695,7 +695,7 @@ Sources
### 漫画更新
-
+
## 漫画 DB
diff --git a/lib/router.js b/lib/router.js
index bfc2adcf1..55e8ec8f7 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1001,10 +1001,10 @@ router.get('/tencentvideo/playlist/:id', lazyloadRouteHandler('./routes/tencent/
// router.get('/twmanhuagui/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/twmanhuagui/comic'));
// 拷贝漫画
-router.get('/copymanga/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/copymanga/comic'));
+// router.get('/copymanga/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/copymanga/comic'));
// 拷贝漫画
-router.get('/copymanga/comic/:id', lazyloadRouteHandler('./routes/copymanga/comic'));
+// router.get('/copymanga/comic/:id', lazyloadRouteHandler('./routes/copymanga/comic'));
// 動漫狂
router.get('/cartoonmad/comic/:id', lazyloadRouteHandler('./routes/cartoonmad/comic'));
diff --git a/lib/routes/copymanga/comic.js b/lib/routes/copymanga/comic.js
deleted file mode 100644
index c42a368b7..000000000
--- a/lib/routes/copymanga/comic.js
+++ /dev/null
@@ -1,74 +0,0 @@
-const cheerio = require('cheerio');
-const got = require('@/utils/got');
-
-// 直接调用拷贝漫画的接口
-module.exports = async (ctx) => {
- const { id } = ctx.params;
- // 用于控制返回的章节数量
- const chapterCnt = Number(ctx.params.chapterCnt || 0);
- // 获取漫画列表
- let bHasNextPage = false;
- const iReqLimit = (ctx.queries && ctx.queries.limit) || 100;
- let iReqOffSet = 0;
- const strBaseUrl = `https://api.copymanga.com/api/v3/comic/${id}/group/default/chapters?`;
- let chapterArray = [];
-
- do {
- bHasNextPage = false;
- // eslint-disable-next-line no-await-in-loop
- const { data } = await got.get(strBaseUrl + 'limit=' + iReqLimit + '&offset=' + iReqOffSet);
- const { code, results } = data;
-
- if (code !== 200) {
- break;
- }
-
- if (results.limit + results.offset < results.total) {
- bHasNextPage = true;
- }
- iReqOffSet += iReqLimit;
-
- chapterArray = chapterArray.concat(results.list);
- } while (bHasNextPage);
-
- chapterArray = chapterArray
- .map(({ comic_path_word, uuid, name, size, datetime_created, index }) => ({
- link: 'https://copymanga.com/comic/' + comic_path_word + '/chapter/' + uuid,
- title: name,
- num: size,
- updateTime: datetime_created,
- index,
- }))
- .reverse();
-
- // 获取漫画标题、介绍
- const { bookTitle, bookIntro } = await ctx.cache.tryGet(`https://copymanga.com/comic/${id}`, async () => {
- const { data } = await got.get(`https://copymanga.com/comic/${id}`);
- const $ = cheerio.load(data);
- return {
- bookTitle: $('.comicParticulars-title-right > ul > li > h6').text(),
- bookIntro: $('.intro').text(),
- };
- });
-
- const genResult = (chapter) => ({
- link: chapter.link,
- title: chapter.title,
- description: `
-
${chapter.num}p
- `.trim(),
- });
-
- let itemsLen = chapterArray.length;
-
- if (chapterCnt > 0) {
- itemsLen = chapterCnt;
- }
-
- ctx.state.data = {
- title: `拷贝漫画 - ${bookTitle}`,
- link: `https://copymanga.com/comic/${id}`,
- description: bookIntro,
- item: chapterArray.map(genResult).slice(0, itemsLen),
- };
-};
diff --git a/lib/v2/copymanga/comic.js b/lib/v2/copymanga/comic.js
new file mode 100644
index 000000000..843da8116
--- /dev/null
+++ b/lib/v2/copymanga/comic.js
@@ -0,0 +1,110 @@
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+const { art } = require('@/utils/render');
+const path = require('path');
+
+const host = 'copymanga.site';
+const baseUrl = `https://${host}`;
+const apiBaseUrl = `https://api.${host}`;
+
+// 直接调用拷贝漫画的接口
+module.exports = async (ctx) => {
+ const { id } = ctx.params;
+ // 用于控制返回的章节数量
+ const chapterCnt = Number(ctx.params.chapterCnt || 0);
+ // 获取漫画列表
+ let bHasNextPage = false;
+ const iReqLimit = (ctx.queries && ctx.queries.limit) || 100;
+ let iReqOffSet = 0;
+ const strBaseUrl = `${apiBaseUrl}/api/v3/comic/${id}/group/default/chapters`;
+ let chapterArray = [];
+
+ do {
+ bHasNextPage = false;
+ // eslint-disable-next-line no-await-in-loop
+ const { data } = await got(strBaseUrl, {
+ headers: {
+ platform: 1,
+ },
+ searchParams: {
+ limit: iReqLimit,
+ offset: iReqOffSet === 0 ? undefined : iReqOffSet,
+ },
+ });
+ const { code, results } = data;
+
+ if (code !== 200) {
+ break;
+ }
+
+ if (results.limit + results.offset < results.total) {
+ bHasNextPage = true;
+ }
+ iReqOffSet += iReqLimit;
+
+ chapterArray = [...chapterArray, ...results.list];
+ } while (bHasNextPage);
+
+ chapterArray = chapterArray
+ .map(({ comic_path_word, uuid, name, size, datetime_created /* , index*/ }) => ({
+ link: `${baseUrl}/comic/${comic_path_word}/chapter/${uuid}`,
+ uuid,
+ title: name,
+ size,
+ pubDate: datetime_created,
+ // index,
+ }))
+ .reverse();
+
+ // 获取漫画标题、介绍
+ const { bookTitle, bookIntro } = await ctx.cache.tryGet(`${baseUrl}/comic/${id}`, async () => {
+ const { data } = await got(`${baseUrl}/comic/${id}`);
+ const $ = cheerio.load(data);
+ return {
+ bookTitle: $('.comicParticulars-title-right > ul > li > h6').text(),
+ bookIntro: $('.intro').text(),
+ };
+ });
+
+ const genResult = async (chapter) => {
+ const {
+ data: { results },
+ } = await got(`${apiBaseUrl}/api/v3/comic/${id}/chapter2/${chapter.uuid}`, {
+ headers: {
+ webp: 1,
+ },
+ });
+
+ const pageNumbers = Object.values(results.chapter.words);
+ const contents = results.chapter.contents
+ .map((content, index) => ({
+ page: pageNumbers[index],
+ url: content.url,
+ }))
+ .sort((a, b) => a.page - b.page);
+
+ return {
+ link: chapter.link,
+ title: chapter.title,
+ description: art(path.join(__dirname, './templates/comic.art'), {
+ size: chapter.size,
+ contents,
+ }),
+ pubDate: parseDate(chapter.pubDate, 'YYYY-MM-DD'),
+ };
+ };
+
+ let itemsLen = chapterArray.length;
+
+ if (chapterCnt > 0) {
+ itemsLen = chapterCnt;
+ }
+
+ ctx.state.data = {
+ title: `拷贝漫画 - ${bookTitle}`,
+ link: `${baseUrl}/comic/${id}`,
+ description: bookIntro,
+ item: await Promise.all(chapterArray.slice(0, itemsLen).map((chapter) => ctx.cache.tryGet(chapter.link, () => genResult(chapter)))),
+ };
+};
diff --git a/lib/v2/copymanga/maintainer.js b/lib/v2/copymanga/maintainer.js
new file mode 100644
index 000000000..f8e88f349
--- /dev/null
+++ b/lib/v2/copymanga/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/comic/:id/:chapterCnt?': ['btdwv', 'marvolo666', 'yan12125'],
+};
diff --git a/lib/v2/copymanga/radar.js b/lib/v2/copymanga/radar.js
new file mode 100644
index 000000000..4ac9d9ce5
--- /dev/null
+++ b/lib/v2/copymanga/radar.js
@@ -0,0 +1,19 @@
+const copymanga = {
+ _name: '拷贝漫画',
+ '.': [
+ {
+ title: '漫画更新',
+ docs: 'https://docs.rsshub.app/anime.html#kao-bei-man-hua',
+ source: '/comic/:id',
+ target: '/copymanga/comic/:id/5',
+ },
+ ],
+};
+
+module.exports = {
+ 'copymanga.com': copymanga,
+ 'copymanga.info': copymanga,
+ 'copymanga.net': copymanga,
+ 'copymanga.org': copymanga,
+ 'copymanga.site': copymanga,
+};
diff --git a/lib/v2/copymanga/router.js b/lib/v2/copymanga/router.js
new file mode 100644
index 000000000..c0eb83ef5
--- /dev/null
+++ b/lib/v2/copymanga/router.js
@@ -0,0 +1,3 @@
+module.exports = (router) => {
+ router.get('/comic/:id/:chapterCnt?', require('./comic'));
+};
diff --git a/lib/v2/copymanga/templates/comic.art b/lib/v2/copymanga/templates/comic.art
new file mode 100644
index 000000000..e2f092d60
--- /dev/null
+++ b/lib/v2/copymanga/templates/comic.art
@@ -0,0 +1,4 @@
+{{ size }}p
+{{ each contents img }}
+
+{{ /each }}