Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ curl -X POST http://localhost:3001/create-issue -H "Content-Type: application/js
docker build -t backend .
docker run -it -p 3001:3001 -e GITHUB_TOKEN -e GITHUB_OWNER -e GITHUB_REPO backend
```

alternatively - run with docker-compose:
```
docker compose up --build --remove-orphans
```
21 changes: 21 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
services:
mongo:
image: mongo:8.0.3
volumes:
- mongo-data:/data/db
ports:
- "27017:27017"
api:
build: .
ports:
- "3000:3000"
depends_on:
- mongo
environment:
MONGODB_URI: "mongodb://mongo:27017/open-bus"
volumes:
- .:/usr/src/app
command: npm run dev

volumes:
mongo-data:
115 changes: 115 additions & 0 deletions controllers/complaintController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { chromium } from 'playwright'

let isBusy = false

export 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
}
}
6 changes: 2 additions & 4 deletions controllers/issueController.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const axios = require('axios');
import axios from 'axios';

const createIssue = async (req, res) => {
export const createIssue = async (req, res) => {
try {
// Extract data from the request body
const {
Expand Down Expand Up @@ -53,5 +53,3 @@ const createIssue = async (req, res) => {
res.status(500).json({ error: 'Internal Server Error' });
}
};

module.exports = { createIssue };
24 changes: 18 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const { createIssue } = require('./controllers/issueController');
import express from 'express';
import cors from 'cors';
import { MongoClient } from 'mongodb';

import { createIssue } from './controllers/issueController.js';
import { complaintController } from './controllers/complaintController.js';

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

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

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

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

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

const client = await MongoClient.connect(process.env.MONGODB_URI ?? 'mongodb://localhost:27017');
const db = client.db('open-bus');
console.log('Connected to MongoDB successfully');

app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
console.log(`Server is running on port ${PORT}`);
});

Loading