Skip to content

Commit

Permalink
feat(route/chikubi): refactor URL fetching and add new routes (DIYgod…
Browse files Browse the repository at this point in the history
…#16758)

* refactor(route/chikubi): switch to native /feed for article URL fetching

* feat: add new routes

* refactor: remove decodeURIComponent

* fix: Handle unescaped characters in tag URLs

* chore: use '@/utils/rss-parser' instead of 'rss-parser'

* chore: update description

* feat(utils): add getPostById and getPostsByIdList for REST API content fetching

* refactor(search): use getPostsByIdList instead of processItems

* fix: Handle unescaped characters

* refactor: Separate index and navigation

* feat: optimize post fetching by id and add category & tag functions

* refactor: use api to get posts for tags and categories

* chore: directly use url

* fix: use API to fetch 'best'

* fix: destructure post object in map function

* feat: optimize getPosts function for reusability

* refactor: remove wrapper functions for getBySlug and getPostsBy
  • Loading branch information
Tsuyumi25 authored Sep 25, 2024
1 parent 003e3ad commit acdbd11
Show file tree
Hide file tree
Showing 9 changed files with 411 additions and 73 deletions.
41 changes: 41 additions & 0 deletions lib/routes/chikubi/category.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Route, Data } from '@/types';
import { getBySlug, getPostsBy } from './utils';

export const route: Route = {
path: '/category/:keyword',
categories: ['multimedia'],
example: '/chikubi/category/nipple-lesbian',
parameters: { keyword: 'Keyword' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: 'Category',
maintainers: ['SnowAgar25'],
handler,
radar: [
{
title: 'Category',
source: ['chikubi.jp/category/:keyword'],
target: '/category/:keyword',
},
],
};

async function handler(ctx): Promise<Data> {
const baseUrl = 'https://chikubi.jp';
const { keyword } = ctx.req.param();
const { id, name } = await getBySlug('category', keyword);

const items = await getPostsBy('category', id);

return {
title: `Category: ${name} - chikubi.jp`,
link: `${baseUrl}/category/${keyword}`,
item: items,
};
}
91 changes: 41 additions & 50 deletions lib/routes/chikubi/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Route, Data } from '@/types';
import got from '@/utils/got';
import { load } from 'cheerio';
import { processItems } from './utils';
import { getPosts } from './utils';

export const route: Route = {
path: '/:category?',
path: '/',
categories: ['multimedia'],
example: '/chikubi',
parameters: { category: '分類,見下表,默認爲最新' },
features: {
requireConfig: false,
requirePuppeteer: false,
Expand All @@ -16,60 +13,54 @@ export const route: Route = {
supportPodcast: false,
supportScihub: false,
},
name: 'Category',
maintainers: ['snowagar25'],
name: '最新記事',
maintainers: ['SnowAgar25'],
handler,
description: `| 最新 | 殿堂 | 動畫 | VR | 漫畫 | 音聲 | CG |
| ------ | ---- | ----- | -- | ----- | ----- | -- |
| (empty) | best | video | vr | comic | voice | cg |`,
radar: [
{
source: ['chikubi.jp/:category', 'chikubi.jp/'],
target: '/:category',
title: '最新記事',
source: ['chikubi.jp/'],
target: '/',
},
{
title: '殿堂',
source: ['chikubi.jp/best-nipple-article'],
target: '/best',
},
{
title: '動畫',
source: ['chikubi.jp/nipple-video'],
target: '/video',
},
{
title: 'VR',
source: ['chikubi.jp/nipple-video-category/cat-nipple-video-vr'],
target: '/vr',
},
{
title: '漫畫',
source: ['chikubi.jp/comic'],
target: '/comic',
},
{
title: '音聲',
source: ['chikubi.jp/voice'],
target: '/voice',
},
{
title: 'CG・イラスト',
source: ['chikubi.jp/cg'],
target: '/cg',
},
],
};

const categoryMap = {
'': { url: '/page/1', title: '最新', selector: '.article_list_area > article > a' },
best: { url: '/best-nipple-article', title: '殿堂', selector: '.article-list:first .title > a' },
video: { url: '/nipple-video', title: '動畫', selector: 'ul.video_list > li > a' },
vr: { url: '/nipple-video-category/cat-nipple-video-vr', title: 'VR', selector: 'ul.video_list > li > a' },
comic: { url: '/comic', title: '漫畫', selector: '.section:nth-of-type(2) .list-doujin .photo a' },
voice: { url: '/voice', title: '音聲', selector: 'ul.list-doujin > li > .photo > a' },
cg: { url: '/cg', title: 'CG', selector: 'ul.list-doujin > li > .photo > a' },
};

async function handler(ctx): Promise<Data> {
const category = ctx.req.param('category') ?? '';
const baseUrl = 'https://chikubi.jp';

const { url, title, selector } = categoryMap[category];

const response = await got(`${baseUrl}${url}`);
const $ = load(response.data);

let list = $(selector)
.toArray()
.map((item) => {
const $item = $(item);
return {
title: $item.text().trim(),
link: new URL($item.attr('href') ?? '', baseUrl).href,
};
});

// 限制殿堂最多獲取30個
if (category === 'best') {
list = list.slice(0, 30);
}

// 獲取內文
const items = await processItems(list);
async function handler(): Promise<Data> {
const items = await getPosts();

return {
title: `${title} - chikubi.jp`,
link: `${baseUrl}${url}`,
title: '最新記事 - chikubi.jp',
link: 'https://chikubi.jp',
item: items,
};
}
9 changes: 9 additions & 0 deletions lib/routes/chikubi/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@ import type { Namespace } from '@/types';
export const namespace: Namespace = {
name: '乳首ふぇち',
url: 'chikubi.jp',
description: `:::tip
The content of 乳首ふぇち is divided into two parts:
Works: Only reposts official product descriptions.
Posts: Contains the website author's thoughts and additional information.
Sometimes a product may exist in both posts and works.
Sometimes there might be only a single post without any reposted work, and vice versa.
:::`,
};
66 changes: 66 additions & 0 deletions lib/routes/chikubi/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Route, Data } from '@/types';
import { getBySlug, getPostsBy, processItems } from './utils';
import parser from '@/utils/rss-parser';

export const route: Route = {
path: '/:keyword',
categories: ['multimedia'],
example: '/chikubi',
parameters: { keyword: '導覽列,見下表,默認爲最新' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: 'Navigation',
maintainers: ['SnowAgar25'],
handler,
description: `| 殿堂 | 動畫 | VR | 漫畫 | 音聲 | CG・イラスト |
| ---- | ----- | -- | ----- | ----- | -- |
| best | video | vr | comic | voice | cg |`,
};

const navigationItems = {
video: { url: '/nipple-video', title: '動畫' },
vr: { url: '/nipple-video-category/cat-nipple-video-vr', title: 'VR' },
comic: { url: '/comic', title: '漫畫' },
voice: { url: '/voice', title: '音聲' },
cg: { url: '/cg', title: 'CG' },
};

async function handler(ctx): Promise<Data> {
const keyword = ctx.req.param('keyword') ?? '';
const baseUrl = 'https://chikubi.jp';

if (keyword === 'best') {
const { id } = await getBySlug('category', 'nipple-best');
const items = await getPostsBy('category', id);

return {
title: '殿堂 - chikubi.jp',
link: `${baseUrl}/best-nipple-article`,
item: items,
};
} else {
const { url, title } = navigationItems[keyword];

const feed = await parser.parseURL(`${baseUrl}${url}/feed`);

const list = feed.items.map((item) => ({
title: item.title,
link: item.link,
}));

// 獲取內文
const items = await processItems(list);

return {
title: `${title} - chikubi.jp`,
link: `${baseUrl}${url}`,
item: items,
};
}
}
49 changes: 49 additions & 0 deletions lib/routes/chikubi/nipple-video-category.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Route, Data } from '@/types';
import { processItems } from './utils';
import parser from '@/utils/rss-parser';

export const route: Route = {
path: '/nipple-video-category/:keyword',
categories: ['multimedia'],
example: '/chikubi/nipple-video-category/cat-nipple-video-god',
parameters: { keyword: 'Keyword' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: '動画カテゴリー',
maintainers: ['SnowAgar25'],
handler,
radar: [
{
title: '動画カテゴリー',
source: ['chikubi.jp/nipple-video-category/:keyword'],
target: '/nipple-video-category/:keyword',
},
],
};

async function handler(ctx): Promise<Data> {
const { keyword } = ctx.req.param();
const baseUrl = 'https://chikubi.jp';
const url = `/nipple-video-category/${encodeURIComponent(keyword)}`;

const feed = await parser.parseURL(`${baseUrl}${url}/feed`);

const list = feed.items.map((item) => ({
title: item.title,
link: item.link,
}));

const items = await processItems(list);

return {
title: `動画カテゴリー: ${feed.title?.split('-')[0]} - chikubi.jp`,
link: `${baseUrl}${url}`,
item: items,
};
}
49 changes: 49 additions & 0 deletions lib/routes/chikubi/nipple-video-maker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Route, Data } from '@/types';
import { processItems } from './utils';
import parser from '@/utils/rss-parser';

export const route: Route = {
path: '/nipple-video-maker/:keyword',
categories: ['multimedia'],
example: '/chikubi/nipple-video-maker/nipple-video-maker-nh',
parameters: { keyword: 'Keyword' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: 'AVメーカー',
maintainers: ['SnowAgar25'],
handler,
radar: [
{
title: 'AVメーカー',
source: ['chikubi.jp/nipple-video-maker/:keyword'],
target: '/nipple-video-maker/:keyword',
},
],
};

async function handler(ctx): Promise<Data> {
const { keyword } = ctx.req.param();
const baseUrl = 'https://chikubi.jp';
const url = `/nipple-video-maker/${encodeURIComponent(keyword)}`;

const feed = await parser.parseURL(`${baseUrl}${url}/feed`);

const list = feed.items.map((item) => ({
title: item.title,
link: item.link,
}));

const items = await processItems(list);

return {
title: `AVメーカー: ${feed.title?.split('-')[0]} - chikubi.jp`,
link: `${baseUrl}${url}`,
item: items,
};
}
39 changes: 39 additions & 0 deletions lib/routes/chikubi/search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Route, Data } from '@/types';
import { getPosts } from './utils';
import got from '@/utils/got';

export const route: Route = {
path: '/search/:keyword',
categories: ['multimedia'],
example: '/chikubi/search/ギャップ',
parameters: { keyword: 'Keyword' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: 'Search',
maintainers: ['SnowAgar25'],
handler,
};

async function handler(ctx): Promise<Data> {
const { keyword } = ctx.req.param();
const baseUrl = 'https://chikubi.jp';
const searchUrl = `${baseUrl}/wp-json/wp/v2/search?search=${keyword}`;

const response = await got.get(searchUrl);
const searchResults = response.data;

const postIds = searchResults.map((item) => item.id.toString());
const items = await getPosts(postIds);

return {
title: `Search: ${keyword} - chikubi.jp`,
link: `${baseUrl}/search/${encodeURIComponent(keyword)}`,
item: items,
};
}
Loading

0 comments on commit acdbd11

Please sign in to comment.