facebook webdriver | | list friends | Search

The code imports necessary dependencies, including Selenium, and defines environment variables for a user's profile directory and password file. The enterFacebook function is an asynchronous function that automates a Facebook sign-in process, including finding and filling out form elements, waiting for and handling potential CAPTCHA or other issues, and submitting the form.

Run example

npm run import -- "facebook login"

facebook login


const getClient = importer.import("selenium client")
const { Builder, Browser, By, Key, until } = require('selenium-webdriver')

const PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
const PASSWORDS_FILE = path.join(PROFILE_PATH, '.credentials', 'brian.json');

async function enterFacebook(driver) {
  console.log('Facebook: Sign in required');

  var credentials = require(PASSWORDS_FILE)

  //let body = await driver.findElement(By.css('body'))
  await driver.wait(until.elementLocated(By.css('.login-form, [type="submit"]')), 10000);
  let submit = await driver.findElement(By.css('.login-form, [type="submit"]'))

  let login = await driver.findElement(By.css('input[name*="email"]'))
  
  await driver.executeScript('arguments[0].click();', login)
  await driver.actions().sendKeys(credentials.username).perform()

  await new Promise(resolve => setTimeout(resolve, 1000))

  //await pass.sendKeys(credentials.username)
  //await driver.executeScript('arguments[0].value="' + credentials.username + '";', login)
  
  console.log('Facebook: Require password')

  let pass = await driver.findElement(By.css('input[name*="pass"]'))
  await pass.click()
  await pass.sendKeys(credentials.password)

  await submit.click()

  await new Promise(resolve => setTimeout(resolve, 3000))

  let loginStill, loginStill2, loginStill3
  try {
    loginStill = await driver.findElement(By.css('#captcha-internal'))
  } catch (e) {}
  try {
    loginStill2 = await driver.findElement(By.css('input[name*="session_password"]'))
  } catch (e) {}
  try {
    loginStill3 = await driver.findElement(By.xpath('//*[contains(text(),"Check your notifications")]'))
  } catch (e) {}

  if(loginStill3) {
    await new Promise(resolve => setTimeout(resolve, 20000))
    try {
      loginStill = false
      loginStill2 = false
      loginStill3 = await driver.findElement(By.xpath('//*[contains(text(),"Check your notifications")]'))
    } catch (e) {}
  }

  if(loginStill || loginStill2 || loginStill3) {
    throw new Error('captcha')
  }
}

async function loginFacebook(driver) {
  if(!driver) {
    driver = await getClient();
  }

  try {
    let url = await driver.getCurrentUrl()
    let loggedIn = url.indexOf('facebook') > -1 && url.indexOf('login') == -1

    if(loggedIn) {
      if(await driver.findElement(By.xpath('iframe.authentication-iframe'))) {
        await driver.frame((await driver.element('iframe.authentication-iframe')).value)
        await enterFacebook()
        await frame()
      }
    } else {
      await driver.get('https://www.facebook.com/')
      let loginLink, loginLink2
      try {
        loginLink = await driver.findElement(By.xpath('//a[text()[contains(.,"Forgot password?")]]'))
      } catch (e) {}
      try {
        loginLink2 = await driver.findElement(By.xpath('//a[text()[contains(.,"Create new account")]]'))
      } catch (e) {}
      if(loginLink || loginLink2) {
        await enterFacebook(driver)
      }
    }
  } catch (e) {
    driver.quit() // avoid leaving sessions hanging around

    throw e
  }

  return driver
}

module.exports = loginFacebook

What the code could have been:

const { Builder, Browser, By, Key, until, WebElement } = require('selenium-webdriver');
const path = require('path');
const { Client } = require('selenium-webdriver/lib/remote/index.js');

const PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
const PASSWORDS_FILE = path.join(PROFILE_PATH, '.credentials', 'brian.json');

async function enterFacebook(driver) {
  /**
   * Enters Facebook login credentials into the driver instance.
   * @param {Client} driver Selenium WebDriver instance.
   */
  console.log('Facebook: Sign in required');

  try {
    const credentials = require(PASSWORDS_FILE);
    await driver.wait(until.elementLocated(By.css('.login-form, [type="submit"]')), 10000);

    const submitButton = await driver.findElement(By.css('.login-form, [type="submit"]'));
    const emailInput = await driver.findElement(By.css('input[name*="email"]'));

    await driver.executeScript('arguments[0].click();', emailInput);
    await driver.actions().sendKeys(credentials.username).perform();

    await new Promise(resolve => setTimeout(resolve, 1000));

    const passwordInput = await driver.findElement(By.css('input[name*="pass"]'));
    await passwordInput.click();
    await passwordInput.sendKeys(credentials.password);

    await submitButton.click();

    await new Promise(resolve => setTimeout(resolve, 3000));
  } catch (e) {
    console.error('Failed to enter Facebook credentials', e);
    throw e;
  }

  try {
    // Wait for CAPTCHA to appear
    await driver.wait(until.elementLocated(By.css('#captcha-internal')), 20000);
    throw new Error('captcha');
  } catch (e) {}

  try {
    // Wait for notifications to appear
    const notification = await driver.findElement(By.xpath('//*[contains(text(),"Check your notifications")]'));
    await driver.sleep(20000); // Wait for notification to load
    await driver.wait(until.elementLocated(By.xpath('//*[contains(text(),"Check your notifications")]')), 20000);
    throw new Error('captcha');
  } catch (e) {}
}

async function loginFacebook(driver) {
  /**
   * Logs in to Facebook using the provided driver instance.
   * @param {Client} driver Selenium WebDriver instance.
   */
  if (!driver) {
    driver = await getClient();
  }

  try {
    const url = await driver.getCurrentUrl();
    const loggedIn = url.indexOf('facebook') > -1 && url.indexOf('login') == -1;

    if (loggedIn) {
      if (await driver.findElement(By.xpath('iframe.authentication-iframe'))) {
        await driver.switchTo().frame(await driver.findElement(By.xpath('iframe.authentication-iframe')));
        await enterFacebook();
        await driver.switchTo().defaultContent();
      }
    } else {
      await driver.get('https://www.facebook.com/');

      try {
        const loginLink = await driver.findElement(By.xpath('//a[text()[contains(.,"Forgot password?")]]'));
        const loginLink2 = await driver.findElement(By.xpath('//a[text()[contains(.,"Create new account")]]'));

        if (loginLink || loginLink2) {
          await enterFacebook(driver);
        }
      } catch (e) {
        console.error('Failed to find login link', e);
      }
    }
  } catch (e) {
    driver.quit(); // avoid leaving sessions hanging around

    throw e;
  }

  return driver;
}

module.exports = loginFacebook;

Code Breakdown

Importing Dependencies

The code imports the following dependencies:

Environment Variable and File Path

The code defines two environment variables:

enterFacebook Function

The enterFacebook function is an asynchronous function that takes a driver object as an argument. It performs the following actions:

  1. Logs a message to the console indicating that a Facebook sign-in is required
  2. Requires the credentials from the brian.json file
  3. Waits for the login form to be present on the page
  4. Finds the login form and submit button elements
  5. Finds the email input element, clicks it, and sends the username to it
  6. Waits for 1 second
  7. Finds the password input element, clicks it, and sends the password to it
  8. Submits the form
  9. Waits for 3 seconds
  10. Attempts to find the following elements:
  11. If any of these elements are found, it throws an error indicating that a CAPTCHA is required

Other Notes