-
-
Notifications
You must be signed in to change notification settings - Fork 83
/
index.js
94 lines (81 loc) · 2.06 KB
/
index.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
import os from 'node:os';
import got, {CancelError} from 'got';
import {publicIpv4, publicIpv6} from 'public-ip';
import pAny from 'p-any';
import pTimeout from 'p-timeout';
const appleCheck = options => {
const gotPromise = got('https://captive.apple.com/hotspot-detect.html', {
timeout: {
request: options.timeout,
},
dnsLookupIpVersion: options.ipVersion,
headers: {
'user-agent': 'CaptiveNetworkSupport/1.0 wispr',
},
});
const promise = (async () => {
try {
const {body} = await gotPromise;
if (!body?.includes('Success')) {
throw new Error('Apple check failed');
}
} catch (error) {
if (!(error instanceof CancelError)) {
throw error;
}
}
})();
promise.cancel = gotPromise.cancel;
return promise;
};
// Note: It cannot be `async`` as then it looses the `.cancel()` method.
export default function isOnline(options) {
options = {
timeout: 5000,
ipVersion: 4,
...options,
};
if (Object.values(os.networkInterfaces()).flat().every(({internal}) => internal)) {
return false;
}
if (![4, 6].includes(options.ipVersion)) {
throw new TypeError('`ipVersion` must be 4 or 6');
}
const publicIpFunction = options.ipVersion === 4 ? publicIpv4 : publicIpv6;
const queries = [];
const promise = pAny([
(async () => {
const query = publicIpFunction(options);
queries.push(query);
await query;
return true;
})(),
(async () => {
const query = publicIpFunction({...options, onlyHttps: true});
queries.push(query);
await query;
return true;
})(),
(async () => {
const query = appleCheck(options);
queries.push(query);
await query;
return true;
})(),
]);
return pTimeout(promise, {milliseconds: options.timeout}).catch(() => { // eslint-disable-line promise/prefer-await-to-then
for (const query of queries) {
query.cancel();
}
return false;
});
// TODO: Use this instead when supporting AbortController.
// try {
// return await pTimeout(promise, options.timeout);
// } catch {
// for (const query of queries) {
// query.cancel();
// }
// return false;
// }
}