diff --git a/lib/routes/utgd/category.ts b/lib/routes/utgd/category.ts index 30d738f72..376fe5207 100644 --- a/lib/routes/utgd/category.ts +++ b/lib/routes/utgd/category.ts @@ -1,22 +1,12 @@ import { Route } from '@/types'; -import { getCurrentPath } from '@/utils/helpers'; -const __dirname = getCurrentPath(import.meta.url); -import cache from '@/utils/cache'; -import got from '@/utils/got'; -import timezone from '@/utils/timezone'; -import { parseDate } from '@/utils/parse-date'; -import { art } from '@/utils/render'; -import path from 'node:path'; -import MarkdownIt from 'markdown-it'; -const md = MarkdownIt({ - html: true, -}); +import ofetch from '@/utils/ofetch'; +import { rootUrl, apiRootUrl, parseResult, parseArticle } from './utils'; export const route: Route = { - path: '/:category?', + path: '/category/:category?', categories: ['new-media'], - example: '/utgd/method', + example: '/utgd/category/method', parameters: { category: '分类,可在对应分类页的 URL 中找到,默认为方法' }, features: { requireConfig: false, @@ -29,7 +19,7 @@ export const route: Route = { radar: [ { source: ['utgd.net/category/s/:category', 'utgd.net/'], - target: '/:category', + target: '/category/:category', }, ], name: '分类', @@ -42,61 +32,30 @@ export const route: Route = { async function handler(ctx) { const category = ctx.req.param('category') ?? 'method'; - const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20; + const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 9; - const rootUrl = 'https://utgd.net'; - const apiUrl = `${rootUrl}/api/v2/pages/`; + const apiUrl = `${apiRootUrl}/api/v2/categories`; const currentUrl = `${rootUrl}/category/s/${category}`; - const slugUrl = `${rootUrl}/api/v2/category/slug/${category}/`; + const slugUrl = `${apiRootUrl}/api/v2/category/slug/${category}/`; - let response = await got({ - method: 'get', - url: slugUrl, - }); + const categoryData = await ofetch(slugUrl); - const data = response.data; - - response = await got({ - method: 'get', - url: apiUrl, - searchParams: { - type: 'article.Article', - fields: `article_category(category_name),article_tag(tag_name),title,article_image,article_author,article_description,article_published_time`, - article_category: data.id, - order: '-article_published_time', - limit, + const response = await ofetch(`${apiUrl}/${categoryData.id}/related_articles`, { + query: { + page: 1, + page_size: limit, }, }); - const items = await Promise.all( - response.data.items.map((item) => - cache.tryGet(`untag-${item.id}`, async () => { - const authorResponse = await got({ - method: 'get', - url: `${rootUrl}/api/v2/user/profile/${item.article_author.id}/`, - }); + const list = parseResult(response.results, limit); - return { - title: item.title, - link: `${rootUrl}/article/${item.id}`, - description: art(path.join(__dirname, 'templates/description.art'), { - membership: item.article_for_membership, - image: item.article_image, - description: md.render(item.article_description), - }), - author: authorResponse.data.display_name, - pubDate: timezone(parseDate(item.article_published_time), +8), - category: [...item.article_category.map((c) => c.category_name), ...item.article_tag.map((t) => t.tag_name)], - }; - }) - ) - ); + const items = await Promise.all(list.map((item) => parseArticle(item))); return { - title: `UNTAG - ${data.category_name}`, + title: `UNTAG - ${categoryData.category_name}`, link: currentUrl, item: items, - image: data.category_image, - description: data.category_description, + image: categoryData.category_image, + description: categoryData.category_description, }; } diff --git a/lib/routes/utgd/timeline.ts b/lib/routes/utgd/timeline.ts index cd3d14778..1b23fcec6 100644 --- a/lib/routes/utgd/timeline.ts +++ b/lib/routes/utgd/timeline.ts @@ -1,17 +1,7 @@ import { Route } from '@/types'; -import { getCurrentPath } from '@/utils/helpers'; -const __dirname = getCurrentPath(import.meta.url); -import cache from '@/utils/cache'; -import got from '@/utils/got'; -import timezone from '@/utils/timezone'; -import { parseDate } from '@/utils/parse-date'; -import { art } from '@/utils/render'; -import path from 'node:path'; -import MarkdownIt from 'markdown-it'; -const md = MarkdownIt({ - html: true, -}); +import ofetch from '@/utils/ofetch'; +import { rootUrl, apiRootUrl, parseResult, parseArticle } from './utils'; export const route: Route = { path: '/timeline', @@ -40,42 +30,16 @@ export const route: Route = { async function handler(ctx) { const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20; - const rootUrl = 'https://utgd.net'; - const apiUrl = `${rootUrl}/api/v2/timeline/?page=1&page_size=${limit}`; - - const response = await got({ - method: 'get', - url: apiUrl, + const response = await ofetch(`${apiRootUrl}/api/v2/timeline/`, { + query: { + page: 1, + page_size: limit, + }, }); - const items = await Promise.all( - response.data.results.slice(0, limit).map((item) => - cache.tryGet(`untag-${item.id}`, async () => { - const detailResponse = await got({ - method: 'get', - url: `${rootUrl}/api/v2/article/${item.id}/`, - searchParams: { - fields: 'article_description,article_category(category_name),article_tag(tag_name)', - }, - }); + const list = parseResult(response.results, limit); - const data = detailResponse.data; - - return { - title: item.title, - link: `${rootUrl}/article/${item.id}`, - description: art(path.join(__dirname, 'templates/description.art'), { - membership: data.article_for_membership, - image: item.article_image, - description: md.render(data.article_description), - }), - author: item.article_author_displayname, - pubDate: timezone(parseDate(item.article_published_time), +8), - category: [...data.article_category.map((c) => c.category_name), ...data.article_tag.map((t) => t.tag_name)], - }; - }) - ) - ); + const items = await Promise.all(list.map((item) => parseArticle(item))); return { title: 'UNTAG', diff --git a/lib/routes/utgd/topic.ts b/lib/routes/utgd/topic.ts index e01fa5147..15642c88b 100644 --- a/lib/routes/utgd/topic.ts +++ b/lib/routes/utgd/topic.ts @@ -1,18 +1,8 @@ import { Route } from '@/types'; -import { getCurrentPath } from '@/utils/helpers'; -const __dirname = getCurrentPath(import.meta.url); -import cache from '@/utils/cache'; -import got from '@/utils/got'; -import timezone from '@/utils/timezone'; -import { parseDate } from '@/utils/parse-date'; -import { art } from '@/utils/render'; -import path from 'node:path'; -import MarkdownIt from 'markdown-it'; +import ofetch from '@/utils/ofetch'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -const md = MarkdownIt({ - html: true, -}); +import { rootUrl, apiRootUrl, parseResult, parseArticle } from './utils'; export const route: Route = { path: '/topic/:topic?', @@ -47,56 +37,24 @@ async function handler(ctx) { const topic = ctx.req.param('topic') ?? '在线阅读专栏'; const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20; - const rootUrl = 'https://utgd.net'; const currentUrl = `${rootUrl}/topic`; - const topicUrl = `${rootUrl}/api/v2/topic/`; + const topicUrl = `${apiRootUrl}/api/v2/topic/`; - let response = await got({ - method: 'get', - url: topicUrl, - }); + let response = await ofetch(topicUrl); - const topicItems = response.data.filter((i) => i.title === topic); + const topicItem = response.find((i) => i.title === topic); - if (!topicItems) { + if (!topicItem) { throw new InvalidParameterError(`No topic named ${topic}`); } - const topicItem = topicItems[0]; - const apiUrl = `${rootUrl}/api/v2/topic/${topicItem.id}/article/`; - response = await got({ - method: 'get', - url: apiUrl, - }); + response = await ofetch(apiUrl); - const items = await Promise.all( - response.data.slice(0, limit).map((item) => - cache.tryGet(`untag-${item.id}`, async () => { - const detailResponse = await got({ - method: 'get', - url: `${rootUrl}/api/v2/article/${item.id}/`, - searchParams: { - fields: 'article_description', - }, - }); + const list = parseResult(response.results, limit); - return { - title: item.title, - link: `${rootUrl}/article/${item.id}`, - description: art(path.join(__dirname, 'templates/description.art'), { - membership: item.article_for_membership, - image: item.article_image, - description: md.render(detailResponse.data.article_description), - }), - author: item.article_author_displayname, - pubDate: timezone(parseDate(item.article_published_time), +8), - category: [...item.article_category.map((c) => c.name), ...item.article_tag.map((t) => t.name)], - }; - }) - ) - ); + const items = await Promise.all(list.map((item) => parseArticle(item))); return { title: `UNTAG - ${topicItem.title}`, diff --git a/lib/routes/utgd/utils.ts b/lib/routes/utgd/utils.ts new file mode 100644 index 000000000..1239a428e --- /dev/null +++ b/lib/routes/utgd/utils.ts @@ -0,0 +1,41 @@ +import { getCurrentPath } from '@/utils/helpers'; +const __dirname = getCurrentPath(import.meta.url); + +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; +import timezone from '@/utils/timezone'; +import { parseDate } from '@/utils/parse-date'; +import { art } from '@/utils/render'; +import path from 'node:path'; +import MarkdownIt from 'markdown-it'; +const md = MarkdownIt({ + html: true, +}); + +export const rootUrl = 'https://utgd.net'; +export const apiRootUrl = 'https://api.utgd.net'; + +export const parseResult = (results, limit) => + results.slice(0, limit).map((item) => ({ + id: item.id, + title: item.title, + link: `${rootUrl}/article/${item.id}`, + author: item.article_author_displayname, + pubDate: timezone(parseDate(item.article_published_time), +8), + category: item.article_category.map((c) => c.category_name), + })); + +export const parseArticle = (item) => + cache.tryGet(`untag-${item.id}`, async () => { + const data = await ofetch(`${apiRootUrl}/api/v2/article/${item.id}/`); + + item.description = art(path.join(__dirname, 'templates/description.art'), { + membership: data.article_for_membership, + image: data.article_image, + description: md.render(data.article_description), + }); + + item.category = [...data.article_category.map((c) => c.category_name), ...data.article_tag.map((t) => t.tag_name)]; + + return item; + });