Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from diygod:master #4

Merged
merged 7 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions lib/routes/500px/tribe-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Route } from '@/types';
import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);

import cache from '@/utils/cache';
import { parseDate } from '@/utils/parse-date';
import { art } from '@/utils/render';
import path from 'node:path';
Expand All @@ -14,14 +13,6 @@ export const route: Route = {
categories: ['picture'],
example: '/500px/tribe/set/f5de0b8aa6d54ec486f5e79616418001',
parameters: { id: '部落 ID' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: '部落影集',
maintainers: ['TonyRL'],
handler,
Expand All @@ -31,8 +22,8 @@ async function handler(ctx) {
const id = ctx.req.param('id');
const limit = Number.parseInt(ctx.req.query('limit')) || 100;

const { tribe } = await getTribeDetail(id, cache.tryGet);
const tribeSets = await getTribeSets(id, limit, cache.tryGet);
const { tribe } = await getTribeDetail(id);
const tribeSets = await getTribeSets(id, limit);

const items = tribeSets.map((item) => ({
title: item.title,
Expand Down
60 changes: 0 additions & 60 deletions lib/routes/500px/user.ts

This file was deleted.

45 changes: 23 additions & 22 deletions lib/routes/500px/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import got from '@/utils/got';
import ofetch from '@/utils/ofetch';
import cache from '@/utils/cache';
import { load } from 'cheerio';
import { config } from '@/config';

Expand All @@ -24,39 +25,39 @@ const headers = {
'X-Tingyun-Id': `Fm3hXcTiLT8;r=${Date.now() % 1e8}`,
};

const getUserInfoFromUsername = (username, tryGet) =>
tryGet(`500px:user:${username}`, async () => {
const { data } = await got(`${baseUrl}/${username}`);
const getUserInfoFromUsername = (username) =>
cache.tryGet(`500px:user:${username}`, async () => {
const data = await ofetch(`${baseUrl}/${username}`);
const $ = load(data);
return JSON.parse(
$('script[type="text/javascript"]')
.text()
.match(/var cur_user = new Object\((.*?)\);/)[1]
.match(/var cur_user = new Object\((.*?)\);/)?.[1] || '{}'
);
});

const getUserInfoFromId = (id, tryGet) =>
tryGet(`500px:user:indexInfo:${id}`, async () => {
const { data } = await got(`${baseUrl}/community/v2/user/indexInfo`, {
const getUserInfoFromId = (id) =>
cache.tryGet(`500px:user:indexInfo:${id}`, async () => {
const data = await ofetch(`${baseUrl}/community/v2/user/indexInfo`, {
headers: {
...headers,
},
searchParams: {
query: {
queriedUserId: id,
},
});
return data.data;
});

const getUserWorks = (id, limit, tryGet) =>
tryGet(
const getUserWorks = (id, limit) =>
cache.tryGet(
`500px:user:profile:${id}`,
async () => {
const { data } = await got(`${baseUrl}/community/v2/user/profile`, {
const data = await ofetch(`${baseUrl}/community/v2/user/profile`, {
headers: {
...headers,
},
searchParams: {
query: {
resourceType: '0,2,4',
imgsize: 'p1,p2,p3,p4',
queriedUserId: id,
Expand All @@ -66,21 +67,21 @@ const getUserWorks = (id, limit, tryGet) =>
type: 'json',
},
});
return data.data;
return data;
},
config.cache.routeExpire,
false
);

const getTribeDetail = (id, tryGet) =>
tryGet(
const getTribeDetail = (id) =>
cache.tryGet(
`500px:tribeDetail:${id}`,
async () => {
const { data } = await got(`${baseUrl}/community/tribe/tribeDetail`, {
const data = await ofetch(`${baseUrl}/community/tribe/tribeDetail`, {
headers: {
...headers,
},
searchParams: {
query: {
tribeId: id,
},
});
Expand All @@ -90,15 +91,15 @@ const getTribeDetail = (id, tryGet) =>
false
);

const getTribeSets = (id, limit, tryGet) =>
tryGet(
const getTribeSets = (id, limit) =>
cache.tryGet(
`500px:tribeSets:${id}`,
async () => {
const { data } = await got(`${baseUrl}/community/tribe/getTribeSetsV2`, {
const data = await ofetch(`${baseUrl}/community/tribe/getTribeSetsV2`, {
headers: {
...headers,
},
searchParams: {
query: {
tribeId: id,
privacy: 1,
page: 1,
Expand Down
8 changes: 4 additions & 4 deletions lib/routes/discourse/notifications.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Route } from '@/types';
import cache from '@/utils/cache';
import { getConfig } from './utils';
import got from '@/utils/got';
import ofetch from '@/utils/ofetch';

export const route: Route = {
path: '/:configId/notifications/:fulltext?',
Expand Down Expand Up @@ -32,7 +32,7 @@ If you opt to enable \`fulltext\` feature, consider adding \`limit\` parameter t
async function handler(ctx) {
const { link, key } = getConfig(ctx);

const response = await got(`${link}/notifications.json`, { headers: { 'User-Api-Key': key } }).json();
const response = await ofetch(`${link}/notifications.json`, { headers: { 'User-Api-Key': key } });
let items = response.notifications.slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 10).map((e) => ({
title: e.fancy_title ?? e.data.badge_name,
link: `${link}/${Object.hasOwn(e.data, 'badge_id') ? `badges/${e.data.badge_id}/${e.data.badge_slug}?username=${e.data.username}` : `t/topic/${e.topic_id}/${e.post_number}`}`,
Expand All @@ -48,7 +48,7 @@ async function handler(ctx) {
if (e.original_post_id) {
const post_link = `${link}/posts/${e.original_post_id}.json`;
return cache.tryGet(post_link, async () => {
const { cooked } = await got(post_link, { headers: { 'User-Api-Key': key } }).json();
const { cooked } = await ofetch(post_link, { headers: { 'User-Api-Key': key } });
return { ...e, description: cooked };
});
} else {
Expand All @@ -58,7 +58,7 @@ async function handler(ctx) {
);
}

const { about } = await got(`${link}/about.json`, { headers: { 'User-Api-Key': key } }).json();
const { about } = await ofetch(`${link}/about.json`, { headers: { 'User-Api-Key': key } });
return {
title: `${about.title} - Notifications`,
description: about.description,
Expand Down
6 changes: 6 additions & 0 deletions lib/routes/hitcon/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { Namespace } from '@/types';

export const namespace: Namespace = {
name: 'HITCON',
url: 'hitcon.org',
};
8 changes: 8 additions & 0 deletions lib/routes/hitcon/templates/zeroday.art
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<ul>
<li>{{ vender }}</li>
<li>ZDID: {{ code }}</li>
<li>風險: {{ risk }}</li>
<li>處理狀態: {{ status }}</li>
<li>通報者: {{ reporter }}</li>
<li>通報日期: {{ date }}</li>
</ul>
109 changes: 109 additions & 0 deletions lib/routes/hitcon/zeroday.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
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';
import { getCurrentPath } from '@/utils/helpers';

const __dirname = getCurrentPath(import.meta.url);

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);
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',
};
}
Loading