Skip to content

Commit

Permalink
fix-generate-mrz (#224)
Browse files Browse the repository at this point in the history
  • Loading branch information
hajonsoft authored Apr 29, 2024
1 parent e3a83b0 commit 57a9b75
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 4 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.35",
"version": "2.6.36",
"description": "HAJonSoft node app to submit passengers to visa systems",
"main": "index.js",
"scripts": {
Expand Down
26 changes: 23 additions & 3 deletions src/ehj.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ let importClicks = 0;
let editPassportNumber;
let liberiaPassports = [];
const questionnaireClicked = {};
let sent = {};

if (fs.existsSync(getPath("passports.txt"))) {
const rawPassports = fs
Expand Down Expand Up @@ -462,7 +463,13 @@ async function pasteCodeLine(selectedTraveler, passengersData) {
browser.disconnect();
}
var passenger = passengersData.travellers[selectedTraveler];
await page.keyboard.type(passenger.codeline);
if (sent[passenger.passportNumber] === undefined) {
await page.keyboard.type(passenger.codeline);
} else {
const newCodeLine = util.generateMRZ(passenger);
console.log("📢[ehj.js:470]: newCodeLine: ", newCodeLine);
await page.keyboard.type(newCodeLine);
}
}

async function send(sendData) {
Expand Down Expand Up @@ -888,6 +895,13 @@ async function pageContentHandler(currentConfig) {
return el.innerText;
});
if (error.includes("try again")) {
// try again once using generated MRZ, do not log error unless it is the second time around
if (sent[passenger.passportNumber] === undefined) {
sent[passenger.passportNumber] = 1;
fs.writeFileSync(getPath("loop.txt"), "ehaj", "utf-8");
await page.reload();
return;
}
await kea.updatePassenger(
data.system.accountId,
passenger.passportNumber,
Expand Down Expand Up @@ -1278,8 +1292,14 @@ async function pageContentHandler(currentConfig) {

await util.commit(page, currentConfig.details, passenger);
// get the email from budgie ot use emailinthecloud
const name = `${passenger.name.first}.${passenger.name.last}`.substring(0, 20);
const email = budgie.get("ehaj_questionnaire_email", `${name}.${passenger.passportNumber}@emailinthecloud.com`.toLowerCase());
const name = `${passenger.name.first}.${passenger.name.last}`.substring(
0,
20
);
const email = budgie.get(
"ehaj_questionnaire_email",
`${name}.${passenger.passportNumber}@emailinthecloud.com`.toLowerCase()
);
// commit the email to this selector "#kt_app_content_container > div:nth-child(2) > form > div.ui-panel.ui-widget.ui-widget-content.ui-corner-all > div.ui-panel-content.ui-widget-content > div:nth-child(4) > div > input"
await util.commit(
page,
Expand Down
100 changes: 100 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const IMGUR_CLIENT_ID = "0b4827447357d6b";
const IMGUR_CLIENT_SECRET = "c842b1a08f0748150465ec643c04c0aeb17329c7";
const kea = require("./lib/kea");

const MRZ_TD3_LINE_LENGTH = 44;

// or your client ID
const imgurClient = new ImgurClient({
clientId: IMGUR_CLIENT_ID,
Expand Down Expand Up @@ -1789,6 +1791,103 @@ async function clickWhenReady(selector, page) {
}
}

function generateMRZ(passenger) {
console.log(passenger);
try {
// LINE 1
const codeLine1 = `P<${passenger.nationality.code}${passenger.name.last.replace(
/ /g,
"<"
)}<<${passenger.name.given.replace(/ /g, "<")}`
.padEnd(MRZ_TD3_LINE_LENGTH, "<")
.substring(0, MRZ_TD3_LINE_LENGTH);
// LINE 2
const icaoPassportNumber = passenger.passportNumber.padEnd(9, "<");
const birthDate = `${passenger.dob.yyyy.substring(2)}${passenger.dob.mm}${passenger.dob.dd}`;
const expiryDate = `${passenger.passExpireDt.yyyy.substring(2)}${passenger.passExpireDt.mm}${passenger.passExpireDt.dd}`;
const gender = passenger.gender.substring(0, 1).toUpperCase();
let codeLine2 = `${icaoPassportNumber}${checkDigit(
icaoPassportNumber
)}${passenger.nationality.code}${birthDate}${checkDigit(
birthDate
)}${gender}${expiryDate}${checkDigit(expiryDate)}`;

if (codeLine2.length) {
const filler = "<".repeat(MRZ_TD3_LINE_LENGTH - 2 - codeLine2.length);
codeLine2 += filler;
codeLine2 += checkDigit(filler);

// Composite check digit for characters of machine readable data of the lower line in positions 1 to 10, 14 to 20 and 22 to 43, including values for
// letters that are a part of the number fields and their check digits.
const compositeCheckDigit = checkDigit(
codeLine2.substring(0, 10) +
codeLine2.substring(13, 20) +
codeLine2.substring(21, 43)
);
codeLine2 += compositeCheckDigit.replace(/[-]/g, "<");
}

return `${codeLine1}\n${codeLine2}`.toUpperCase();
} catch (error) {
console.warn(error);
return null;
}
};

function checkDigit(inputData) {
// http://www.highprogrammer.com/alan/numbers/mrp.html#checkdigit
let multiplier = 7;
let total = 0;
for (const char of inputData) {
total += checkDigitDiagram[char] * multiplier;
if (multiplier === 7) multiplier = 3;
else if (multiplier === 3) multiplier = 1;
else if (multiplier === 1) multiplier = 7;
}

const result = total % 10;
return result.toString();
}

const checkDigitDiagram = {
"<": 0,
0: 0,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
6: 6,
7: 7,
8: 8,
9: 9,
A: 10,
B: 11,
C: 12,
D: 13,
E: 14,
F: 15,
G: 16,
H: 17,
I: 18,
J: 19,
K: 20,
L: 21,
M: 22,
N: 23,
O: 24,
P: 25,
Q: 26,
R: 27,
S: 28,
T: 29,
U: 30,
V: 31,
W: 32,
X: 33,
Y: 34,
Z: 35
};
module.exports = {
hijriYear,
findConfig,
Expand Down Expand Up @@ -1843,4 +1942,5 @@ module.exports = {
downloadPDF,
clickWhenReady,
pdfToKea,
generateMRZ,
};

0 comments on commit 57a9b75

Please sign in to comment.