Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules/
.env
traces
117 changes: 117 additions & 0 deletions controllers/complaintController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
const { chromium } = require('playwright')

let isBusy = false

async function complaintController(req, res) {
if (isBusy) {
res.status(429).send('busy')
return
}
isBusy = true
try {
const url =
'https://forms.gov.il/globaldata/getsequence/getHtmlForm.aspx?formType=PniotMot%40mot.gov.il'

const complaint = req.body

console.log(complaint)

const complaintTypes = ['אי עצירה בתחנה', 'אחר']

const browser = await chromium.launch({
// headless: false,
})
const context = await browser.newContext()
await context.tracing.start({
screenshots: true,
snapshots: true,
sources: true,
})
const page = await context.newPage()
try {
for (let attempt = 0; attempt < 3; attempt++) {
try {
await page.goto(url)
await page.click('text=כניסה לטופס')
await page.getByLabel('שם פרטי').fill(complaint.firstName)
await page.getByLabel('שם משפחה').fill(complaint.lastName)
await page.getByLabel('מספר זהות').fill(complaint.id)
await page.getByLabel('טלפון נייד', { exact: true }).fill(complaint.phone)
await page.getByRole('textbox', { name: 'דואר אלקטרוני' }).fill(complaint.email)
await page.getByRole('button', { name: 'לשלב הבא' }).click()
// await page.getByLabel('נושא הפנייה').getByLabel('בחירה מהרשימה').first().click()
// await new Promise((r) => setTimeout(r, 100))
await page.getByLabel('נושא הפנייה', { exact: true }).fill('אוטובוס')
await new Promise((r) => setTimeout(r, 100))
await page.getByLabel('נושא הפנייה').getByLabel('בחירה מהרשימה').first().click()
await new Promise((r) => setTimeout(r, 100))
await page.getByText('אוטובוס', { exact: true }).click()
await new Promise((r) => setTimeout(r, 100))
await page.getByLabel('סוג הפנייה').fill(complaintTypes[0])
await new Promise((r) => setTimeout(r, 100))
await page.getByText(complaintTypes[0]).click()
await new Promise((r) => setTimeout(r, 100))
await page.getByRole('button', { name: 'לשלב הבא' }).click()
await page.getByLabel('חברת האוטובוסים (מפעיל)').fill(complaint.operator)
await page.getByRole('textbox', { name: 'מספר רישוי' }).fill(complaint.licensePlate)
await page.getByRole('textbox', { name: 'תאריך האירוע' }).fill(formatDate(complaint.time))
await page.getByRole('textbox', { name: 'שעת האירוע' }).fill(formatTime(complaint.time))
await page.getByLabel('שעת המתנה מ').fill('00:00')
await page.getByLabel('שעת המתנה עד').fill('23:59')
await page
.getByRole('textbox', { name: 'תוכן הפנייה' })
.fill('האוטובוס עצר בתחנה ולא נסע עד שעה מאוחרת')
await page.getByRole('textbox', { name: 'מספר קו' }).fill(complaint.lineNumber)
await page.getByLabel('מוצא/ יעד (כיוון )').fill(complaint.routeName)

for (let i = 0; i < 10 && (await page.getByText('הנחיות לצירוף מסמכים').isHidden()); i++) {
// retry until it works
await page.getByRole('button', { name: 'לשלב הבא' }).click()
await page.waitForTimeout(300)
}
break
} catch (e) {
console.log(`attempt ${attempt} failed`, e)
}
}
if(process.env.ENV === 'production' && !complaint.dryRun) {
await page.getByTitle('לחצו כאן לשליחת הטופס').click();
} else {
await page.getByText('לחצו כאן לשליחת הטופס').waitFor({ state: 'visible' });
}
} finally {
await context.tracing.stop({
path: `./traces/trace.zip`,
})
// await page.waitForTimeout(10000)
await browser.close()
}
/**
* @param {Date} date
*/
function formatDate(date) {
date = new Date(date)
const d = leadZero(date.getDate())
const month = leadZero(date.getMonth() + 1)
const year = date.getFullYear()
return `${d}/${month}/${year}`
}

function formatTime(date) {
date = new Date(date)
return `${leadZero(date.getHours())}:${leadZero(date.getMinutes())}`
}

function leadZero(number) {
return number < 10 ? `0${number}` : number
}
res.send('sent complaint')
} catch (e) {
console.log(e)
res.status(500).send(e.message)
} finally {
isBusy = false
}
}

exports.complaintController = complaintController
6 changes: 6 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@ const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const { createIssue } = require('./controllers/issueController');
const { complaintController } = require('./controllers/complaintController');

const app = express();
const PORT = process.env.PORT || 3001;

app.use(cors());
app.use(bodyParser.json());

app.get('/', (_, res) => {res.send('alive')});

app.post('/create-issue', createIssue);
app.post('/complaint', complaintController);

app.use('/traces', express.static('traces'));

app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
Expand Down
44 changes: 43 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"axios": "^1.6.5",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.18.2"
"express": "^4.18.2",
"playwright": "^1.41.1"
}
}