@nka212bg/backend-utils 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/db/dbUtils.js +36 -0
- package/db/mysql2.js +56 -0
- package/db/sqlite3.js +99 -0
- package/location/GeoLite2-City.mmdb +0 -0
- package/location/VPNs-master.zip +0 -0
- package/location/index.js +88 -0
- package/location/localelib.js +4362 -0
- package/mailSmsTools/defaultTemplate.html +21 -0
- package/mailSmsTools/index.js +162 -0
- package/markdown/index.js +24 -0
- package/markdown/markdown.js +2 -0
- package/misc.js +463 -0
- package/os.js +53 -0
- package/package.json +23 -0
- package/session.js +145 -0
- package/socket.js +157 -0
- package/stripe.js +98 -0
- package/systemLog.js +72 -0
package/README.md
ADDED
package/db/dbUtils.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// HELPERS
|
|
2
|
+
exports.stripString = (input) => {
|
|
3
|
+
if (!input) return input;
|
|
4
|
+
|
|
5
|
+
return (
|
|
6
|
+
String(input)
|
|
7
|
+
// .replace(/([!@#$%^&*,/\\<>]| )+/g, " ")
|
|
8
|
+
.replace(/\/\*|\*\/| +/g, " ")
|
|
9
|
+
.replace(/(( +$)?(' *)( +$)?)+/g, "'")
|
|
10
|
+
.replace(/(( +$)?(" *)( +$)?)+/g, '"')
|
|
11
|
+
.replace(/\-+/g, "-")
|
|
12
|
+
.replace(/ +/g, " ")
|
|
13
|
+
.trim()
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
exports.paramsSanitize = (params) => {
|
|
18
|
+
if (!params) return [];
|
|
19
|
+
if (!Array.isArray(params)) params = [params];
|
|
20
|
+
|
|
21
|
+
return params.map((param) => {
|
|
22
|
+
if (typeof param == "object" && param !== null) {
|
|
23
|
+
return JSON.stringify(param);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
param = String(param).trim();
|
|
27
|
+
const pLowerCase = param.toLowerCase();
|
|
28
|
+
|
|
29
|
+
if (pLowerCase === "true") return 1;
|
|
30
|
+
if (pLowerCase === "false") return 0;
|
|
31
|
+
if (!param || pLowerCase == "null" || pLowerCase == "undefined") return undefined;
|
|
32
|
+
// if (!isNaN(param)) return Number(param);
|
|
33
|
+
|
|
34
|
+
return param;
|
|
35
|
+
});
|
|
36
|
+
};
|
package/db/mysql2.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const { paramsSanitize, stripString } = require("./dbUtils");
|
|
2
|
+
const { createPool } = require("mysql2");
|
|
3
|
+
|
|
4
|
+
const pool = createPool({
|
|
5
|
+
host: process.env.MYSQL_HOST,
|
|
6
|
+
port: process.env.MYSQL_PORT,
|
|
7
|
+
user: process.env.MYSQL_USER,
|
|
8
|
+
password: process.env.MYSQL_PASSWORD,
|
|
9
|
+
database: process.env.MYSQL_DATABASE,
|
|
10
|
+
waitForConnections: true,
|
|
11
|
+
connectionLimit: 10,
|
|
12
|
+
queueLimit: 0,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
exports.mysql = (sql, params) => {
|
|
16
|
+
// (SELECT JSON_ARRAYAGG(JSON_OBJECT('CountryId', CountryID)) FROM country) AS Countries // JSON_ARRAYAGG and JSON_OBJECT demos
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
try {
|
|
19
|
+
sql = stripString(sql);
|
|
20
|
+
if (!sql) throw "Missing sql";
|
|
21
|
+
|
|
22
|
+
if (params?.length) {
|
|
23
|
+
const queryPlaceholdersLength = (sql.match(/\?/g) || []).length; // [?]
|
|
24
|
+
if (queryPlaceholdersLength < params.length) {
|
|
25
|
+
params.splice(queryPlaceholdersLength, params.length);
|
|
26
|
+
} else if (queryPlaceholdersLength > params.length) {
|
|
27
|
+
params = params.concat(Array(queryPlaceholdersLength - params.length).fill(params[params.length - 1]));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pool.query(sql, paramsSanitize(params), function (error, data) {
|
|
32
|
+
const changes = this._rows?.[0]?.affectedRows;
|
|
33
|
+
if (!error) {
|
|
34
|
+
if (/^INSERT/gi.test(sql)) {
|
|
35
|
+
const targetDB = /INTO\s(.*?) /i.exec(sql)[1];
|
|
36
|
+
pool.query(`SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'PRIMARY' AND TABLE_NAME = '${targetDB}' LIMIT 1`, [], function (error, tableName) {
|
|
37
|
+
tableName = tableName?.[0].COLUMN_NAME;
|
|
38
|
+
if (!tableName) return resolve({ error, data: undefined, changes });
|
|
39
|
+
|
|
40
|
+
pool.query(`SELECT MAX(${tableName}) AS ${tableName} FROM ${targetDB}`, [], function (error, tableValue) {
|
|
41
|
+
tableValue = tableValue?.[0];
|
|
42
|
+
resolve({ error, data: tableValue || undefined, changes });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
!data?.length && (data = undefined);
|
|
50
|
+
resolve({ error, data, changes });
|
|
51
|
+
});
|
|
52
|
+
} catch (error) {
|
|
53
|
+
resolve({ error, data: undefined, changes: 0 });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
package/db/sqlite3.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const { paramsSanitize, stripString } = require("./dbUtils");
|
|
2
|
+
const sqlite3 = require("sqlite3").verbose();
|
|
3
|
+
|
|
4
|
+
const dbs = {};
|
|
5
|
+
let vacuumed = [];
|
|
6
|
+
let day = new Date().getDate();
|
|
7
|
+
|
|
8
|
+
setInterval(() => {
|
|
9
|
+
const now = new Date();
|
|
10
|
+
if (day != now.getDate()) {
|
|
11
|
+
day = now.getDate();
|
|
12
|
+
vacuumed = [];
|
|
13
|
+
}
|
|
14
|
+
for (const e in dbs) {
|
|
15
|
+
if (dbs[e].time + 1000 * 60 * 5 < now.getTime()) {
|
|
16
|
+
if (dbs[e].vacuum && !vacuumed.includes(e)) {
|
|
17
|
+
vacuumed.push(e);
|
|
18
|
+
dbs[e].run("VACUUM");
|
|
19
|
+
}
|
|
20
|
+
dbs[e].close();
|
|
21
|
+
delete dbs[e];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}, 1000 * 60);
|
|
25
|
+
|
|
26
|
+
exports.sqlite = (dbName, sql, params = []) => {
|
|
27
|
+
return new Promise(async (resolve) => {
|
|
28
|
+
try {
|
|
29
|
+
sql = stripString(sql);
|
|
30
|
+
if (!sql) throw "Missing sql";
|
|
31
|
+
const isWrite = /^(INSERT|DELETE|UPDATE)/i.test(sql);
|
|
32
|
+
const queryPlaceholdersLength = (sql.match(/\?/g) || []).length; // [?]
|
|
33
|
+
|
|
34
|
+
if (queryPlaceholdersLength < params.length) {
|
|
35
|
+
params.splice(queryPlaceholdersLength, params.length);
|
|
36
|
+
} else if (queryPlaceholdersLength > params.length) {
|
|
37
|
+
params = params.concat(Array(queryPlaceholdersLength - params.length).fill(params[params.length - 1]));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let dbError;
|
|
41
|
+
if (!dbs[dbName]) {
|
|
42
|
+
let db;
|
|
43
|
+
await new Promise(async (resolve) => {
|
|
44
|
+
db = new sqlite3.Database(dbName, (error) => {
|
|
45
|
+
dbError = error;
|
|
46
|
+
resolve();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (dbError) throw dbError;
|
|
51
|
+
|
|
52
|
+
db.time = Date.now();
|
|
53
|
+
dbs[dbName] = db;
|
|
54
|
+
|
|
55
|
+
// some db settings here
|
|
56
|
+
dbs[dbName].run("pragma synchronous = normal");
|
|
57
|
+
|
|
58
|
+
if (dbName.endsWith("/main.db")) {
|
|
59
|
+
dbs[dbName].run("pragma temp_store = memory").run("pragma mmap_size = 3000000000");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
dbs[dbName][isWrite ? "run" : "all"](sql, paramsSanitize(params), function (error, res) {
|
|
64
|
+
if (error) return resolve({ error });
|
|
65
|
+
|
|
66
|
+
!res?.length && (res = undefined);
|
|
67
|
+
const changes = this.changes;
|
|
68
|
+
|
|
69
|
+
if (/^INSERT/i.test(sql)) {
|
|
70
|
+
const targetDB = /INTO\s(.*?) /i.exec(sql)[1];
|
|
71
|
+
const insertId = this.lastID;
|
|
72
|
+
return dbs[dbName].all(`SELECT name FROM pragma_table_info(?) WHERE pk = 1 LIMIT 1`, [targetDB], function (error, insertData) {
|
|
73
|
+
insertData = insertData?.[0] ? { [insertData[0].name]: insertId } : undefined;
|
|
74
|
+
|
|
75
|
+
resolve({ error, data: insertData, changes });
|
|
76
|
+
printError(error);
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
resolve({ error, data: res, changes });
|
|
80
|
+
printError(error);
|
|
81
|
+
|
|
82
|
+
if (/^DELETE/i.test(sql)) dbs[dbName].vacuum = true;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
} catch (error) {
|
|
86
|
+
try {
|
|
87
|
+
dbs[dbName].close();
|
|
88
|
+
} catch {}
|
|
89
|
+
|
|
90
|
+
delete dbs[dbName];
|
|
91
|
+
resolve({ error, data: undefined });
|
|
92
|
+
printError(error);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function printError(error) {
|
|
96
|
+
error && console.error(`SQLite error\n--> ${dbName}\n--> ${sql}\n--> ${error.message || String(error)}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
};
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const { readFileSync } = require("fs");
|
|
2
|
+
const { locales, timeZones } = require(`./localelib`);
|
|
3
|
+
|
|
4
|
+
// Load the db in the memory
|
|
5
|
+
const Reader = require("@maxmind/geoip2-node").Reader;
|
|
6
|
+
const GeoDB = Reader.openBuffer(readFileSync(`${__dirname}/GeoLite2-City.mmdb`));
|
|
7
|
+
|
|
8
|
+
exports.userIp = (req) => {
|
|
9
|
+
if (!req) throw new Error("Request object is missing, can't work like that! That's absurd!!!");
|
|
10
|
+
|
|
11
|
+
let ip = (req.headers["x-forwarded-for"] || req.socket?.remoteAddress || req.connection?.remoteAddress || req.ip)?.split(",")[0].replace(/::ffff:/gi, "");
|
|
12
|
+
|
|
13
|
+
// if (["127.0.0.1", "::1"].includes(ip)) return "146.70.185.8";
|
|
14
|
+
return ip;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// user geo
|
|
18
|
+
exports.location = ({ req, ip }) => {
|
|
19
|
+
let userIP;
|
|
20
|
+
try {
|
|
21
|
+
if (!ip && !req) throw "missing_required";
|
|
22
|
+
userIP = ip || this.userIp(req);
|
|
23
|
+
const geo = GeoDB.city(userIP);
|
|
24
|
+
|
|
25
|
+
const country = locales[geo.country.isoCode];
|
|
26
|
+
country.isoCode = geo.country.isoCode;
|
|
27
|
+
|
|
28
|
+
const data = {
|
|
29
|
+
...country,
|
|
30
|
+
...timeZones[country?.timeZone],
|
|
31
|
+
...this.userDevice(req?.headers["user-agent"]),
|
|
32
|
+
|
|
33
|
+
ipAddress: userIP,
|
|
34
|
+
city: geo.city?.names.en || "",
|
|
35
|
+
postalCode: geo.postal?.code || "",
|
|
36
|
+
coordinates: geo.location,
|
|
37
|
+
traits: geo.traits,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return { data };
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return {
|
|
43
|
+
error: {
|
|
44
|
+
error,
|
|
45
|
+
ipAddress: userIP,
|
|
46
|
+
msg: "Invalid or not existing IP",
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
exports.userDevice = (userAgent) => {
|
|
53
|
+
try {
|
|
54
|
+
if (!userAgent) throw "no_user_agent";
|
|
55
|
+
|
|
56
|
+
const getBrowser = () => {
|
|
57
|
+
if (/trident/i.test(userAgent)) return "msie";
|
|
58
|
+
if (/ope?ra?|opr/i.test(userAgent)) return "opera";
|
|
59
|
+
if (/edge?/i.test(userAgent)) return "edge";
|
|
60
|
+
if (/chrome/i.test(userAgent)) return "chrome";
|
|
61
|
+
if (/firefox/i.test(userAgent)) return "firefox";
|
|
62
|
+
if (/safari/i.test(userAgent)) return "safari";
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getOS = () => {
|
|
66
|
+
if (/Win/i.test(userAgent)) return "windows";
|
|
67
|
+
if (/Linux/i.test(userAgent)) return "linux";
|
|
68
|
+
if (/Mac/i.test(userAgent)) return "mac";
|
|
69
|
+
if (/Android/i.test(userAgent)) return "android";
|
|
70
|
+
if (/iPhone/i.test(userAgent)) return "iPhone";
|
|
71
|
+
if (/CrOS/i.test(userAgent)) return "chromeOS";
|
|
72
|
+
if (/WebOS/i.test(userAgent)) return "webOS";
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const res = {
|
|
76
|
+
browser: getBrowser(),
|
|
77
|
+
os: getOS(),
|
|
78
|
+
device: /Mobile|Phone|Android|Pad|Pod|BlackBerry|IEMobile/i.test(userAgent) ? "mobile" : "desktop",
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
...res,
|
|
83
|
+
string: `${res.browser},${res.os},${res.device}`,
|
|
84
|
+
};
|
|
85
|
+
} catch (error) {
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
};
|