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");