-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
124 lines (100 loc) Β· 4.12 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// TO DO:
// 1. make app run on a schdule, a few times a day, exept when servers are closed.
// 2. communiate availability result to user, screen shot / mapped data of each test center and wether they have slots available
// EXTRA FEATURE: if slot is available, make the bot book the next available slot for you. At present you ould have to login-in yourself ASAP and hope the slot is still available.
import dotenv from 'dotenv'
import puppeteer from 'puppeteer-extra'
import StealthPlugin from 'puppeteer-extra-plugin-stealth'
import RecaptchaPlugin from 'puppeteer-extra-plugin-recaptcha'
dotenv.config()
// .env variables for hiding sensitive info
const apiToken = process.env['API_TOKEN']
const drivingLicenceNumber = process.env['DRIVING_LICENCE_NUMBER']
const theoryTestPassNumber = process.env['THEORY_TEST_PASS_NUMBER']
// application global variables
const timeoutDuration = 480000
const clickDelay = 30
puppeteer.use(StealthPlugin())
puppeteer.use(
RecaptchaPlugin({
provider: { id: '2captcha', token: apiToken },
visualFeedback: true // colorize reCAPTCHAs (violet = detected, green = solved)
})
)
const customArgs = [
'--disable-features=IsolateOrigins,site-per-process',
'--flag-switches-begin --disable-site-isolation-trials --flag-switches-end',
'--disable-web-security'
]
const chromeOptions = {
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
headless: true,
slowMo: 30,
defaultViewport: null,
args: customArgs
}
const handleRecaptcha = async(page) => {
try {
for (const frame of await page.mainFrame().childFrames()) {
console.log('π¨ recaptcha found')
await frame.solveRecaptchas()
console.log('𧩠recaptcha solved')
}
} catch (err) {
console.log(err)
}
}
const checkWebsite = async() => {
try {
// * launch puppetteer
console.log('π launching puppeteer')
const browser = await puppeteer.launch(chromeOptions)
const page = await browser.newPage()
await page.goto('https://driverpracticaltest.dvsa.gov.uk/login')
// ? page nav (potential reCaptcha checkpoint)
await handleRecaptcha(page)
// * Wait to leave server queue
console.log('π¨ entering server queue')
await page.waitForNavigation({ timeout: timeoutDuration })
//console.log('β
left server queue')
// ? page nav (potential reCaptcha checkpoint)
// await handleRecaptcha(page)
// console.log('π page navigated')
// * handle login form
await page.waitForSelector('#driving-licence-number', { timeout: timeoutDuration })
console.log('β
left server queue')
console.log('π page navigated')
await page.type('#driving-licence-number', drivingLicenceNumber)
await page.click('#use-theory-test-number', { delay: clickDelay })
await page.type('#theory-test-pass-number', theoryTestPassNumber)
await page.click('#booking-login', { delay: clickDelay })
console.log('β
logged in')
// ? page nav (potential reCaptcha checkpoint)
await handleRecaptcha(page)
console.log('π page navigated')
// * next page actions
await page.waitForSelector('#test-centre-change', { timeout: timeoutDuration })
await page.click('#test-centre-change', { delay: clickDelay })
console.log('β
form submitted')
// ? page nav (potential reCaptcha checkpoint)
await handleRecaptcha(page)
console.log('π page navigated')
// * next page actions
await page.waitForSelector('#test-centres-input', { timeout: timeoutDuration })
await page.type('#test-centres-input', 'PO9 6DY')
await page.click('#test-centres-submit', { delay: clickDelay })
console.log('β
form submitted')
// ? page nav (potential reCaptcha checkpoint)
await handleRecaptcha(page)
console.log('π page navigated')
// * results page
const resultsArray = await page.$$eval('.test-centre-details > span', results => results.map(result => result.textContent))
console.log('π RESULTS FOUND ->', await resultsArray)
// await page.screenshot({ path: 'results-page.png' })
// * done
await browser.close()
} catch (err) {
console.log(err)
}
}
checkWebsite()