/
index.ts
115 lines (102 loc) · 3.51 KB
/
index.ts
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
import puppeteer, { Browser } from 'puppeteer';
import fetch from 'node-fetch';
const fritzUrl: string = process.env.FRITZ_URL!;
const user: string = process.env.FRITZ_USER!;
const password: string = process.env.FRITZ_PWD!;
const endpoint: string = process.env.SERVER_ENDPOINT!;
function timeout(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
class Device {
mac: string;
ip: string;
constructor(mac: string, ip: string) {
this.ip = ip;
this.mac = mac;
}
equals(other: Device): boolean {
return (other.ip + other.mac) === (this.ip + this.mac);
}
}
let activeDevices: Device[] = [];
async function main(): Promise<void> {
let browser: Browser | undefined = undefined;
browser = await puppeteer.launch({
headless: true,
defaultViewport: { width: 1500, height: 1000 },
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser!.newPage();
await page.goto(fritzUrl, { waitUntil: 'networkidle2' });
page.select('select#uiViewUser', user);
await page.type('input[type="password"]', password, { delay: 5 });
await page.click('button[type="submit"]');
await page.waitForNetworkIdle();
await timeout(2000);
page.on('response', async event => {
try {
if (event.url().includes('data.lua')) {
if (event.headers()['content-type'].includes('application/json')) {
const json = await event.json();
if (json.pid === 'netDev') {
const active = json.data.active as any[];
activeDevices = [];
for (const element of active) {
activeDevices.push(new Device(element.mac, element.ipv4.ip));
}
checkChanges();
}
}
}
} catch (error) {
console.log(error);
}
});
await page.click('a[id="lan"]', { delay: 1000 });
while (true) {
await timeout(2000);
await page.click('a[id="net"]', { delay: 1000 });
await timeout(40000);
await page.click('a[id="meshNet"]', { delay: 1000 });
}
}
let lastDeviceSnapshot: Device[] = [];
function checkChanges(): void {
lastDeviceSnapshot.sort((a, b) => a.mac.localeCompare(b.mac));
activeDevices.sort((a, b) => a.mac.localeCompare(b.mac));
for (const device of activeDevices) {
const result = lastDeviceSnapshot.find(lDevice => device.equals(lDevice));
if (!result) {
deviceAppeared(device);
}
}
for (const lDevice of lastDeviceSnapshot) {
const result = activeDevices.find(device => device.equals(lDevice));
if (!result) {
deviceDisappeared(lDevice);
}
}
if (JSON.stringify(lastDeviceSnapshot) !== JSON.stringify(activeDevices)) {
postChanges();
}
lastDeviceSnapshot = [...activeDevices];
}
function deviceAppeared(device: Device): void {
console.log('Appeared', device);
}
function deviceDisappeared(device: Device): void {
console.log('Disappeared', device);
}
async function postChanges(): Promise<void> {
try {
const response = await fetch(endpoint, {
method: 'post',
body: JSON.stringify(activeDevices),
headers: { 'Content-Type': 'application/json' }
});
console.log(await response.text());
} catch (error) {
console.log(error);
}
}
main();