diff --git a/lib/routes/railway/index.ts b/lib/routes/railway/index.ts new file mode 100644 index 000000000..ed8843190 --- /dev/null +++ b/lib/routes/railway/index.ts @@ -0,0 +1,73 @@ +import { Route, DataItem } from '@/types'; + +import cache from '@/utils/cache'; +import { load } from 'cheerio'; +import { parseDate } from '@/utils/parse-date'; +import ofetch from '@/utils/ofetch'; +import { Context } from 'hono'; + +export const route: Route = { + path: '/blog', + categories: ['blog'], + example: '/railway/blog', + url: 'blog.railway.com', + name: 'Blog', + maintainers: ['jihuayu'], + handler, +}; + +async function handler(ctx: Context) { + const limit = Number.parseInt(ctx.req.query('limit') || '10'); + + const items = await fetchArticles(limit); + + return { + title: 'Railway articles', + link: 'https://blog.railway.com', + item: items, + }; +} + +export const fetchArticles = async (limit: number): Promise => { + const page = await ofetch('https://blog.railway.com/rss.xml', { + responseType: 'text', + }); + + const $ = load(page, { xml: true }); + + return Promise.all( + $('item') + .toArray() + .slice(0, limit) + .map>((element) => { + const id = $(element).find('guid').text(); + + return cache.tryGet(`railway:blogs:${id}`, async () => { + const title = $(element).find('title').text(); + const pubDate = $(element).find('pubDate').text(); + const link = $(element).find('link').text(); + + const { content } = await fetchArticleDetails(link); + + return { + guid: id, + title, + link, + pubDate: parseDate(pubDate), + description: content, + } as DataItem; + }) as Promise; + }) + ); +}; + +export const fetchArticleDetails = async (url: string) => { + const page = await ofetch(url); + const $ = load(page); + + const $article = $('article > section '); + + return { + content: $article.html() ?? undefined, + }; +}; diff --git a/lib/routes/railway/namespace.ts b/lib/routes/railway/namespace.ts new file mode 100644 index 000000000..520ffb2a5 --- /dev/null +++ b/lib/routes/railway/namespace.ts @@ -0,0 +1,8 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'Railway', + url: 'railway.com', + description: '', + lang: 'en', +};