Skip to content

Commit

Permalink
fix/nsk mrz (#209)
Browse files Browse the repository at this point in the history
* fix: nsk hos-000

* ver
  • Loading branch information
hajonsoft authored Feb 27, 2024
1 parent 178a033 commit 1982d28
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 106 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hajonsoft-eagle",
"version": "2.6.15",
"version": "2.6.16",
"description": "HAJonSoft node app to submit passengers to visa systems",
"main": "index.js",
"scripts": {
Expand Down
26 changes: 14 additions & 12 deletions play.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,36 +409,38 @@ const fs = require("fs");
const sharp = require("sharp");

// Path to the input image
const imagePath = "input.jpg";
const imagePath = "/Users/aali/hajonsoft/passports/CF9361618.jpg";
const fontName = "OCRB";
// Text to be added at the bottom
const textLine1 = "P<INDKHAN<<VASIM<<<<<<<<<<<<<<<<<<<<<<<<<<<<";
const textLine2 = "Y5252725<2IND9601019M33113072068702785423<02";
const encodedTextLine1 = textLine1.replace(/</g, '&lt;')
const encodedTextLine2 = textLine2.replace(/</g, '&lt;');
const encodedTextLine1 = textLine1.replace(/</g, "&lt;");
const encodedTextLine2 = textLine2.replace(/</g, "&lt;");

async function makeImage() {
const metaData = await sharp(imagePath).metadata();
const height = Math.floor(metaData.height / 4);
// SVG markup with encoded text
const mrzImage = `
<svg width="${metaData.width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
const height = Math.floor(400 / 4);
// SVG markup with encoded text
const mrzImage = `
<svg width="600" height="${height}" xmlns="http://www.w3.org/2000/svg">
<!-- Background rectangle -->
<rect fill="white" x="0" y="0" width="${metaData.width}" height="${height}" />
<text x="60" y="140" font-family="Ariel" font-size="50" fill="black">
<rect fill="white" x="0" y="${height / 8}" width="600" height="${height}" />
<text x="40" y="50" font-family="${fontName}" font-size="16" fill="black">
${encodedTextLine1}
</text>
<text x="60" y="230" font-family="Ariel" font-size="50" fill="black">
<text x="40" y="75" font-family="${fontName}" font-size="16" fill="black">
${encodedTextLine2}
</text>
</svg>
`;

const mrzBuffer = Buffer.from(mrzImage);
await sharp(imagePath)
.resize(600, 400)
.grayscale()
.composite([
{
input: mrzBuffer,
top: metaData.height - height, // Position at the bottom of the image
top: 300,
left: 0,
},
])
Expand Down
185 changes: 92 additions & 93 deletions src/nsk.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const { getPath } = require("./lib/getPath");
const totp = require("totp-generator");
const kea = require("./lib/kea");
const { fetchNusukIMAPPDF } = require("./lib/imap");
const sharp = require("sharp");

let page;
let data;
Expand Down Expand Up @@ -553,68 +554,52 @@ async function pageContentHandler(currentConfig) {

async function pasteSimulatedPassport() {
const passenger = data.travellers[util.getSelectedTraveler()];
const blankPassportPath = getPath(`${passenger.passportNumber}_mrz.jpg`);
// Generate simulated passport image using the browser canvas api
const dataUrl = await page.evaluate((_passenger) => {
const ele = document.createElement("canvas");
ele.id = "hajonsoftcanvas";
ele.style.display = "none";
document.body.appendChild(ele);
const canvas = document.getElementById("hajonsoftcanvas");
canvas.width = 700;
canvas.height = 400;
const ctx = canvas.getContext("2d");
// White background
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = "black";
ctx.font = "18px OCR-B, monospace";
ctx.fillText(
_passenger.codeline?.replace(/\n/g, "")?.substring(0, 44),
14,
canvas.height - 70
);
ctx.fillText(
_passenger.codeline?.replace(/\n/g, "")?.substring(44),
14,
canvas.height - 25
);

// Photo
ctx.lineWidth = 1;
ctx.fillStyle = "hsl(240, 25%, 94%)";
ctx.fillRect(45, 25, 100, 125);
// Visible area
ctx.fillStyle = "hsl(240, 25%, 94%)";
ctx.fillRect(170, 25, 200, 175);

// under photo area
ctx.fillStyle = "hsl(240, 25%, 94%)";
ctx.fillRect(45, 165, 100, 35);
return canvas.toDataURL("image/jpeg", 1.0);
}, passenger);
await util.downloadImage(
passenger.images.passport,
getPath(`${passenger.passportNumber}.jpg`)
);
const fontName = "OCRB";
// Text to be added at the bottom
const textLine1 = passenger.codeline.split("\n")[0];
const textLine2 = passenger.codeline.split("\n")[1];
const encodedTextLine1 = textLine1.replace(/</g, "&lt;");
const encodedTextLine2 = textLine2.replace(/</g, "&lt;");

// Save dataUrl to file
const imageData = dataUrl.replace(/^data:image\/\w+;base64,/, "");
const buf = Buffer.from(imageData, "base64");
fs.writeFileSync(blankPassportPath, buf);
await util.commitFile("#PassportPictureUploader", blankPassportPath);
}
const height = 100;
const mrzImage = `
<svg width="600" height="${height}" xmlns="http://www.w3.org/2000/svg">
<!-- Background rectangle -->
<rect fill="white" x="0" y="0" width="600" height="${height}" />
<text x="40" y="50" font-family="${fontName}" font-size="16" fill="black">
${encodedTextLine1}
</text>
<text x="40" y="75" font-family="${fontName}" font-size="16" fill="black">
${encodedTextLine2}
</text>
</svg>
`;

async function originalPassport() {
const passenger = data.travellers[util.getSelectedTraveler()];
const passportPath = await util.downloadImage(
passenger,
600,
400,
"passport",
400,
1024,
true
const passportPathMrz = path.join(
util.passportsFolder,
`${passenger.passportNumber}_mrz.png`
);
const mrzBuffer = Buffer.from(mrzImage);
await sharp(getPath(`${passenger.passportNumber}.jpg`))
.resize(600, 400)
.grayscale()
.composite([
{
input: mrzBuffer,
top: 300,
left: 0,
},
])
.png()
.toFile(passportPathMrz);

await util.commitFile("#PassportPictureUploader", blankPassportPath);
await util.commitFile("#PassportPictureUploader", passportPathMrz);
const isSuccess = await assertPassportImage();
return isSuccess;
}

function suggestEmail(passenger) {
Expand Down Expand Up @@ -651,7 +636,7 @@ async function sendCurrentPassenger() {
util.infoMessage(page, `🧟 Inputting ${passenger.slug} saved`);
let isPassportScanSuccessful = await pastePassportImage(passenger);
if (!isPassportScanSuccessful) {
isPassportScanSuccessful = await pastePassportImage(passenger, false);
isPassportScanSuccessful = await pasteSimulatedPassport(passenger);
}
await pasteRemainingImages(passenger);
await showCommanders(passenger);
Expand All @@ -664,17 +649,17 @@ async function sendCurrentPassenger() {
if (!isPassportScanSuccessful) {
await page.$eval("#qa-add-mutamer-save", (e) => {
e.textContent =
"Save (Be careful Passport number or Last name is not correct)";
"Save (Be careful Passport number or Last name is not correct) - download OCRB font from https://fontsgeek.com/fonts/OCRB-Medium";
});
// scroll to this selector
// scroll to this selector
// #qa-add-mutamer-save
await page.evaluate((selector) => {
const element = document.querySelector(selector);
if (element) {
element.scrollIntoView();
}
}, "#qa-add-mutamer-save");

openFields();
await kea.updatePassenger(data.system.accountId, passenger.passportNumber, {
"submissionData.nsk.status": "Rejected",
Expand Down Expand Up @@ -821,37 +806,41 @@ async function pasteRemainingImages(passenger) {
true
);
await util.commitFile("#ResidencyPictureUploader", permitPath);
} else {
await util.commitFile("#ResidencyPictureUploader", resizedPhotoPath);
}

await util.commit(
page,
[
{
selector: "#IqamaExpiryDate",
value: (row) =>
`${row.idExpireDt.yyyy}-${row.idExpireDt.mm}-${row.idExpireDt.dd}`,
},
],
passenger
);

await page.$eval(
"#dvResidencyExpiryDate > label",
(e, idExpireDt) => {
e.textContent = `Residency Expiry Date (${idExpireDt})`;
await page.click("#IqamaExpiryDate");
await page.waitForTimeout(500);
await util.commit(
page,
[
{
selector: "#IqamaExpiryDate",
value: (row) =>
`${row.idExpireDt.yyyy || row.passExpireDt.yyyy}-${row.idExpireDt.mm || row.passExpireDt.mm}-${row.idExpireDt.dd || row.passExpireDt.dd}`,
},
passenger.idExpireDt.dmmmy
);
],
passenger
);

await page.$eval(
"#dvResidencyExpiryDate > label",
(e, idExpireDt) => {
e.textContent = `Residency Expiry Date: => (${idExpireDt})`;
},
passenger.idExpireDt.dmmmy
);

await page.$eval(
"#dvResidencyId > label",
(e, residenceId) => {
e.textContent = `Residency ID: => (${residenceId})`;
},
passenger.idNumber
);

await page.$eval(
"#dvResidencyId > label",
(e, residenceId) => {
e.textContent = `Residency ID (${residenceId})`;
},
passenger.idNumber
);
} else {
await util.commitFile("#ResidencyPictureUploader", resizedPhotoPath);
}
} catch (e) {
console.log("Error: ", e);
}
Expand Down Expand Up @@ -880,7 +869,12 @@ async function pastePassportImage(passenger, resized = true) {
await util.downloadImage(passenger.images.passport, passportPath);
await util.commitFile("#PassportPictureUploader", passportPath);
}
await page.waitForTimeout(1000);
await page.waitForTimeout(1000);
const isSuccess = await assertPassportImage();
return isSuccess;
}

async function assertPassportImage() {
try {
const modalContentSelector =
"body > div.swal2-container.swal2-center.swal2-shown > div > div.swal2-content";
Expand Down Expand Up @@ -922,6 +916,7 @@ await page.waitForTimeout(1000);
passenger.passportNumber === passportNumberInPage
);
} catch (e) {}
return false;
}

async function addMutamerClick() {
Expand Down Expand Up @@ -1053,9 +1048,13 @@ async function recordStatus(passenger) {
)
) {
util.infoMessage(page, `🧟 passenger ${passenger.slug} saved`);
await kea.updatePassenger(data.system.accountId, passenger.passportNumber, {
"submissionData.nsk.status": "Submitted",
});
await kea.updatePassenger(
data.system.accountId,
passenger.passportNumber,
{
"submissionData.nsk.status": "Submitted",
}
);
} else {
try {
// Wait for the error icon to appear
Expand Down

0 comments on commit 1982d28

Please sign in to comment.