Skip to content

Instantly share code, notes, and snippets.

@emrekasg
Created January 12, 2024 03:36
Show Gist options
  • Save emrekasg/7250efcccb263ece9007044ad6dba40a to your computer and use it in GitHub Desktop.
Save emrekasg/7250efcccb263ece9007044ad6dba40a to your computer and use it in GitHub Desktop.
USA Visa Appointment slot picker
const { Builder, Key, By, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
console.log('Starting Chrome WebDriver');
let options = new chrome.Options();
// Modular function to create a WebDriver instance
async function createDriver() {
return new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
}
// Function to scroll to the bottom of a page
async function scrollToBottom(driver) {
await driver.executeScript("window.scrollTo(0, document.body.scrollHeight)");
}
// Function to perform login
async function performLogin(driver) {
await driver.get('https://ais.usvisa-info.com/tr-tr/niv/users/sign_in');
await scrollToBottom(driver);
await driver.findElement({ id: 'user_email' }).sendKeys('');
await driver.findElement({ id: 'user_password' }).sendKeys('Emre1234!!');
let checkbox = await driver.findElement({ className: 'icheckbox' });
await checkbox.click();
await driver.findElement({ name: 'commit' }).click();
}
// Function to navigate to the appointment page
async function navigateToAppointmentPage(driver) {
await driver.sleep(4000);
await driver.get(""); // the appointment url you want to check
}
// Function to select a consulate
async function selectConsulate(driver, consulate) {
let select = await driver.findElement({ id: 'appointments_consulate_appointment_facility_id' });
let options = await select.findElements({ tagName: 'option' });
for (let option of options) {
let text = await option.getText();
if (consulate === text) {
await option.click();
return true;
}
}
throw new Error('Consulate not found');
}
// Function to select a date from the date picker
async function selectDateFromDatePicker(driver, wantedMonths) {
await driver.findElement({ id: 'appointments_consulate_appointment_date' }).click();
let foundSlot = false;
let noAvailableDate = false;
while (!foundSlot) {
let firstMonthText = await getMonthText(driver, 'ui-datepicker-group-first');
let secondMonthText = await getMonthText(driver, 'ui-datepicker-group-last');
let firstYearText = await getYearText(driver, 'ui-datepicker-group-first');
let secondYearText = await getYearText(driver, 'ui-datepicker-group-last');
console.log(`First month displayed: ${firstMonthText}`);
if (firstYearText !== '2024') {
console.log('Year is not 2024, skipping');
return false;
}
if (wantedMonths.includes(firstMonthText) && firstYearText === '2024') {
foundSlot = await selectAvailableDate(driver, 'ui-datepicker-group-first');
} else if (wantedMonths.includes(secondMonthText) && secondYearText === '2024') {
foundSlot = await selectAvailableDate(driver, 'ui-datepicker-group-last');
}
if (!foundSlot) {
// Navigate to the next month
await driver.findElement({ className: 'ui-datepicker-next' }).click();
await driver.sleep(2000);
}
}
return true;
}
// Function to get the month text from a date picker group
async function getMonthText(driver, className) {
let monthGroup = await driver.findElement({ className: className });
let monthTitle = await monthGroup.findElement({ className: 'ui-datepicker-title' });
let monthSpan = await monthTitle.findElement({ className: 'ui-datepicker-month' });
return await monthSpan.getText();
}
async function getYearText(driver, className) {
let monthGroup = await driver.findElement({ className: className });
let monthTitle = await monthGroup.findElement({ className: 'ui-datepicker-title' });
let monthSpan = await monthTitle.findElement({ className: 'ui-datepicker-year' });
return await monthSpan.getText();
}
// Function to select an available date from a specific date picker group
async function selectAvailableDate(driver, className) {
let datePickerGroup = await driver.findElement({ className: className });
let datePickerTable = await datePickerGroup.findElement({ className: 'ui-datepicker-calendar' });
let datePickerRows = await datePickerTable.findElements({ tagName: 'tr' });
for (let row of datePickerRows) {
let dates = await row.findElements({ tagName: 'td' });
for (let date of dates) {
let classAttr = await date.getAttribute('class');
if (!classAttr.includes('ui-state-disabled')) {
console.log('Available date found');
await date.click();
return true; // Date selected successfully
} else {
console.log('Date is not available, date: ' + await date.getText());
}
}
}
return false; // No available date found in this group
}
async function selectAvailableTime(driver) {
let appointmentTimes = await driver.findElement({ id: "appointments_consulate_appointment_time" });
let appointmentTimesOptions = await appointmentTimes.findElements({ tagName: 'option' });
for (let appointmentTimeOption of appointmentTimesOptions) {
let value = await appointmentTimeOption.getAttribute('value');
if (value !== '') {
await appointmentTimeOption.click();
return true;
}
}
return false;
}
async function automateTasks() {
let driver = await createDriver();
let foundEmptySlot = false;
while (!foundEmptySlot) {
try {
await performLogin(driver);
await scrollToBottom(driver);
for (let i = 0; i < 100000; i++) {
await navigateToAppointmentPage(driver);
// check if we logged in
let currentUrl = await driver.getCurrentUrl();
if (currentUrl !== '') { // the url you want to check
console.log('Not logged in, logging in again');
await performLogin(driver);
await scrollToBottom(driver);
await navigateToAppointmentPage(driver);
}
let consulates = ['Istanbul', 'Ankara'];
for (let consulate of consulates) {
console.log(`Checking for consulate: ${consulate}`);
await selectConsulate(driver, consulate);
await driver.sleep(1000);
const wantedMonths = ["January", "February", "March", "April", "May", "December"];
// run esc command to close the date picker
await driver.actions().sendKeys(Key.ESCAPE).perform();
await driver.sleep(1000);
await driver.actions().sendKeys(Key.ESCAPE).perform();
const success = await selectDateFromDatePicker(driver, wantedMonths);
if (!success) {
console.log('No available date found, skipping');
continue;
} else {
console.log('Available date found');
const foundTime = await selectAvailableTime(driver);
if (foundTime) {
console.log('Available time found');
foundEmptySlot = true;
break;
}else{
console.log('No available time found, skipping');
continue;
}
break;
}
}
if (foundEmptySlot) {
break;
}
await driver.sleep(30000);
}
} catch (error) {
console.error('Error occurred:', error);
await driver.sleep(30000); // Wait for 30 seconds before retrying
continue;
}
}
// closes the browser after finding an empty slot
await driver.quit();
}
automateTasks();
@rockswe
Copy link

rockswe commented Jan 12, 2024

oha

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment