Skip to content

Commit

Permalink
Add FreeBSD support (#1054)
Browse files Browse the repository at this point in the history
  • Loading branch information
Asthowen committed Feb 28, 2024
1 parent 0bc7a44 commit afdc1c7
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 24 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ This is the recommended way for Windows users.
* Run `pip install -r requirements.txt` command to install FlareSolverr dependencies.
* Run `python src/flaresolverr.py` command to start FlareSolverr.

### From source code (FreeBSD/TrueNAS CORE)

* Run `pkg install chromium python39 py39-pip xorg-vfbserver` command to install the required dependencies.
* Clone this repository and open a shell in that path.
* Run `python3.9 -m pip install -r requirements.txt` command to install FlareSolverr dependencies.
* Run `python3.9 src/flaresolverr.py` command to start FlareSolverr.

### Systemd service

We provide an example Systemd unit file `flaresolverr.service` as reference. You have to modify the file to suit your needs: paths, user and environment variables.
Expand Down
4 changes: 3 additions & 1 deletion src/undetected_chromedriver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,10 @@ def __init__(
options.binary_location, *options.arguments
)
else:
startupinfo = subprocess.STARTUPINFO()
startupinfo = None
if os.name == 'nt' and windows_headless:
# STARTUPINFO() is Windows only
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
browser = subprocess.Popen(
[options.binary_location, *options.arguments],
Expand Down
78 changes: 58 additions & 20 deletions src/undetected_chromedriver/patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

logger = logging.getLogger(__name__)

IS_POSIX = sys.platform.startswith(("darwin", "cygwin", "linux", "linux2"))
IS_POSIX = sys.platform.startswith(("darwin", "cygwin", "linux", "linux2", "freebsd"))


class Patcher(object):
Expand Down Expand Up @@ -80,9 +80,14 @@ def __init__(
os.makedirs(self.data_path, exist_ok=True)

if not executable_path:
self.executable_path = os.path.join(
self.data_path, "_".join([prefix, self.exe_name])
)
if sys.platform.startswith("freebsd"):
self.executable_path = os.path.join(
self.data_path, self.exe_name
)
else:
self.executable_path = os.path.join(
self.data_path, "_".join([prefix, self.exe_name])
)

if not IS_POSIX:
if executable_path:
Expand Down Expand Up @@ -127,6 +132,9 @@ def _set_platform_name(self):
else:
self.platform_name = "mac-x64"
self.exe_name %= ""
if self.platform.startswith("freebsd"):
self.platform_name = "freebsd"
self.exe_name %= ""

def auto(self, executable_path=None, force=False, version_main=None, _=None):
"""
Expand Down Expand Up @@ -166,26 +174,56 @@ def auto(self, executable_path=None, force=False, version_main=None, _=None):
if force is True:
self.force = force

try:
os.unlink(self.executable_path)
except PermissionError:
if self.force:
self.force_kill_instances(self.executable_path)
return self.auto(force=not self.force)

if self.platform_name == "freebsd":
chromedriver_path = shutil.which("chromedriver")

if not os.path.isfile(chromedriver_path) or not os.access(chromedriver_path, os.X_OK):
logging.error("Chromedriver not installed!")
return

version_path = os.path.join(os.path.dirname(self.executable_path), "version.txt")

process = os.popen(f'"{chromedriver_path}" --version')
chromedriver_version = process.read().split(' ')[1].split(' ')[0]
process.close()

current_version = None
if os.path.isfile(version_path) or os.access(version_path, os.X_OK):
with open(version_path, 'r') as f:
current_version = f.read()

if current_version != chromedriver_version:
logging.info("Copying chromedriver executable...")
shutil.copy(chromedriver_path, self.executable_path)
os.chmod(self.executable_path, 0o755)

with open(version_path, 'w') as f:
f.write(chromedriver_version)

logging.info("Chromedriver executable copied!")
else:
try:
if self.is_binary_patched():
# assumes already running AND patched
return True
os.unlink(self.executable_path)
except PermissionError:
if self.force:
self.force_kill_instances(self.executable_path)
return self.auto(force=not self.force)
try:
if self.is_binary_patched():
# assumes already running AND patched
return True
except PermissionError:
pass
# return False
except FileNotFoundError:
pass
# return False
except FileNotFoundError:
pass

release = self.fetch_release_number()
self.version_main = release.version[0]
self.version_full = release
self.unzip_package(self.fetch_package())
release = self.fetch_release_number()
self.version_main = release.version[0]
self.version_full = release
self.unzip_package(self.fetch_package())

return self.patch()

def driver_binary_in_use(self, path: str = None) -> bool:
Expand Down
10 changes: 7 additions & 3 deletions src/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import shutil
import urllib.parse
import tempfile
import sys

from selenium.webdriver.chrome.webdriver import WebDriver
import undetected_chromedriver as uc
Expand Down Expand Up @@ -182,9 +183,12 @@ def get_webdriver(proxy: dict = None) -> WebDriver:

# downloads and patches the chromedriver
# if we don't set driver_executable_path it downloads, patches, and deletes the driver each time
driver = uc.Chrome(options=options, browser_executable_path=browser_executable_path,
driver_executable_path=driver_exe_path, version_main=version_main,
windows_headless=windows_headless, headless=windows_headless)
try:
driver = uc.Chrome(options=options, browser_executable_path=browser_executable_path,
driver_executable_path=driver_exe_path, version_main=version_main,
windows_headless=windows_headless, headless=windows_headless)
except Exception as e:
logging.error("Error starting Chrome: %s" % e)

# save the patched driver to avoid re-downloads
if driver_exe_path is None:
Expand Down

0 comments on commit afdc1c7

Please sign in to comment.