Adapt SurrealDB

This commit is contained in:
Aelita4 2022-09-16 18:30:37 +02:00
parent 41995c90c2
commit e7c6a51752
Signed by: Aelita4
GPG Key ID: E4773B4E7238A472
9 changed files with 229 additions and 47 deletions

130
package-lock.json generated
View File

@ -15,7 +15,8 @@
"express": "^4.18.1", "express": "^4.18.1",
"express-session": "^1.17.3", "express-session": "^1.17.3",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"ping": "^0.4.2" "ping": "^0.4.2",
"surrealdb.js": "^0.3.1"
}, },
"devDependencies": { "devDependencies": {
"@types/bcrypt": "^5.0.0", "@types/bcrypt": "^5.0.0",
@ -529,6 +530,19 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/bufferutil": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz",
"integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
"node-gyp-build": "^4.3.0"
},
"engines": {
"node": ">=6.14.2"
}
},
"node_modules/bytes": { "node_modules/bytes": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@ -1820,6 +1834,17 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}, },
"node_modules/nanoid": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz",
"integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==",
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^14 || ^16 || >=18"
}
},
"node_modules/natural-compare": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -1858,6 +1883,17 @@
} }
} }
}, },
"node_modules/node-gyp-build": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
"integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==",
"optional": true,
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/nopt": { "node_modules/nopt": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@ -2466,6 +2502,19 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/surrealdb.js": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/surrealdb.js/-/surrealdb.js-0.3.1.tgz",
"integrity": "sha512-qVd3xIaZ120KClGBe5WKDswwI2y7ZYjXfhI2F2eRvr1Uv9t/tz8tF0heqdDXXfPqqZA4S2GadEwjBkGSIRNBCw==",
"dependencies": {
"nanoid": "^4.0.0",
"ws": "^8.8.1"
},
"optionalDependencies": {
"bufferutil": "^4.0.6",
"utf-8-validate": "^5.0.9"
}
},
"node_modules/tar": { "node_modules/tar": {
"version": "6.1.11", "version": "6.1.11",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
@ -2595,6 +2644,19 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/utf-8-validate": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz",
"integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
"node-gyp-build": "^4.3.0"
},
"engines": {
"node": ">=6.14.2"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -2673,6 +2735,26 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}, },
"node_modules/ws": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz",
"integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/yallist": { "node_modules/yallist": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@ -3104,6 +3186,15 @@
"fill-range": "^7.0.1" "fill-range": "^7.0.1"
} }
}, },
"bufferutil": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz",
"integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==",
"optional": true,
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"bytes": { "bytes": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@ -4086,6 +4177,11 @@
} }
} }
}, },
"nanoid": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz",
"integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg=="
},
"natural-compare": { "natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -4110,6 +4206,12 @@
"whatwg-url": "^5.0.0" "whatwg-url": "^5.0.0"
} }
}, },
"node-gyp-build": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
"integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==",
"optional": true
},
"nopt": { "nopt": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@ -4530,6 +4632,17 @@
"has-flag": "^4.0.0" "has-flag": "^4.0.0"
} }
}, },
"surrealdb.js": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/surrealdb.js/-/surrealdb.js-0.3.1.tgz",
"integrity": "sha512-qVd3xIaZ120KClGBe5WKDswwI2y7ZYjXfhI2F2eRvr1Uv9t/tz8tF0heqdDXXfPqqZA4S2GadEwjBkGSIRNBCw==",
"requires": {
"bufferutil": "^4.0.6",
"nanoid": "^4.0.0",
"utf-8-validate": "^5.0.9",
"ws": "^8.8.1"
}
},
"tar": { "tar": {
"version": "6.1.11", "version": "6.1.11",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
@ -4625,6 +4738,15 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"utf-8-validate": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz",
"integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==",
"optional": true,
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -4688,6 +4810,12 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}, },
"ws": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz",
"integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==",
"requires": {}
},
"yallist": { "yallist": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",

View File

@ -17,7 +17,8 @@
"express": "^4.18.1", "express": "^4.18.1",
"express-session": "^1.17.3", "express-session": "^1.17.3",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"ping": "^0.4.2" "ping": "^0.4.2",
"surrealdb.js": "^0.3.1"
}, },
"devDependencies": { "devDependencies": {
"@types/bcrypt": "^5.0.0", "@types/bcrypt": "^5.0.0",

View File

@ -1,9 +1,10 @@
import express from 'express'; import express, { NextFunction } from 'express';
import Ping from 'ping'; import Ping from 'ping';
import { readdirSync } from 'fs'; import { readdirSync } from 'fs';
import sessions from "express-session" import sessions from "express-session"
import cookieParser from "cookie-parser" import cookieParser from "cookie-parser"
import mysql from 'mysql' //@ts-ignore
import Surreal from 'surrealdb.js'
import bcrypt from 'bcrypt' import bcrypt from 'bcrypt'
import url from 'url'; import url from 'url';
@ -19,23 +20,29 @@ const ping = async (host: string) => {
const getIP = () : Promise<string[]> => { const getIP = () : Promise<string[]> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
connection.query("SELECT * FROM ips", async (err, results, fields) => { connection.query("SELECT * FROM ips").then((data : any) => {
const addresses = [...data[0].result.slice()].map(a => a.ip);
resolve(addresses);
}).catch((err : any) => {
reject(err);
});
/*connection.query("SELECT * FROM ips", async (err, results, fields) => {
if(err) reject(err); if(err) reject(err);
const addresses = [...results.slice()].map(a => a.ip); const addresses = [...results.slice()].map(a => a.ip);
resolve(addresses); resolve(addresses);
}); });*/
}); });
} }
const connection = mysql.createConnection({ const connection = new Surreal("http://127.0.0.1:8000/rpc");
host: "mysql",
await connection.signin({
user: "root", user: "root",
password: "root", pass: "root"
database: "sshmon"
}); });
connection.connect(); await connection.use("sshmon", "sshmon");
const app = express(); const app = express();
@ -67,6 +74,11 @@ routes.forEach(async route => {
} }
}); });
app.all("*", (req, res, next) => {
console.log(`${req.method} ${req.httpVersion} ${req.path}`);
next();
});
app.listen(8080, () => console.log('rdy')); app.listen(8080, () => console.log('rdy'));
export interface Data { export interface Data {

View File

@ -5,19 +5,25 @@ export default {
method: "GET", method: "GET",
url: "/addIP/:ip", url: "/addIP/:ip",
callback: async (data: any, req: Request, res: Response) => { callback: async (data: any, req: Request, res: Response) => {
connection.query("SELECT * FROM ips WHERE ip = ?", req.params.ip, (err, results, fields) => { connection.query("SELECT * FROM ips WHERE ip=$ip", {
if(err) throw err; ip: req.params.ip
}).then((result: any) => {
if(results.length > 0) { if(result[0].result.length > 0) {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ status: "OK" })); res.end(JSON.stringify({ status: "OK" }));
} else { } else {
connection.query("INSERT INTO ips VALUES (NULL, ?)", [req.params.ip], (errr, resultss, fieldss) => { connection.query("CREATE ips SET ip=$ip", {
if(errr) throw errr ip: req.params.ip
}).then((resultt: any) => {
data.pings.set(req.params.ip, `${Date.now()}_1`);
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ status: "OK" })); res.end(JSON.stringify({ status: "OK" }));
}).catch((err: any) => {
throw err;
}); });
} }
}).catch((err: any) => {
throw err;
}); });
} }
} }

View File

@ -5,12 +5,12 @@ export default {
method: "POST", method: "POST",
url: "/loginUser", url: "/loginUser",
callback: async (data: any, req: Request, res: Response) => { callback: async (data: any, req: Request, res: Response) => {
connection.query(`SELECT * FROM users WHERE username=$user`, {
connection.query("SELECT * FROM users WHERE username = ?", req.body.username, async (err, results, fields) => { user: req.body.username
if(err) throw err; }).then(async (result: any) => {
if(results.length === 0) res.render("pages/login.ejs", { invalid: "baduserorpass" }); if(result[0].result.length === 0) res.render("pages/login.ejs", { invalid: "baduserorpass" });
else { else {
const compare = await bcrypt.compare(req.body.password, results[0].password); const compare = await bcrypt.compare(req.body.password, result[0].result[0].password);
if(compare) { if(compare) {
const session = req.session; const session = req.session;
//@ts-ignore //@ts-ignore
@ -23,6 +23,8 @@ export default {
res.redirect("/"); res.redirect("/");
} else res.render("pages/login.ejs", { invalid: "baduserorpass" }); } else res.render("pages/login.ejs", { invalid: "baduserorpass" });
} }
}) }).catch((err: any) => {
throw err;
});
} }
} }

View File

@ -8,20 +8,39 @@ export default {
const ip = req.params.ip; const ip = req.params.ip;
const r = await data.ping(ip); const r = await data.ping(ip);
if((Number(data.pings.get(ip).split("_")[0]) + (1000 * 60 * 5)) < Date.now()) { if((Number(data.pings.get(ip).split("_")[0]) + (1000 * 60 * 5)) < Date.now()) {
if(!r.alive) connection.query("SELECT * FROM downtime WHERE ip=? AND date=? AND status=?", [ip, new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '), "DOWN"], (err, results, fields) => { if(!r.alive) {
if(err) throw err; connection.query("SELECT * FROM downtime WHERE ip=$ip AND date=$date AND status=$status", {
if(results.length === 0) connection.query("INSERT INTO downtime VALUES (NULL, ?, ?, ?)", [ip, new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '), "DOWN"], (errr, resultss, fieldss) => { ip: ip,
if(errr) throw errr; date: new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '),
}); status: "DOWN"
}); }).then((result: any) => {
if(result[0].result.length === 0) connection.query("CREATE downtime SET ip=$ip, date=$date, status=$status", {
ip: ip,
date: new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '),
status: "DOWN"
});
else connection.query("SELECT * FROM downtime WHERE ip=? AND date=? AND status=?", [ip, new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '), "UP"], (err, results, fields) => { }).catch((err: any) => {
if(err) throw err; throw err;
if(results.length === 0) connection.query("INSERT INTO downtime VALUES (NULL, ?, ?, ?)", [ip, new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '), "UP"], (errr, resultss, fieldss) => {
if(errr) throw errr;
}); });
}); } else {
connection.query("SELECT * FROM downtime WHERE ip=$ip AND date=$date AND status=$status", {
ip: ip,
date: new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '),
status: "UP"
}).then((result: any) => {
if(result[0].result.length === 0) connection.query("CREATE downtime SET ip=$ip, date=$date, status=$status", {
ip: ip,
date: new Date(Number(data.pings.get(ip).split("_")[0])).toISOString().slice(0, 19).replace('T', ' '),
status: "UP"
});
}).catch((err: any) => {
throw err;
});
}
} }
if(!r.alive && data.pings.get(ip).split("_")[1] === "1") data.pings.set(ip, `${Date.now()}_0`); if(!r.alive && data.pings.get(ip).split("_")[1] === "1") data.pings.set(ip, `${Date.now()}_0`);
else if(r.alive) data.pings.set(ip, `${Date.now()}_1`); else if(r.alive) data.pings.set(ip, `${Date.now()}_1`);
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');

View File

@ -17,16 +17,23 @@ export default {
const encryptedPassword = await bcrypt.hash(req.body.password, 10); const encryptedPassword = await bcrypt.hash(req.body.password, 10);
connection.query("SELECT * FROM users WHERE username = ?", req.body.username, (err, results, fields) => { connection.query(`SELECT * FROM users WHERE username=$user`, {
if(err) throw err; user: req.body.username
})
if(results.length > 0) res.render("pages/register.ejs", { invalid: "exists" }); .then((result: any) => {
if(result[0].result.length > 0) res.render("pages/register.ejs", { invalid: "exists" });
else { else {
connection.query("INSERT INTO users VALUES (NULL, ?, ?)", [req.body.username, encryptedPassword], (errr, resultss, fieldss) => { connection.query("CREATE users SET username=$user, password=$pass", {
if(errr) throw errr user: req.body.username,
pass: encryptedPassword
}).then((resultt: any) => {
res.render("pages/register.ejs", { invalid: "created" }); res.render("pages/register.ejs", { invalid: "created" });
}).catch((err: any) => {
throw err;
}); });
} }
}).catch((err: any) => {
throw err;
}); });
} }
} }

View File

@ -5,19 +5,25 @@ export default {
method: "GET", method: "GET",
url: "/removeIP/:ip", url: "/removeIP/:ip",
callback: async (data: any, req: Request, res: Response) => { callback: async (data: any, req: Request, res: Response) => {
connection.query("SELECT * FROM ips WHERE ip = ?", req.params.ip, (err, results, fields) => { connection.query("SELECT * FROM ips WHERE ip=$ip", {
if(err) throw err; ip: req.params.ip
})
if(results.length == 0) { .then((result: any) => {
if(result[0].result.length == 0) {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ status: "OK" })); res.end(JSON.stringify({ status: "OK" }));
} else { } else {
connection.query("DELETE FROM ips WHERE ip = ?", req.params.ip, (errr, resultss, fieldss) => { connection.query("DELETE ips WHERE ip=$ip", {
if(errr) throw errr ip: req.params.ip
}).then((resultt: any) => {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ status: "OK" })); res.end(JSON.stringify({ status: "OK" }));
}).catch((err: any) => {
throw err;
}); });
} }
}).catch((err: any) => {
throw err;
}); });
} }
} }

View File

@ -21,6 +21,7 @@
await fetch('http://localhost:8080/removeIP/' + ip) await fetch('http://localhost:8080/removeIP/' + ip)
const a = document.getElementById(ip + "_main"); const a = document.getElementById(ip + "_main");
a.remove(); a.remove();
window.location.reload(true);
} }
async function aaa() { async function aaa() {