diff --git a/lib/routes/baobua/article.ts b/lib/routes/baobua/article.ts new file mode 100644 index 000000000..7b40702fd --- /dev/null +++ b/lib/routes/baobua/article.ts @@ -0,0 +1,51 @@ +import { load } from 'cheerio'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; + +async function loadArticle(link) { + const resp = await got(link); + const article = load(resp.body); + + const title = article('title') + .text() + .replace('BaoBua.Com:', '') + .replace(/\| Page \d+\/\d+/, '') + .trim(); + const totalPagesRegex = /Page \d+\/(\d+)/; + const totalPagesMatch = totalPagesRegex.exec(article('title').text()); + const totalPages = totalPagesMatch ? Number.parseInt(totalPagesMatch[1]) : 1; + + let pubDate; + const blogPostingScript = article('script:contains("BlogPosting")').first(); + if (blogPostingScript) { + const jsonData = JSON.parse(blogPostingScript.text()); + pubDate = parseDate(jsonData.datePublished); + } + + const contentDiv = article('.contentme2'); + let description = contentDiv.html() ?? ''; + + if (totalPages > 1) { + const additionalContents = await Promise.all( + Array.from({ length: totalPages - 1 }, async (_, i) => { + try { + const response = await got(`${link}?page=${i + 2}`); + const pageDom = load(response.body); + return pageDom('.contentme2').html() ?? ''; + } catch { + return ''; + } + }) + ); + description += additionalContents.join(''); + } + + return { + title, + description, + pubDate, + link, + }; +} + +export default loadArticle; diff --git a/lib/routes/baobua/category.ts b/lib/routes/baobua/category.ts new file mode 100644 index 000000000..54cad3a70 --- /dev/null +++ b/lib/routes/baobua/category.ts @@ -0,0 +1,60 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { load } from 'cheerio'; +import { SUB_NAME_PREFIX, SUB_URL } from './const'; +import loadArticle from './article'; + +export const route: Route = { + path: '/category/:category', + categories: ['picture'], + example: '/baobua/category/network', + parameters: { category: 'Category' }, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['baobua.com/cat/:category'], + target: '/category/:category', + }, + ], + name: 'Category', + maintainers: ['AiraNadih'], + handler, + url: 'baobua.com/', +}; + +async function handler(ctx) { + const category = ctx.req.param('category'); + const url = `${SUB_URL}cat/${category}/`; + + const response = await got(url); + const $ = load(response.body); + const itemRaw = $('.thcovering-video').toArray(); + + return { + title: `${SUB_NAME_PREFIX} - Category: ${category}`, + link: url, + item: await Promise.all( + itemRaw + .map((e) => { + const item = $(e); + let link = item.find('a').attr('href'); + if (!link) { + return null; + } + if (link.startsWith('/')) { + link = new URL(link, SUB_URL).href; + } + return cache.tryGet(link, () => loadArticle(link)); + }) + .filter(Boolean) + ), + }; +} diff --git a/lib/routes/baobua/const.ts b/lib/routes/baobua/const.ts new file mode 100644 index 000000000..c135b8373 --- /dev/null +++ b/lib/routes/baobua/const.ts @@ -0,0 +1,4 @@ +const SUB_NAME_PREFIX = 'BaoBua'; +const SUB_URL = 'https://baobua.com/'; + +export { SUB_NAME_PREFIX, SUB_URL }; diff --git a/lib/routes/baobua/latest.ts b/lib/routes/baobua/latest.ts new file mode 100644 index 000000000..664f95c76 --- /dev/null +++ b/lib/routes/baobua/latest.ts @@ -0,0 +1,57 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { load } from 'cheerio'; +import { SUB_NAME_PREFIX, SUB_URL } from './const'; +import loadArticle from './article'; + +export const route: Route = { + path: '/', + categories: ['picture'], + example: '/baobua', + parameters: {}, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['baobua.com/'], + target: '', + }, + ], + name: 'Latest', + maintainers: ['AiraNadih'], + handler, + url: 'baobua.com/', +}; + +async function handler() { + const response = await got(SUB_URL); + const $ = load(response.body); + const itemRaw = $('.thcovering-video').toArray(); + + return { + title: `${SUB_NAME_PREFIX} - Latest`, + link: SUB_URL, + item: await Promise.all( + itemRaw + .map((e) => { + const item = $(e); + let link = item.find('a').attr('href'); + if (!link) { + return null; + } + if (link.startsWith('/')) { + link = new URL(link, SUB_URL).href; + } + return cache.tryGet(link, () => loadArticle(link)); + }) + .filter(Boolean) + ), + }; +} diff --git a/lib/routes/baobua/namespace.ts b/lib/routes/baobua/namespace.ts new file mode 100644 index 000000000..0d5583395 --- /dev/null +++ b/lib/routes/baobua/namespace.ts @@ -0,0 +1,8 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'BaoBua', + url: 'baobua.com', + description: 'BaoBua.Com - Hot beauty girl pics, girls photos, free watch online hd photo sets', + lang: 'en', +}; diff --git a/lib/routes/baobua/search.ts b/lib/routes/baobua/search.ts new file mode 100644 index 000000000..804a61ea5 --- /dev/null +++ b/lib/routes/baobua/search.ts @@ -0,0 +1,60 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { load } from 'cheerio'; +import { SUB_NAME_PREFIX, SUB_URL } from './const'; +import loadArticle from './article'; + +export const route: Route = { + path: '/search/:keyword', + categories: ['picture'], + example: '/baobua/search/cos', + parameters: { keyword: 'Keyword' }, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['baobua.com/search'], + target: '/search/:keyword', + }, + ], + name: 'Search', + maintainers: ['AiraNadih'], + handler, + url: 'baobua.com/', +}; + +async function handler(ctx) { + const keyword = ctx.req.param('keyword'); + const url = `${SUB_URL}search?q=${keyword}`; + + const response = await got(url); + const $ = load(response.body); + const itemRaw = $('.thcovering-video').toArray(); + + return { + title: `${SUB_NAME_PREFIX} - Search: ${keyword}`, + link: url, + item: await Promise.all( + itemRaw + .map((e) => { + const item = $(e); + let link = item.find('a').attr('href'); + if (!link) { + return null; + } + if (link.startsWith('/')) { + link = new URL(link, SUB_URL).href; + } + return cache.tryGet(link, () => loadArticle(link)); + }) + .filter(Boolean) + ), + }; +}