const got = require('@/utils/got'); const cheerio = require('cheerio'); const { parseDate } = require('@/utils/parse-date'); module.exports = async (ctx) => { const section = ctx.params.section ?? 'index'; const type = ctx.params.type ?? 'sources'; const rootUrl = 'https://news.ycombinator.com'; const currentUrl = `${rootUrl}${section === 'index' ? '' : `/${section}`}`; const response = await got({ method: 'get', url: currentUrl, }); const $ = cheerio.load(response.data); const list = $('.athing') .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 30) .map((_, thing) => { thing = $(thing); const item = {}; item.guid = thing.attr('id'); item.title = thing.find('.titlelink').text(); item.category = thing.find('.sitestr').text(); item.author = thing.next().find('.hnuser').text(); item.pubDate = parseDate(thing.next().attr('title')); item.link = `${rootUrl}/item?id=${item.guid}`; item.origin = thing.find('.titlelink').attr('href'); item.comments = thing.next().find('a').last().text().split(' comment')[0]; item.guid = type === 'sources' ? item.guid : `${item.guid}${item.comments === 'discuss' ? '' : `-${item.comments}`}`; item.description = `Comments on Hacker News | Source`; return item; }) .get(); const items = await Promise.all( list.map((item) => ctx.cache.tryGet(item.guid, async () => { if (item.comments !== 'discuss' && type !== 'sources') { const detailResponse = await got({ method: 'get', url: item.link, }); const content = cheerio.load(detailResponse.data); content('.reply').remove(); item.description = ''; content('.comtr').each(function () { const author = content(this).find('.hnuser'); const comment = content(this).find('.commtext'); item.description += `
${author.text()}` + `  ` + `${content(this).find('.age').attr('title')}
`; const commentText = comment.clone(); commentText.find('p').remove(); commentText.html(`

${commentText.text()}

`); commentText.append( comment .find('p') .toArray() .map((p) => `

${content(p).html()}

`) ); item.description += `
${commentText.html()}
`; }); } item.link = type === 'sources' ? item.origin : item.link; delete item.origin; return item; }) ) ); ctx.state.data = { title: $('title').text(), link: currentUrl, item: items, }; };