use chromiumoxide::Page;
#[cfg(feature = "debug")]
use log::{debug, info, trace};
use crate::{PinterestLoginError, PINTEREST_LOGIN_URL};
#[async_trait::async_trait]
pub trait BrowserLoginBot {
async fn fill_login_form(&self, page: &Page) -> crate::Result<()>;
async fn submit_login_form(&self, page: &Page) -> crate::Result<()>;
async fn check_login(&self, page: &Page) -> crate::Result<()>;
}
pub struct DefaultBrowserLoginBot<'a> {
email: &'a str,
password: &'a str,
}
impl<'a> DefaultBrowserLoginBot<'a> {
pub fn new(email: &'a str, password: &'a str) -> Self {
Self { email, password }
}
}
#[async_trait::async_trait]
impl BrowserLoginBot for DefaultBrowserLoginBot<'_> {
#[inline(always)]
async fn fill_login_form(&self, page: &Page) -> crate::Result<()> {
const EMAIL_INPUT_SELECTOR: &str = "input#email";
const PASSWORD_INPUT_SELECTOR: &str = "input#password";
#[cfg(feature = "debug")]
{
trace!(
"Filling the login form with the email: {} and password: {}",
self.email,
self.password
);
debug!("entering the email");
trace!(
"Finding the email input field with the selector: {}",
EMAIL_INPUT_SELECTOR
);
}
page.find_element(EMAIL_INPUT_SELECTOR)
.await?
.click()
.await?
.type_str(self.email)
.await?;
#[cfg(feature = "debug")]
{
debug!("Email entered successfully, entering the password");
trace!(
"Finding the password input field with the selector: {}",
PASSWORD_INPUT_SELECTOR
);
}
page.find_element(PASSWORD_INPUT_SELECTOR)
.await?
.click()
.await?
.type_str(self.password)
.await?;
#[cfg(feature = "debug")]
debug!("Password entered successfully");
Ok(())
}
#[inline(always)]
async fn submit_login_form(&self, page: &Page) -> crate::Result<()> {
const LOGIN_BUTTON_SELECTOR: &str = "button[type='submit']";
#[cfg(feature = "debug")]
{
debug!("Submitting the login form");
info!("Finding the submit button and clicking it");
trace!(
"Finding the submit button with the selector: {}",
LOGIN_BUTTON_SELECTOR
);
}
page.find_element(LOGIN_BUTTON_SELECTOR)
.await?
.click()
.await?;
#[cfg(feature = "debug")]
debug!("Login form submitted successfully");
Ok(())
}
#[inline(always)]
async fn check_login(&self, page: &Page) -> crate::Result<()> {
#[cfg(feature = "debug")]
debug!("Checking if the login was successful");
match page.wait_for_navigation().await?.url().await? {
None => {
#[cfg(feature = "debug")]
debug!("Couldn't get the url, the login was unsuccessful");
Err(PinterestLoginError::AuthenticationError)
}
Some(url) => {
#[cfg(feature = "debug")]
{
debug!("Got the url: {}", url);
info!("Checking if the url is the same as the login url");
}
if url == PINTEREST_LOGIN_URL {
#[cfg(feature = "debug")]
debug!("The url is the same as the login url, the login was unsuccessful");
Err(PinterestLoginError::AuthenticationError)
} else {
#[cfg(feature = "debug")]
info!("The url is not the same as the login url, the login was successful");
Ok(())
}
}
}
}
}