diff --git a/assets/radar-rules.js b/assets/radar-rules.js index 4733c75678..c5470ae6d1 100644 --- a/assets/radar-rules.js +++ b/assets/radar-rules.js @@ -522,42 +522,6 @@ ], sites: [{ title: 'Sites', docs: 'https://docs.rsshub.app/blog.html#google-sites', source: ['/site/:id/*', '/site/:id'], target: '/google/sites/:id' }], }, - 'javlibrary.com': { - _name: 'javlibrary', - www: [ - { title: '新话题', docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', source: '/cn', target: '/javlibrary/videos/update' }, - { title: '新发行', docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', source: '/cn', target: '/javlibrary/videos/newrelease' }, - { title: '新加入', docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', source: '/cn', target: '/javlibrary/videos/newentries' }, - { title: '最想要', docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', source: '/cn', target: '/javlibrary/videos/mostwanted' }, - { title: '高评价', docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', source: '/cn', target: '/javlibrary/videos/bestrated' }, - { title: '最佳评论', docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', source: '/cn', target: '/javlibrary/bestreviews' }, - { title: '影星', docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', source: '/cn/vl_star.php', target: (params, url) => `/javlibrary/stars/${new URL(url).searchParams.get('s')}` }, - { - title: '用户文章', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userposts`, - }, - { - title: '用户拥有', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userowned`, - }, - { - title: '用户看过', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userwatched`, - }, - { - title: '用户想要', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userwanted`, - }, - ], - }, 'qidian.com': { _name: '起点', book: [ diff --git a/docs/en/multimedia.md b/docs/en/multimedia.md index f369001b04..c2c2344675 100644 --- a/docs/en/multimedia.md +++ b/docs/en/multimedia.md @@ -44,31 +44,103 @@ Official RSS: https://eztv.io/ezrss.xml -## JavLibrary +## JAVLibrary -### Videos +### Recently Discussed Videos + + + +### New Releases + + + +| videos with comments (by date) | everything (by date) | +| ------------------------------ | -------------------- | +| 1 | 2 | - -|New Comments|New Release|New Entries|Most Wanted|Best Rated| -|-----|------|------|-----|------| -|update|newrelease|newentries|mostwanted|bestrated| -### Stars +### Recently Inserted Videos - + -### Users +### Most Wanted Videos + + + +| Last Month | All Time | +| ---------- | -------- | +| 1 | 2 | - -|User wanted|User watched|User owned|User posts| -|-----|------|------|-----| -|userwanted|userwatched|userowned|userposts| -### Bestreviews +### Best Rated Videos - + + +| Last Month | All Time | +| ---------- | -------- | +| 1 | 2 | + + + +### Best Reviews + + + +| Last Month | All Time | +| ---------- | -------- | +| 1 | 2 | + + + +### Videos by categories + + + +| videos with comments (by date) | everything (by date) | +| ------------------------------ | -------------------- | +| 1 | 2 | + +::: tip Tip + +See [Categories](https://www.javlibrary.com/en/genres.php) to view all categories. + +::: + + + +### Videos by star + + + +| videos with comments (by date) | everything (by date) | +| ------------------------------ | -------------------- | +| 1 | 2 | + +::: tip Tip + +See [Ranking](https://www.javlibrary.com/en/star_mostfav.php) to view stars by ranks. + +See [Directory](https://www.javlibrary.com/en/star_list.php) to view all stars. + +::: + + + +### Posts published by user + + + +### Videos by user + + + +| Wanted | Watched | Owned | +| ---------- | ----------- | --------- | +| userwanted | userwatched | userowned | + + ## Melon diff --git a/docs/multimedia.md b/docs/multimedia.md index 71a96265f2..22ec54da65 100644 --- a/docs/multimedia.md +++ b/docs/multimedia.md @@ -565,31 +565,103 @@ JavDB 有多个备用域名,本路由以 为默认域名 -## JavLibrary +## JAVLibrary -### 影片 +### 最近讨论的影片 + + + +### 新发行的影片 + + + +| 有评论的影片(依发行日) | 所有的影片(依发行日) | +| ------------------------ | ---------------------- | +| 1 | 2 | - -|新话题|新发行|新加入|最想要|高评价| -|-----|------|------|-----|------| -|update|newrelease|newentries|mostwanted|bestrated| -### 影星 +### 最新加入的影片 - + -### 用户 +### 最想要的影片 + + + +| 上个月 | 全部 | +| ------ | ---- | +| 1 | 2 | + + + +### 评价最高的影片 + + + +| 上个月 | 全部 | +| ------ | ---- | +| 1 | 2 | + + + +### 影片依分类 + + + +| 有评论的影片(依发行日) | 所有的影片(依发行日) | +| ------------------------ | ---------------------- | +| 1 | 2 | + +::: tip 提示 + +全部分类参见 [依分类](https://www.javlibrary.com/cn/genres.php) + +::: + + + +### 影片按演员 + + + +| 有评论的影片(依发行日) | 所有的影片(依发行日) | +| ------------------------ | ---------------------- | +| 1 | 2 | + +::: tip 提示 + +按排行榜查看演员可前往 [排行榜](https://www.javlibrary.com/cn/star_mostfav.php) + +全部演员参见 [名鑑](https://www.javlibrary.com/cn/star_list.php) + +::: - -|想要的|看过的|拥有的|发表的文章| -|-----|------|------|-----| -|userwanted|userwatched|userowned|userposts| ### 最佳评论 - + + +| 上个月 | 全部 | +| ------ | ---- | +| 1 | 2 | + + + +### 用户发表的文章 + + + +### 用户相关的影片 + + + +| 用户想要的影片 | 用户看过的影片 | 用户拥有的影片 | +| -------------- | -------------- | -------------- | +| userwanted | userwatched | userowned | + + ## Last.fm diff --git a/lib/radar-rules.js b/lib/radar-rules.js index dd861ec3ac..d79bcd0de3 100644 --- a/lib/radar-rules.js +++ b/lib/radar-rules.js @@ -1304,74 +1304,33 @@ module.exports = { }, ], }, - 'javlibrary.com': { - _name: 'javlibrary', - www: [ + 'google.com': { + _name: '谷歌', + chrome: [ { - title: '新话题', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: '/cn', - target: '/javlibrary/videos/update', + title: '插件更新', + source: '/webstore/detail/:name/:id', + docs: 'https://docs.rsshub.app/program-update.html#chrome-wang-shang-ying-yong-dian', + target: '/chrome/webstore/extensions/:id', }, + ], + photos: [ { - title: '新发行', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: '/cn', - target: '/javlibrary/videos/newrelease', + title: '相册', + docs: 'https://docs.rsshub.app/picture.html#google-xiang-ce', + source: '/share/*', + target: (params, url, document) => { + const id = document && document.querySelector('html').innerHTML.match(/photos.app.goo.gl\/(.*?)"/)[1]; + return id ? `/google/album/${id}` : ''; + }, }, + ], + sites: [ { - title: '新加入', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: '/cn', - target: '/javlibrary/videos/newentries', - }, - { - title: '最想要', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: '/cn', - target: '/javlibrary/videos/mostwanted', - }, - { - title: '高评价', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: '/cn', - target: '/javlibrary/videos/bestrated', - }, - { - title: '最佳评论', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: '/cn', - target: '/javlibrary/bestreviews', - }, - { - title: '影星', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: '/cn/vl_star.php', - target: (params, url) => `/javlibrary/stars/${new URL(url).searchParams.get('s')}`, - }, - { - title: '用户文章', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userposts`, - }, - { - title: '用户拥有', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userowned`, - }, - { - title: '用户看过', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userwatched`, - }, - { - title: '用户想要', - docs: 'https://docs.rsshub.app/multimedia.html#javlibrary', - source: ['/cn/user.php', '/cn/userposts.php', '/cn/userwateched.php', '/cn/userowned.php', '/cn/userwanted.php'], - target: (params, url) => `/javlibrary/users/${new URL(url).searchParams.get('u')}/userwanted`, + title: 'Sites', + docs: 'https://docs.rsshub.app/blog.html#google-sites', + source: ['/site/:id/*', '/site/:id'], + target: '/google/sites/:id', }, ], }, diff --git a/lib/router.js b/lib/router.js index c4c0850469..dcd742928d 100644 --- a/lib/router.js +++ b/lib/router.js @@ -2514,10 +2514,10 @@ router.get('/letterboxd/user/diary/:username', lazyloadRouteHandler('./routes/le router.get('/letterboxd/user/followingdiary/:username', lazyloadRouteHandler('./routes/letterboxd/followingdiary')); // javlibrary -router.get('/javlibrary/users/:uid/:utype', lazyloadRouteHandler('./routes/javlibrary/users')); -router.get('/javlibrary/videos/:vtype', lazyloadRouteHandler('./routes/javlibrary/videos')); -router.get('/javlibrary/stars/:sid', lazyloadRouteHandler('./routes/javlibrary/stars')); -router.get('/javlibrary/bestreviews', lazyloadRouteHandler('./routes/javlibrary/bestreviews')); +// router.get('/javlibrary/users/:uid/:utype', lazyloadRouteHandler('./routes/javlibrary/users')); +// router.get('/javlibrary/videos/:vtype', lazyloadRouteHandler('./routes/javlibrary/videos')); +// router.get('/javlibrary/stars/:sid', lazyloadRouteHandler('./routes/javlibrary/stars')); +// router.get('/javlibrary/bestreviews', lazyloadRouteHandler('./routes/javlibrary/bestreviews')); // Last.FM router.get('/lastfm/recent/:user', lazyloadRouteHandler('./routes/lastfm/recent')); diff --git a/lib/routes/javlibrary/bestreviews.js b/lib/routes/javlibrary/bestreviews.js deleted file mode 100644 index 7b066df2d7..0000000000 --- a/lib/routes/javlibrary/bestreviews.js +++ /dev/null @@ -1,11 +0,0 @@ -const { getVideoComments } = require('./utils'); - -module.exports = async (ctx) => { - const link = 'http://www.javlibrary.com/cn/tl_bestreviews.php'; - const items = await getVideoComments(link); - ctx.state.data = { - title: 'Javlibrary - 最佳评论', - link, - item: items, - }; -}; diff --git a/lib/routes/javlibrary/stars.js b/lib/routes/javlibrary/stars.js deleted file mode 100644 index c4ae433bb0..0000000000 --- a/lib/routes/javlibrary/stars.js +++ /dev/null @@ -1,9 +0,0 @@ -const { template } = require('./utils'); - -module.exports = async (ctx) => { - const sid = ctx.params.sid; - ctx.state.data = { - link: `http://www.javlibrary.com/cn/vl_star.php?s=${sid}`, - }; - await template(ctx); -}; diff --git a/lib/routes/javlibrary/users.js b/lib/routes/javlibrary/users.js deleted file mode 100644 index 3c75d3de4a..0000000000 --- a/lib/routes/javlibrary/users.js +++ /dev/null @@ -1,22 +0,0 @@ -const { template, getVideoComments } = require('./utils'); - -module.exports = async (ctx) => { - const utype = ctx.params.utype; - const uid = ctx.params.uid; - - if (utype === 'userposts') { - const uid = ctx.params.uid; - const link = `http://www.javlibrary.com/cn/userposts.php?u=${uid}`; - const items = await getVideoComments(link); - ctx.state.data = { - title: `Javlibrary - ${uid} 发表的文章`, - link, - item: items, - }; - } else { - ctx.state.data = { - link: `http://www.javlibrary.com/cn/${utype}.php?u=${uid}`, - }; - await template(ctx); - } -}; diff --git a/lib/routes/javlibrary/utils.js b/lib/routes/javlibrary/utils.js deleted file mode 100644 index a5b9cf9ff9..0000000000 --- a/lib/routes/javlibrary/utils.js +++ /dev/null @@ -1,68 +0,0 @@ -const url = require('url'); -const cheerio = require('cheerio'); -const got = require('@/utils/got'); -const dateUtil = require('@/utils/date'); - -// 通过传入不同的ctx.state.data.link 返回javlibrary 不同link的rss -exports.template = async function template(ctx) { - const link = ctx.state.data.link; - const response = await got.get(link); - const $ = cheerio.load(response.body); - const list = $('.videothumblist .video').get(); - - const items = await Promise.all( - list.map(async (item) => { - item = $(item); - const itemLink = url.resolve(link, item.find('a').attr('href')); - const simple = { - title: `[${item.find('.id').text()}]${item.find('.title').text()}`, - link: itemLink, - }; - - const details = await ctx.cache.tryGet(itemLink, async () => { - const response = await got.get(itemLink); - const $ = cheerio.load(response.body); - $('#video_info #video_review .icon').remove(); - return { - author: $('.star').text(), - description: `${$('#video_info').html()}`, - }; - }); - return Promise.resolve(Object.assign({}, simple, details)); - }) - ); - - ctx.state.data = { - title: `Javlibrary - ${$('.boxtitle').text()}`, - link, - item: items, - }; -}; - -exports.getVideoComments = async function getVideoComments(link) { - const response = await got.get(link); - const $ = cheerio.load(response.body); - const list = $('#video_comments > table'); - - return ( - list && - list - .map((index, item) => { - item = $(item); - // 文章内容只能抓取到 td.t textarea,若含有图片则替换[img]image-link[/img] => - let comments = item.find('textarea').text(); - comments = comments.replace(new RegExp('\\[img\\]', 'g'), ''); - return { - title: item.find('tbody > tr:nth-child(1) > td:nth-child(2)').text(), - link: item.find('tbody > tr:nth-child(1) > td:nth-child(2) > a').attr('href'), - description: ` - - ${item.find('tbody > tr:nth-child(1) > td:nth-child(2)').html()} - ${comments} - `, - pubDate: dateUtil(item.find('tbody > tr:nth-child(3) > td.date')), - }; - }) - .get() - ); -}; diff --git a/lib/routes/javlibrary/videos.js b/lib/routes/javlibrary/videos.js deleted file mode 100644 index 15488c724c..0000000000 --- a/lib/routes/javlibrary/videos.js +++ /dev/null @@ -1,9 +0,0 @@ -const { template } = require('./utils'); - -module.exports = async (ctx) => { - const vtype = ctx.params.vtype; - ctx.state.data = { - link: `http://www.javlibrary.com/cn/vl_${vtype}.php`, - }; - await template(ctx); -}; diff --git a/lib/v2/javlibrary/bestrated.js b/lib/v2/javlibrary/bestrated.js new file mode 100644 index 0000000000..da7b2e099d --- /dev/null +++ b/lib/v2/javlibrary/bestrated.js @@ -0,0 +1,9 @@ +const { defaultMode, defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const mode = ctx.params.mode ?? defaultMode; + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/vl_bestrated.php?list&mode=${mode}`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/bestreviews.js b/lib/v2/javlibrary/bestreviews.js new file mode 100644 index 0000000000..b0a61bd58b --- /dev/null +++ b/lib/v2/javlibrary/bestreviews.js @@ -0,0 +1,9 @@ +const { defaultMode, defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const mode = ctx.params.mode ?? defaultMode; + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/tl_bestreviews.php?list&mode=${mode}`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/genre.js b/lib/v2/javlibrary/genre.js new file mode 100644 index 0000000000..271211fcf7 --- /dev/null +++ b/lib/v2/javlibrary/genre.js @@ -0,0 +1,10 @@ +const { defaultMode, defaultGenre, defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const mode = ctx.params.mode ?? defaultMode; + const genre = ctx.params.genre ?? defaultGenre; + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/vl_genre.php?list&g=${genre}&mode=${mode}`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/maintainer.js b/lib/v2/javlibrary/maintainer.js new file mode 100644 index 0000000000..7d98441fc2 --- /dev/null +++ b/lib/v2/javlibrary/maintainer.js @@ -0,0 +1,11 @@ +module.exports = { + '/bestrated/:language?/:mode?': ['nczitzk'], + '/bestreviews/:language?/:mode?': ['nczitzk'], + '/genre/:genre?/:language?/:mode?': ['nczitzk'], + '/mostwanted/:language?/:mode?': ['nczitzk'], + '/newentries/:language?': ['nczitzk'], + '/newrelease/:language?/:mode?': ['nczitzk'], + '/star/:id/:language?/:mode?': ['nczitzk'], + '/update/:language?': ['nczitzk'], + '/:type/:id/:language?': ['nczitzk'], +}; diff --git a/lib/v2/javlibrary/mostwanted.js b/lib/v2/javlibrary/mostwanted.js new file mode 100644 index 0000000000..46d68d1570 --- /dev/null +++ b/lib/v2/javlibrary/mostwanted.js @@ -0,0 +1,9 @@ +const { defaultMode, defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const mode = ctx.params.mode ?? defaultMode; + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/vl_mostwanted.php?list&mode=${mode}`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/newentries.js b/lib/v2/javlibrary/newentries.js new file mode 100644 index 0000000000..7b844d4214 --- /dev/null +++ b/lib/v2/javlibrary/newentries.js @@ -0,0 +1,8 @@ +const { defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/vl_newentries.php?list`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/newrelease.js b/lib/v2/javlibrary/newrelease.js new file mode 100644 index 0000000000..f98b732b88 --- /dev/null +++ b/lib/v2/javlibrary/newrelease.js @@ -0,0 +1,9 @@ +const { defaultMode, defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const mode = ctx.params.mode ?? defaultMode; + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/vl_newrelease.php?list&mode=${mode}`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/radar.js b/lib/v2/javlibrary/radar.js new file mode 100644 index 0000000000..468f12011f --- /dev/null +++ b/lib/v2/javlibrary/radar.js @@ -0,0 +1,79 @@ +module.exports = { + 'javlibrary.com': { + _name: 'JAVLibrary', + '.': [ + { + title: '最近讨论的影片', + docs: 'https://docs.rsshub.app/multimedia.html#zui-jin-tao-lun-de-ying-pian', + source: ['/:language', '/'], + target: (params) => `/javlibrary/update/${params.language}`, + }, + { + title: '新发行的影片', + docs: 'https://docs.rsshub.app/multimedia.html#xin-fa-xing-de-ying-pian', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/newrelease/${params.language}/${new URL(url).searchParams.get('mode')}`, + }, + { + title: '最新加入的影片', + docs: 'https://docs.rsshub.app/multimedia.html#zui-xin-jia-ru-de-ying-pian', + source: ['/:language', '/'], + target: (params) => `/javlibrary/update/${params.language}`, + }, + { + title: '最想要的影片', + docs: 'https://docs.rsshub.app/multimedia.html#zui-xiang-yao-de-ying-pian', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/mostwanted/${params.language}/${new URL(url).searchParams.get('mode')}`, + }, + { + title: '评价最高的影片', + docs: 'https://docs.rsshub.app/multimedia.html#ping-jia-zui-gao-de-ying-pian', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/bestrated/${params.language}/${new URL(url).searchParams.get('mode')}`, + }, + { + title: '最佳评论', + docs: 'https://docs.rsshub.app/multimedia.html#zui-jia-ping-lun', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/bestreviews/${params.language}/${new URL(url).searchParams.get('mode')}`, + }, + { + title: '影片依分类', + docs: 'https://docs.rsshub.app/multimedia.html#ying-pian-yi-fen-lei', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/genre/${new URL(url).searchParams.get('g')}/${params.language}/${new URL(url).searchParams.get('mode')}`, + }, + { + title: '影片按演员', + docs: 'https://docs.rsshub.app/multimedia.html#ying-pian-an-yan-yuan', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/star/${new URL(url).searchParams.get('s')}/${params.language}/${new URL(url).searchParams.get('mode')}`, + }, + { + title: '用户发表的文章', + docs: 'https://docs.rsshub.app/multimedia.html#yong-hu-fa-biao-de-wen-zhang', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/userposts/${new URL(url).searchParams.get('u')}/${params.language}`, + }, + { + title: '用户想要的影片', + docs: 'https://docs.rsshub.app/multimedia.html#yong-hu-xiang-yao-de-ying-pian', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/userwanted/${new URL(url).searchParams.get('u')}/${params.language}`, + }, + { + title: '用户看过的影片', + docs: 'https://docs.rsshub.app/multimedia.html#yong-hu-kan-guo-de-ying-pian', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/userwatched/${new URL(url).searchParams.get('u')}/${params.language}`, + }, + { + title: '用户拥有的影片', + docs: 'https://docs.rsshub.app/multimedia.html#yong-hu-yong-you-de-ying-pian', + source: ['/:language', '/'], + target: (params, url) => `/javlibrary/userowned/${new URL(url).searchParams.get('u')}/${params.language}`, + }, + ], + }, +}; diff --git a/lib/v2/javlibrary/router.js b/lib/v2/javlibrary/router.js new file mode 100644 index 0000000000..9c0029db69 --- /dev/null +++ b/lib/v2/javlibrary/router.js @@ -0,0 +1,19 @@ +module.exports = function (router) { + router.get('/users/:id/:type/:language?', require('./user')); + router.get('/videos/bestrated/:language?/:mode?', require('./bestrated')); + router.get('/videos/genre/:genre?/:language?/:mode?', require('./genre')); + router.get('/videos/mostwanted/:language?/:mode?', require('./mostwanted')); + router.get('/videos/newentries/:language?', require('./newentries')); + router.get('/videos/newrelease/:language?/:mode?', require('./newrelease')); + router.get('/videos/update/:language?', require('./update')); + + router.get('/bestrated/:language?/:mode?', require('./bestrated')); + router.get('/bestreviews/:language?/:mode?', require('./bestreviews')); + router.get('/genre/:genre?/:language?/:mode?', require('./genre')); + router.get('/mostwanted/:language?/:mode?', require('./mostwanted')); + router.get('/newentries/:language?', require('./newentries')); + router.get('/newrelease/:language?/:mode?', require('./newrelease')); + router.get('/star/:id/:language?/:mode?', require('./star')); + router.get('/update/:language?', require('./update')); + router.get('/:type/:id/:language?', require('./user')); +}; diff --git a/lib/v2/javlibrary/star.js b/lib/v2/javlibrary/star.js new file mode 100644 index 0000000000..044ac346d6 --- /dev/null +++ b/lib/v2/javlibrary/star.js @@ -0,0 +1,10 @@ +const { defaultMode, defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const id = ctx.params.id; + const mode = ctx.params.mode ?? defaultMode; + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/vl_star.php?list&s=${id}&mode=${mode}`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/templates/description.art b/lib/v2/javlibrary/templates/description.art new file mode 100644 index 0000000000..dfd46e4a7c --- /dev/null +++ b/lib/v2/javlibrary/templates/description.art @@ -0,0 +1,17 @@ + + +{{@ info }} + +{{if comment}} + +{{@ comment }} + +{{/if}} + +{{each videos}} + +{{/each}} + +{{each thumbs}} + +{{/each}} \ No newline at end of file diff --git a/lib/v2/javlibrary/update.js b/lib/v2/javlibrary/update.js new file mode 100644 index 0000000000..d97682f141 --- /dev/null +++ b/lib/v2/javlibrary/update.js @@ -0,0 +1,8 @@ +const { defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/vl_update.php?list`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/user.js b/lib/v2/javlibrary/user.js new file mode 100644 index 0000000000..5989353c71 --- /dev/null +++ b/lib/v2/javlibrary/user.js @@ -0,0 +1,10 @@ +const { defaultLanguage, rootUrl, ProcessItems } = require('./utils'); + +module.exports = async (ctx) => { + const id = ctx.params.id; + const type = ctx.params.type; + const language = ctx.params.language ?? defaultLanguage; + const currentUrl = `${rootUrl}/${language}/${type}.php?list&u=${id}`; + + ctx.state.data = await ProcessItems(language, currentUrl, ctx.cache.tryGet); +}; diff --git a/lib/v2/javlibrary/utils.js b/lib/v2/javlibrary/utils.js new file mode 100644 index 0000000000..01a2353351 --- /dev/null +++ b/lib/v2/javlibrary/utils.js @@ -0,0 +1,98 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const { art } = require('@/utils/render'); +const path = require('path'); + +const rootUrl = 'https://www.javlibrary.com'; + +module.exports = { + rootUrl, + defaultMode: '1', + defaultGenre: 'amjq', + defaultLanguage: 'ja', + + ProcessItems: async (language, currentUrl, tryGet) => { + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = cheerio.load(response.data); + + $('.toolbar, .info, .videoinfo').remove(); + + let items = $('.videotextlist, #video_comments') + .find('a') + .toArray() + .filter((i) => $(i).parent().hasClass('video') || $(i).parent().get(0).tagName === 'strong') + .map((item) => { + item = $(item); + + const table = item.parentsUntil('table'); + const link = `${rootUrl}/${language}/${item.attr('href').replace(/^\.\//, '')}`; + + return { + link, // url to target content. + url: link.replace(/video.*\.php/, ''), // url to the video page. + + title: item.text(), + description: table.find('textarea').text(), + pubDate: parseDate(table.find('.date').text()), + }; + }); + + items = await Promise.all( + items.map((item) => + tryGet(item.url, async () => { + const detailResponse = await got({ + method: 'get', + url: item.url, + }); + + const content = cheerio.load(detailResponse.data); + + content('.icn_edit, .btn_videoplayer, a[rel="bookmark"]').remove(); + content('span').each(function () { + if (/^icn_/.test(content(this).attr('class'))) { + content(this).remove(); + } + }); + + item.author = content('.star') + .toArray() + .map((star) => content(star).text()) + .filter((star) => star !== '') + .join(','); + item.category = content('a[rel]') + .toArray() + .map((tag) => content(tag).text()) + .filter((tag) => tag !== ''); + item.description = art(path.join(__dirname, 'templates/description.art'), { + cover: content('#video_jacket_img').attr('src'), + info: content('#video_info') + .html() + .replace(/span>, '), + thumbs: content('.previewthumbs img') + .toArray() + .map((img) => content(img).attr('src').replace(/-/g, 'jp-')), + videos: [...new Set(detailResponse.data.match(/(http[\w\d:/]+\.mp4)/g))], + }); + item.pubDate = item.pubDate.toString() === 'Invalid Date' ? parseDate(content('#video_date').find('.text').text()) : item.pubDate; + + delete item.url; + + return item; + }) + ) + ); + + return { + title: $('title').text(), + link: currentUrl, + item: items, + allowEmpty: true, + }; + }, +};