Files
Beam/Beam.Stealth/StealthConfig.cs
T

126 lines
4.8 KiB
C#

using System;
using System.IO;
using Microsoft.Extensions.Logging;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Edge;
namespace Beam.Stealth {
public enum Browser {
Firefox = 0,
Chrome = 1,
Chromium = 2,
Edge = 3
}
public sealed class StealthConfig : IDisposable {
public bool ShowBrowser { get; init; }
public TimeSpan TimeOut { get; init; } = Timeout.InfiniteTimeSpan;
public string DownloadsDirectory { get; }
public ILogger? Logger { get; init; }
public required IWebDriver Driver { get; init; }
private StealthConfig(string downloadDir) => DownloadsDirectory = downloadDir;
/* ---------- browser-specific option builders ---------- */
private static FirefoxOptions GetFirefoxOptions(string downloadDir, bool headless) {
var o = new FirefoxOptions();
if (headless) o.AddArgument("--headless");
o.SetPreference("browser.download.folderList", 2); // use custom dir
o.SetPreference("browser.download.dir", downloadDir);
o.SetPreference("browser.download.useDownloadDir", true);
o.SetPreference("browser.helperApps.neverAsk.saveToDisk",
"application/octet-stream,application/pdf,application/zip");
o.SetPreference("pdfjs.disabled", true); // open PDFs externally
o.SetPreference("browser.download.manager.showWhenStarting", false);
return o;
}
private static ChromeOptions GetChromeOptions(string downloadDir, bool headless) {
var o = new ChromeOptions();
if (headless) o.AddArgument("--headless=new");
// download prefs
o.AddUserProfilePreference("download.default_directory", downloadDir);
o.AddUserProfilePreference("download.prompt_for_download", false);
o.AddUserProfilePreference("safebrowsing.enabled", false);
// common stability flags
o.AddArgument("--no-sandbox");
o.AddArgument("--disable-dev-shm-usage");
return o;
}
private static EdgeOptions GetEdgeOptions(string downloadDir, bool headless) {
var o = new EdgeOptions();
if (headless) o.AddArgument("--headless=new");
o.AddUserProfilePreference("download.default_directory", downloadDir);
o.AddUserProfilePreference("download.prompt_for_download", false);
o.AddUserProfilePreference("safebrowsing.enabled", false);
return o;
}
/* ---------- factory ---------- */
public static StealthConfig Create(
bool showBrowser = false,
string? downloadDir = null,
TimeSpan? timeOut = null,
Browser preferredBrowser = Browser.Firefox,
ILogger? logger = null) {
// pick or create a dedicated download folder
downloadDir ??= Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(downloadDir);
bool headless = !showBrowser;
IWebDriver? driver = null;
List<Exception>? errors = [];
while (preferredBrowser <= Browser.Edge) {
try {
driver = preferredBrowser switch {
Browser.Chrome or Browser.Chromium
=> new ChromeDriver(GetChromeOptions(downloadDir, headless)),
Browser.Edge
=> new EdgeDriver(GetEdgeOptions(downloadDir, headless)),
Browser.Firefox or _
=> new FirefoxDriver(GetFirefoxOptions(downloadDir, headless)),
};
break;
}
catch (Exception e) {
if (preferredBrowser != Browser.Edge)
logger?.LogWarning(e, "Failed to create driver for browser {Browser}, falling back to {Fallback}", preferredBrowser, Enum.GetName(preferredBrowser + 1));
else {
logger?.LogCritical(e, "Failed to create driver for browser {Browser}, no more fallback remaining!", preferredBrowser);
}
preferredBrowser++;
errors.Add(e);
}
}
if (driver is null)
throw new AggregateException(errors);
return new StealthConfig(downloadDir) {
ShowBrowser = showBrowser,
TimeOut = timeOut ?? Timeout.InfiniteTimeSpan,
Logger = logger,
Driver = driver
};
}
public void Dispose() {
Driver.Dispose();
}
}
}