frc/src/browser.rs

119 lines
3.6 KiB
Rust

use std::{env, path::Path};
use thirtyfour::{session::handle::SessionHandle, By, DesiredCapabilities, WebDriver};
pub struct BrowserSession {
driver: WebDriver,
}
const DATA_DIR_ARG: &str = "--user-data-dir";
#[cfg(target_os = "linux")]
const DATA_DIR_CHROMIUM: &str = "/.config/chromium";
#[cfg(target_os = "linux")]
const DATA_DIR_CHROME: &str = "~/.config/google-chrome";
#[cfg(target_os = "linux")]
const DATA_DIR_CHROME_BETA: &str = "~/.config/google-chrome-beta";
#[cfg(target_os = "linux")]
const HOME_VARIABLE: &str = "HOME";
#[cfg(target_os = "windows")]
const DATA_DIR_CHROME: &str = "\\Google\\Chrome\\User Data";
#[cfg(target_os = "windows")]
const DATA_DIR_CHROME_BETA: &str = "\\Google\\Chrome Beta\\User Data";
#[cfg(target_os = "windows")]
const DATA_DIR_CHROMIUM: &str = "\\Google\\Chromium\\User Data";
#[cfg(target_os = "windows")]
const HOME_VARIABLE: &str = "LOCALAPPDATA";
#[derive(Clone)]
pub struct BrowserHandle {
handle: SessionHandle,
}
fn get_data_dir() -> String {
let mut home = String::new();
for (key, val) in env::vars() {
if key == HOME_VARIABLE {
home = val;
}
}
if home.is_empty() {
panic!("cannot find home env variable");
}
let by_preference = vec![DATA_DIR_CHROMIUM, DATA_DIR_CHROME, DATA_DIR_CHROME_BETA];
for data_dir in by_preference {
if Path::new(format!("{}{}", home, data_dir).as_str()).exists() {
return format!("{}{}", home, data_dir);
}
}
// Default to chrome anyway I guess
return format!("{}{}", home, DATA_DIR_CHROME);
}
impl BrowserSession {
pub async fn new() -> Result<Self, anyhow::Error> {
// TODO: error if chrome is already running
let mut caps = DesiredCapabilities::chrome();
// Use the normal data directory (for extensions and logins)
let data_dir = get_data_dir();
println!("starting chrome using data directory: {}", data_dir);
#[cfg(target_os = "windows")]
let data_dir = format!("\"{}\"", data_dir);
caps.add_chrome_arg(format!("{}={}", DATA_DIR_ARG, data_dir).as_str())?;
let driver = WebDriver::new("http://localhost:6444", caps).await?;
println!("started browser");
Ok(Self { driver: driver })
}
pub fn handle(&self) -> BrowserHandle {
BrowserHandle {
handle: self.driver.clone(),
}
}
pub async fn stop(self) -> Result<(), anyhow::Error> {
self.driver.quit().await?;
Ok(())
}
}
impl BrowserHandle {
pub async fn start(&self, start_url: &str) -> Result<(), anyhow::Error> {
self.handle.fullscreen_window().await?;
self.handle
.get(format!("http://{}", start_url))
.await
.unwrap_or(()); // Ignore errors ig? idfk it errors out in some weirdo way but it works
Ok(())
}
async fn fullscreen_youtube(&self) -> Result<(), anyhow::Error> {
let elems = self
.handle
.find_elements(By::ClassName("ytp-fullscreen-button"))
.await?;
if elems.len() != 0 {
if let Some(button) = elems.first() {
button.click().await?;
}
}
Ok(())
}
async fn youtube(&self) -> Result<(), anyhow::Error> {
self.fullscreen_youtube().await?;
Ok(())
}
pub async fn go_to(&self, url: &str) -> Result<(), anyhow::Error> {
self.handle.get(url).await?;
if let Some(domain) = self.handle.current_url().await?.domain() {
if domain == "www.youtube.com" {
self.youtube().await?;
}
}
Ok(())
}
}