UNPKG

rsshub

Version:
118 lines (107 loc) β€’ 4.84 kB
import { Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import * as cheerio from 'cheerio'; import path from 'node:path'; import { art } from '@/utils/render'; const renderMedia = (media) => art(path.join(__dirname, 'templates/media.art'), { video: { cover: media.posterImages?.full?.href || media.posterImages?.default?.href, src: media.links?.source.mezzanine?.href || media.links?.source.HD?.href || media.links?.source.full?.href || media.links?.source.href, title: media.title, description: media.description, }, image: { src: media.url, alt: media.alt, caption: media.caption, credit: media.credit, }, }); const junkPattern = /inline\d+|alsosee/; const mediaPattern = /(photo|video)(\d+)/; export const route: Route = { path: '/news/:sport', name: 'News', maintainers: ['weijianduan0302'], example: '/espn/news/nba', categories: ['traditional-media'], parameters: { sport: 'sport category, can be nba, nfl, mlb, nhl etc.' }, description: `Get the news feed of the sport you love on ESPN. | Sport | sport | Sport | sport | |----------------------|---------|----------------|---------| | πŸ€ NBA | nba | 🎾 Tennis | tennis | | πŸ€ WNBA | wnba | ⛳️ Golf | golf | | 🏈 NFL | nfl | 🏏 Cricket | cricket | | ⚾️ MLB | mlb | ⚽️ Soccer | soccer | | πŸ’ NHL | nhl | 🏎️ F1 | f1 | | ⛹️ College Basketball | ncb | πŸ₯Š MMA | mma | | 🏟️️ College Football | ncf | 🏈 UFL | ufl | | πŸ‰ Rugby | rugby | πŸƒ Poker | poker |`, radar: [ { source: ['espn.com/:sport*'], target: '/news/:sport', }, ], handler: async (ctx) => { const { sport = 'nba' } = ctx.req.param(); const response = await ofetch(`https://onefeed.fan.api.espn.com/apis/v3/cached/contentEngine/oneFeed/leagues/${sport}?offset=0`, { headers: { accept: 'application/json', }, }); const handledTypes = new Set(['HeadlineNews', 'Story', 'Media', 'Shortstop']); const list = response.feed .filter((item) => handledTypes.has(item.data.now[0].type)) .map((item) => { const itemDetail = item.data.now[0]; const itemType = itemDetail.type; return { title: itemDetail.headline, link: itemDetail.links.web.href, author: itemDetail.byline, pubDate: item.date, // for videos and shortstops, no need to extract full text below description: itemType === 'Media' ? renderMedia(itemDetail.video[0]) : itemType === 'Shortstop' ? itemDetail.headline : '', }; }); const items = await Promise.all( list.map((item) => cache.tryGet(item.link, async () => { if (item.description === '') { const article = await ofetch(`${item.link}?xhr=1`, { headers: { accept: 'application/json', }, }); const $ = cheerio.load(article.content.story, null, false); $('*').each((_, ele) => { if (junkPattern.test(ele.name)) { $(ele).remove(); } if (mediaPattern.test(ele.name)) { const mediaType = ele.name.match(mediaPattern)[1] === 'photo' ? 'images' : 'video'; const mediaIndex = Number.parseInt(ele.name.match(mediaPattern)[2]) - 1; const media = article.content[mediaType][mediaIndex]; if (media) { $(ele).replaceWith(renderMedia(media)); } else { $(ele).remove(); } } }); item.description = $.html(); } return item; }) ) ); return { title: `ESPN ${sport.toUpperCase()} News`, link: `https://www.espn.com/espn/rss/${sport}/news`, item: items, }; }, };