forked from jason5ng32/MyIP
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcfradar.js
185 lines (163 loc) · 5.99 KB
/
cfradar.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import { parse } from 'dotenv';
import { refererCheck } from '../common/referer-check.js';
// 创建一个用于设置 headers 的通用函数
function createFetchOptions() {
return {
headers: {
'Authorization': `Bearer ${process.env.CLOUDFLARE_API}`,
'Content-Type': 'application/json'
}
};
}
// ASN 信息
async function getASNInfo(asn) {
try {
const url = `https://api.cloudflare.com/client/v4/radar/entities/asns/${asn}`;
const headers = createFetchOptions().headers;
const options = { headers };
const response = await fetch(url, options);
const json = await response.json();
return json;
} catch (error) {
console.error(error);
throw new Error('Failed to fetch ASN info');
}
};
// IP 版本分布
async function getASNIPVersion(asn) {
try {
const url = `https://api.cloudflare.com/client/v4/radar/http/summary/ip_version?asn=${asn}&dateRange=7d`;
const headers = createFetchOptions().headers;
const options = { headers };
const response = await fetch(url, options);
const json = await response.json();
return json;
} catch (error) {
console.error(error);
throw new Error('Failed to fetch ASN IP version');
}
};
// HTTP 协议分布
async function getASNHTTPProtocol(asn) {
try {
const url = `https://api.cloudflare.com/client/v4/radar/http/summary/http_protocol?asn=${asn}&dateRange=7d`;
const headers = createFetchOptions().headers;
const options = { headers };
const response = await fetch(url, options);
const json = await response.json();
return json;
} catch (error) {
console.error(error);
throw new Error('Failed to fetch ASN HTTP protocol');
}
};
// 设备分布
async function getASNDeviceType(asn) {
try {
const url = `https://api.cloudflare.com/client/v4/radar/http/summary/device_type?asn=${asn}&dateRange=7d`;
const headers = createFetchOptions().headers;
const options = { headers };
const response = await fetch(url, options);
const json = await response.json();
return json;
} catch (error) {
console.error(error);
throw new Error('Failed to fetch ASN device type');
}
};
// 机器人分布
async function getASNBotType(asn) {
try {
const url = `https://api.cloudflare.com/client/v4/radar/http/summary/bot_class?asn=${asn}&dateRange=7d`;
const headers = createFetchOptions().headers;
const options = { headers };
const response = await fetch(url, options);
const json = await response.json();
return json;
} catch (error) {
console.error(error);
throw new Error('Failed to fetch ASN bot type');
}
};
// 验证 asn 是否合法
function isValidASN(asn) {
return /^[0-9]+$/.test(asn);
};
// 格式化输出
function formatData(data) {
const { asnName, asnOrgName, estimatedUsers, IPv4_Pct, IPv6_Pct, HTTP_Pct, HTTPS_Pct, Desktop_Pct, Mobile_Pct, Bot_Pct, Human_Pct } = data;
const formattedData = {
asnName,
asnOrgName,
estimatedUsers: parseFloat(estimatedUsers).toLocaleString(),
IPv4_Pct: `${parseFloat(IPv4_Pct).toFixed(2)}%`,
IPv6_Pct: `${parseFloat(IPv6_Pct).toFixed(2)}%`,
HTTP_Pct: `${parseFloat(HTTP_Pct).toFixed(2)}%`,
HTTPS_Pct: `${parseFloat(HTTPS_Pct).toFixed(2)}%`,
Desktop_Pct: `${parseFloat(Desktop_Pct).toFixed(2)}%`,
Mobile_Pct: `${parseFloat(Mobile_Pct).toFixed(2)}%`,
Bot_Pct: `${parseFloat(Bot_Pct).toFixed(2)}%`,
Human_Pct: `${parseFloat(Human_Pct).toFixed(2)}%`
};
return formattedData;
}
// 过滤不存在的字段
function filterData(data) {
for (const key in data) {
if (data[key] === 'NaN' || data[key] === 'NaN%') {
delete data[key];
}
}
return data;
}
// 导出函数
export default async (req, res) => {
// 限制只能从指定域名访问
const referer = req.headers.referer;
if (!refererCheck(referer)) {
return res.status(403).json({ error: referer ? 'Access denied' : 'What are you doing?' });
}
const asn = req.query.asn;
if (!asn) {
return res.status(400).json({ error: 'No ASN provided' });
}
if (!isValidASN(asn)) {
return res.status(400).json({ error: 'Invalid ASN' });
}
try {
const results = await Promise.allSettled([
getASNInfo(asn),
getASNIPVersion(asn),
getASNHTTPProtocol(asn),
getASNDeviceType(asn),
getASNBotType(asn)
]);
// 直接转换每个结果,如果状态是 'fulfilled' 则返回值,否则返回一个包含错误信息的对象
const response = results.map(result => {
return result.status === 'fulfilled' ? result.value : { error: 'Failed to fetch data' };
});
// 清洗数据
function cleanUpResponseData(data) {
return {
asnName: data[0]?.result?.asn?.name,
asnOrgName: data[0]?.result?.asn?.orgName,
estimatedUsers: data[0]?.result?.asn?.estimatedUsers?.estimatedUsers,
IPv4_Pct: data[1]?.result?.summary_0?.IPv4,
IPv6_Pct: data[1]?.result?.summary_0?.IPv6,
HTTP_Pct: data[2]?.result?.summary_0?.http,
HTTPS_Pct: data[2]?.result?.summary_0?.https,
Desktop_Pct: data[3]?.result?.summary_0?.desktop,
Mobile_Pct: data[3]?.result?.summary_0?.mobile,
Bot_Pct: data[4]?.result?.summary_0?.bot,
Human_Pct: data[4]?.result?.summary_0?.human
};
}
const cleanedResponse = cleanUpResponseData(response);
const finalResponse = formatData(cleanedResponse);
filterData(finalResponse);
res.json(finalResponse);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
}