UNPKG

rsshub

Version:
107 lines (95 loc) 3.3 kB
import type { Data, DataItem, Route } from '@/types'; import type { Context } from 'hono'; import { load } from 'cheerio'; import puppeteer from '@/utils/puppeteer'; import logger from '@/utils/logger'; import { art } from '@/utils/render'; import path from 'node:path'; import { parseDate } from '@/utils/parse-date'; export const route: Route = { name: '漏洞', categories: ['programming'], path: '/zeroday/vulnerability/:status?', example: '/hitcon/zeroday/vulnerability', parameters: { status: '漏洞状态,见下表', }, maintainers: ['KarasuShin'], radar: [ { source: ['zeroday.hitcon.org/vulnerability/:status?'], }, ], features: { requirePuppeteer: true, }, handler, description: `| 缺省 | all | closed | disclosed | patching | | ------ | ---- | ------ | --------- | -------- | | 活動中 | 全部 | 關閉 | 公開 | 修補中 |`, }; const baseUrl = 'https://zeroday.hitcon.org/vulnerability'; const titleMap = { all: '全部', closed: '關閉', disclosed: '公開', patching: '修補中', }; async function handler(ctx: Context): Promise<Data> { let url = baseUrl; const status = ctx.req.param('status'); if (status) { url += `/${status}`; } const browser = await puppeteer(); const page = await browser.newPage(); await page.setRequestInterception(true); page.on('request', (request) => { request.resourceType() === 'document' ? request.continue() : request.abort(); }); logger.http(`Requesting ${url}`); await page.goto(url, { waitUntil: 'domcontentloaded', }); const response = await page.evaluate(() => document.documentElement.innerHTML); await browser.close(); const $ = load(response); const items: DataItem[] = $('.zdui-strip-list>li') .toArray() .map((el) => { const title = $(el).find('.title a'); const vulData = $(el).find('.vul-data'); const code = vulData .find('.code') .contents() .filter(function () { return this.nodeType === 3; }) .text(); const risk = vulData.find('.risk span').eq(1).text(); const vender = vulData.find('.vender').find('.v-name-full').text(); const status = vulData.find('.status').text().replace('Status:', '').trim(); const date = vulData.find('.date').text().replace('Date:', '').trim(); const reporter = vulData.find('.zdui-author-badge').find('a>span').text(); const description = art(path.join(__dirname, 'templates/zeroday.art'), { code, risk, vender, status, date, reporter, }); return { title: title.text(), link: title.attr('href'), description, pubDate: parseDate(date), }; }); return { title: status ? (titleMap[status] ?? 'ZeroDay') : '活動中', link: url, item: items, image: 'https://zeroday.hitcon.org/images/favicon/favicon.png', }; }