119 lines
3.6 KiB
Rust
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(())
|
|
}
|
|
}
|