Utils/qr_tool/index.js
2023-05-29 17:48:25 +03:00

280 lines
7.0 KiB
JavaScript
Executable File

import inquirer from "inquirer";
import { MongoClient } from "mongodb";
import QRCode from "qrcode";
import { writeFileSync, mkdirSync } from "fs";
import Jimp from "jimp";
import path from "path";
import fs from "fs";
let url;
let client;
let db;
const dbName = "comfortech";
let host = "176.53.196.42";
let port = "27017";
let pass = "password";
let username = "user";
await inquirer
.prompt([
{
name: "host",
message: "Database host",
default: host,
},
{
name: "port",
message: "Database port",
default: "27017",
},
{
type: "list",
name: "credentials",
message: "Login as a specific user?",
choices: ["No", "Yes"],
},
])
.then(async answers => {
host = answers.host;
port = answers.port;
if (answers.credentials == "Yes") {
await inquirer
.prompt([
{
name: "username",
message: "Username",
default: "user",
},
{
name: "pass",
type: "password",
message: "Password",
},
])
.then(answers => {
username = answers.username;
pass = answers.pass;
});
}
});
async function ask_about_all_places(places) {
const flats_list = places.map(x => {
return `${x.name} ${x._id.toString()}`;
});
return await inquirer
.prompt([
{
name: "all",
message: "Generate QR codes for all places",
type: "confirm",
default: false,
},
])
.then(async answers => {
if (answers.all) {
return {
all: true,
ids: flats_list,
};
} else {
const place_ids = await inquirer
.prompt([
{
name: "flats",
message: "Choose flat numbers",
type: "checkbox",
choices: flats_list,
},
])
.then(async answers => {
// return answers.flats.map(num => num.split(" ")[1]);
return answers.flats;
});
return { all: false, ids: place_ids };
}
});
}
async function ask_size() {
return await inquirer.prompt([
{
name: "size",
type: "number",
message: "Size of a side in px",
default: "354",
},
]);
}
async function ask_to_override_existing(ids) {
ids = ids.map(item => item.split(" ")[1]);
console.log("\n\n", ids, "\n\n");
await db
.createCollection("qr_code")
.then(res => {
console.log("Collection created");
})
.catch(err => {
if (err.code == 48) {
console.info("Collection exists");
} else {
console.error("Error:", err);
}
});
const collection = await db.collection("qr_code");
const override = await inquirer
.prompt([
{
name: "override",
message: "If QR codes exist for chosen places",
type: "list",
choices: ["Skip", "Replace"],
default: "Replace",
},
])
.then(answer => {
return answer.override == "Skip" ? false : true;
});
if (override) {
const res = await collection.deleteMany({
place_id: {
$in: [...ids],
},
});
} else {
let res = collection.find({
place_id: {
$in: [...ids],
},
});
const existing_qrs = await res.toArray();
const exclude_places = existing_qrs.map(el => el.place_id);
console.log(`Skiped ${exclude_places.length}/${ids.length} places (QR code exists)`);
exclude_places.forEach(place_id => {
const index = ids.indexOf(place_id);
if (index !== -1) {
ids.splice(index, 1);
}
});
console.log(ids.length, "places left");
}
if (ids.length == 0) return [];
let qrcode_ids = [];
let docs = [];
await ids.forEach(async place_id => {
docs.push({
place_id,
one_time: false,
});
});
const res = await collection
.insertMany(docs)
.then(res => {
return res;
})
.catch(err => {
console.error(err);
});
for (const [key, value] of Object.entries(res.insertedIds)) {
qrcode_ids.push(value.toString());
}
return qrcode_ids;
}
function getAvailableName(fullpath) {
let dir = path.dirname(fullpath);
let base = path.basename(fullpath);
for (let i = 0; fs.existsSync(fullpath); i++) {
let items = base.split(".");
fullpath = dir + "/" + items[0] + "_" + i + "." + items[1];
}
return fullpath;
}
// Connection URL
async function main() {
url = `mongodb://${username ? username + ":" + pass + "@" : ""}${host}:${port}`;
client = new MongoClient(url);
// Use connect method to connect to the server
await client.connect();
db = client.db(dbName);
console.info("Connected successfully");
const place_col = db.collection("place");
const places = place_col.find({ place_type: "flat" });
console.info(await place_col.countDocuments({ place_type: "flat" }), "places found");
const flats = await ask_about_all_places(await places.toArray());
console.info(`Generate QR codes for ${flats.ids.length} places`);
console.info(`Places: ${flats.ids} `);
const qrcode_ids = await ask_to_override_existing(flats.ids);
console.log(qrcode_ids.length, "QR codes generated in data base");
await client.close();
const qr_size = parseInt((await ask_size()).size);
console.log(qr_size, "px");
const folder = new Date().valueOf();
mkdirSync("out/" + folder, { recursive: true });
qrcode_ids.forEach(async qr => {
QRCode.toDataURL(qr, {
errorCorrectionLevel: "H",
scale: 3,
margin: 5,
width: 512,
color: { light: "#fafafa", dark: "#121212" },
})
.then(url => {
const base64Data = url.replace(/^data:image\/png;base64,/, "");
const index = qrcode_ids.indexOf(qr);
let fileName = `./out/${folder}/${flats.ids[index].split(" ")[0]}.png`;
fileName = getAvailableName(fileName);
writeFileSync(`${fileName}`, base64Data, "base64");
const imageCaption = "KB. " + flats.ids[index].split(" ")[0];
let loadedImage;
Jimp.read(fileName)
.then(function (image) {
loadedImage = image;
var fontpath = path.join(process.cwd(), "opensans/open_sans_32.fnt");
return Jimp.loadFont(fontpath);
})
.then(function (font) {
loadedImage.print(font, 204, 12, imageCaption).write(fileName);
const isHorizontal = loadedImage.getWidth() > loadedImage.getHeight();
const ratio = isHorizontal
? loadedImage.getWidth() / loadedImage.getHeight()
: loadedImage.getHeight() / loadedImage.getWidth();
const width = qr_size; // set the width you want
const height = isHorizontal ? width / ratio : width * ratio;
return loadedImage.resize(width, height, Jimp.RESIZE_BICUBIC).quality(60).write(fileName);
})
.catch(function (err) {
console.error(err);
});
})
.catch(err => {
console.error(err);
});
});
}
await main();
console.log("Exited");