add auto validation and takint appointment

This commit is contained in:
andres
2023-03-17 13:16:11 +01:00
parent 35ffac518c
commit 3eb9c81cbf
2 changed files with 110 additions and 5 deletions

15
.idea/git_toolbox_prj.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View File

@@ -1,14 +1,15 @@
import { chromium, type Page } from 'playwright' import { chromium, type Page } from 'playwright'
import { type Browser, expect } from '@playwright/test' import { type Browser, expect } from '@playwright/test'
import { Markup, Telegraf } from 'telegraf' import { type Context, Markup, Telegraf } from 'telegraf'
import dotenv from 'dotenv' import dotenv from 'dotenv'
import { type InputFile } from 'telegraf/types' import { type InputFile } from 'telegraf/types'
import { message } from 'telegraf/filters' import { message } from 'telegraf/filters'
import cron from 'node-cron' import cron from 'node-cron'
dotenv.config() dotenv.config()
const url = 'https://icp.administracionelectronica.gob.es/icpplustiem/citar?p=28&locale=es&appkey=null' // const url = 'https://icp.administracionelectronica.gob.es/icpplustiem/citar?p=28&locale=es&appkey=null'
const { NIE, NAME, COUNTRY_CODE } = process.env const url = 'https://icp.administracionelectronica.gob.es/icpplustiem/citar?p=1&locale=es&appkey=null'
const { NIE, NAME, COUNTRY_CODE, EMAIL, PHONE_NUMBER } = process.env
const NO_APPOINTMENT = 'no hay citas disponibles' const NO_APPOINTMENT = 'no hay citas disponibles'
const delay = async (ms: number) => await new Promise(resolve => setTimeout(resolve, ms)) const delay = async (ms: number) => await new Promise(resolve => setTimeout(resolve, ms))
const screenshots = [] as Array<{ inputFile: InputFile, message: string }> const screenshots = [] as Array<{ inputFile: InputFile, message: string }>
@@ -109,8 +110,83 @@ const step6 = async (page: Page) => {
await saveScreenshot(page, 'step 6') await saveScreenshot(page, 'step 6')
} }
const step7 = async (page: Page) => {
const select = page.getByLabel('Oficina:')
try {
await expect(select).toBeEnabled()
await select.selectOption({ index: 0 })
await delay(2000)
await page.click('#btnSiguiente')
await saveScreenshot(page, 'step 7')
} catch (e) {
await saveScreenshot(page, 'select is not enabled')
await sendText(bot, 'select is not enabled, ' + JSON.stringify(e))
await page.close()
}
}
const step8 = async (page: Page) => {
try {
await page.locator('#txtTelefonoCitado').fill(PHONE_NUMBER ?? '')
await page.locator('#emailUNO').fill(EMAIL ?? '')
await page.locator('#emailDOS').selectOption([EMAIL ?? ''])
await delay(2000)
await page.click('#btnSiguiente')
await saveScreenshot(page, 'step 8')
} catch (e) {
await saveScreenshot(page, 'step 8 failed' + JSON.stringify(e))
}
}
const step9 = async (page: Page) => {
try {
page.on('dialog', dialog => {
void dialog.accept()
}
)
const captcha = await page.waitForSelector('#captcha', { timeout: 1000 })
const isCaptchaVisible = await captcha.isVisible()
if (isCaptchaVisible) {
await saveScreenshot(page, 'captcha')
await sendText(bot, 'captcha')
const captchaSolved = await waitForUserMessage()
if (typeof captchaSolved === 'string') {
await captcha.fill(captchaSolved)
}
await saveScreenshot(page, 'step 9 captcha solved')
}
await page.getByRole('link', { name: 'LIBRE' }).click()
await saveScreenshot(page, 'step 9 finished')
} catch (e) {
await saveScreenshot(page, 'step 9 failed' + JSON.stringify(e))
}
}
const step10 = async (page: Page) => {
try {
const codeFromPhone = await page.waitForSelector('#txtCodigoVerificacion', { timeout: 1000 })
const isVerificationVisible = await codeFromPhone.isVisible()
if (isVerificationVisible) {
await sendText(bot, 'verification code')
const solved = await waitForUserMessage()
if (typeof solved === 'string') {
await codeFromPhone.fill(solved)
}
await saveScreenshot(page, 'step 10 verification solved')
}
await page.locator('#conforme').click()
await delay(500)
await page.locator('#conformidadCorreo').click()
await delay(500)
await saveScreenshot(page, 'step 10 before click')
await page.locator('#btnConfirmar').click()
await saveScreenshot(page, 'step 10 finished')
} catch (e) {
await saveScreenshot(page, 'step 10 failed' + JSON.stringify(e))
}
}
const scrape = async () => { const scrape = async () => {
const browser = await chromium.launch({ headless: false }) const browser = await chromium.launch({ slowMo: 100 })
try { try {
const page = await browser.newPage() const page = await browser.newPage()
await step1(page) await step1(page)
@@ -119,6 +195,11 @@ const scrape = async () => {
await step4(page) await step4(page)
await step5(page, browser) await step5(page, browser)
await step6(page) await step6(page)
await step7(page)
await step8(page)
await step9(page)
await step10(page)
await page.close()
await browser.close() await browser.close()
} catch (e) { } catch (e) {
await sendText(bot, JSON.stringify(e)) await sendText(bot, JSON.stringify(e))
@@ -129,8 +210,17 @@ const scrape = async () => {
} }
const cronTask = cron.schedule('*/4 9-17 * * *', async () => { const cronTask = cron.schedule('*/4 9-17 * * *', async () => {
await scrape() await scrape()
}) }, { scheduled: false })
console.log('valid: ', cron.validate('*/4 9-17 * * *')) console.log('valid: ', cron.validate('*/4 9-17 * * *'))
async function waitForUserMessage () {
return await new Promise((resolve) => {
const messageHandler = async (newCtx: Context) => {
resolve(newCtx.message)
}
bot.on('message', messageHandler)
})
}
bot.on(message('text'), async (ctx) => { bot.on(message('text'), async (ctx) => {
const text = ctx.message?.text const text = ctx.message?.text
if (ctx.message.from.id !== Number(process.env.MY_TELEGRAM_ID)) return if (ctx.message.from.id !== Number(process.env.MY_TELEGRAM_ID)) return