Skip to content

Commit d91d468

Browse files
authored
feat(route): add Cloudflare Status (#20514)
* feat(route): add Cloudflare Status * fix: missing type
1 parent 4608657 commit d91d468

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { type Data, type DataItem, type Route, ViewType } from '@/types';
2+
3+
import { art } from '@/utils/render';
4+
import ofetch from '@/utils/ofetch';
5+
import { parseDate } from '@/utils/parse-date';
6+
7+
import { type CheerioAPI, type Cheerio, load } from 'cheerio';
8+
import type { Element } from 'domhandler';
9+
import { type Context } from 'hono';
10+
import path from 'node:path';
11+
12+
export const handler = async (ctx: Context): Promise<Data> => {
13+
const limit: number = Number.parseInt(ctx.req.query('limit') ?? '100', 10);
14+
15+
const baseUrl: string = 'https://www.cloudflarestatus.com';
16+
17+
const response = await ofetch(baseUrl);
18+
const $: CheerioAPI = load(response);
19+
const language = $('html').attr('lang') ?? 'en';
20+
21+
$('div.incidents-list').remove();
22+
23+
const items: DataItem[] = $('div.update')
24+
.slice(0, limit)
25+
.toArray()
26+
.map((el): Element => {
27+
const $el: Cheerio<Element> = $(el);
28+
29+
const $actualTitleEl: Cheerio<Element> = $el.parent().parent().find('a');
30+
const actualTitle: string = $actualTitleEl.text();
31+
const type: string = $el.find('strong').first().text();
32+
const text: string = $el.find('span.whitespace-pre-wrap').first().text();
33+
34+
const title: string = `${type ? `${type} - ` : ''}${text}`;
35+
const description: string | undefined = art(path.join(__dirname, 'templates/description.art'), {
36+
actualTitle,
37+
description: $el.html(),
38+
});
39+
const pubDateStr: string | undefined = $el.find('span.ago').attr('data-datetime-unix');
40+
const linkUrl: string | undefined = $actualTitleEl.attr('href') ? new URL($actualTitleEl.attr('href') as string, baseUrl).toString() : undefined;
41+
const categories: string[] = [type].filter(Boolean);
42+
const guid: string = linkUrl ? `${linkUrl}#${pubDateStr}` : '';
43+
const upDatedStr: string | undefined = pubDateStr;
44+
45+
const processedItem: DataItem = {
46+
title,
47+
description,
48+
pubDate: pubDateStr ? parseDate(pubDateStr, 'x') : undefined,
49+
link: linkUrl,
50+
category: categories,
51+
guid,
52+
id: guid,
53+
content: {
54+
html: description,
55+
text: description,
56+
},
57+
updated: upDatedStr ? parseDate(upDatedStr, 'x') : undefined,
58+
language,
59+
};
60+
61+
return processedItem;
62+
});
63+
64+
return {
65+
title: $('title').text(),
66+
description: $('meta[name="description"]').attr('content'),
67+
link: baseUrl,
68+
item: items,
69+
allowEmpty: true,
70+
language,
71+
id: baseUrl,
72+
};
73+
};
74+
75+
export const route: Route = {
76+
path: '/',
77+
name: 'Status',
78+
url: 'www.cloudflarestatus.com',
79+
maintainers: ['nczitzk'],
80+
handler,
81+
example: '/cloudflarestatus',
82+
parameters: undefined,
83+
description: undefined,
84+
categories: ['programming'],
85+
features: {
86+
requireConfig: false,
87+
requirePuppeteer: false,
88+
antiCrawler: false,
89+
supportRadar: true,
90+
supportBT: false,
91+
supportPodcast: false,
92+
supportScihub: false,
93+
},
94+
radar: [
95+
{
96+
source: ['www.cloudflarestatus.com'],
97+
target: '/',
98+
},
99+
],
100+
view: ViewType.Notifications,
101+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { Namespace } from '@/types';
2+
3+
export const namespace: Namespace = {
4+
name: 'Cloudflare Status',
5+
url: 'cloudflarestatus.com',
6+
categories: ['programming'],
7+
description: '',
8+
lang: 'en',
9+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{{ if actualTitle }}
2+
<h2>{{ actualTitle}}</h2>
3+
{{ /if }}
4+
5+
{{ if description }}
6+
{{@ description }}
7+
{{ /if }}

0 commit comments

Comments
 (0)