Each prerequisite now follows probe -> offer install -> probe again. The second probe matters: a freshly installed tool is never visible to `where` in the session that installed it, since the process inherited its PATH at start. A *_TRIED guard stops the loop at one attempt. Node installs from the LTS package on purpose - better-sqlite3 publishes prebuilt binaries for LTS, so this sidesteps the node-gyp compile that the existing Node >= 23 warning covers. Python detection runs the interpreter instead of calling `where python`. Windows ships a stub python.exe under WindowsApps that only opens the Microsoft Store; `where` finds it but it cannot execute anything. Asking for sys.version_info distinguishes the two, and the py launcher is preferred because the stub does not shadow it. Dependency install now upgrades pip first and verifies pyautogui actually imports, rather than trusting pip's exit code alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
306 lines
11 KiB
Batchfile
306 lines
11 KiB
Batchfile
@echo off
|
|
setlocal EnableExtensions
|
|
title AutoFirmer - Windows setup
|
|
|
|
REM ============================================================================
|
|
REM AutoFirmer instance setup for Windows.
|
|
REM
|
|
REM Standalone: drop this file anywhere and run it. It clones the repo into a
|
|
REM subfolder next to itself, installs, builds, and points the instance at the
|
|
REM master dashboard. Safe to re-run - it pulls and rebuilds instead of cloning.
|
|
REM ============================================================================
|
|
|
|
set "REPO_URL=https://git.juicerroom.com/senofy/autofirmer-expanded.git"
|
|
set "DEFAULT_MASTER=https://master.juicerroom.com"
|
|
set "TARGET=%~dp0autofirmer"
|
|
|
|
echo.
|
|
echo ============================================
|
|
echo AutoFirmer - Windows setup
|
|
echo ============================================
|
|
echo.
|
|
|
|
REM ---------------------------------------------------------------- git check
|
|
REM Git for Windows only lands on PATH if "Git from the command line" was chosen
|
|
REM at install time, and an already-open cmd keeps its old PATH regardless. So:
|
|
REM probe the usual homes, then offer to install, then probe again - a fresh
|
|
REM install is never visible to `where` in this session.
|
|
:git_probe
|
|
where git >nul 2>&1
|
|
if not errorlevel 1 goto :git_done
|
|
if exist "%ProgramFiles%\Git\cmd\git.exe" set "PATH=%ProgramFiles%\Git\cmd;%PATH%"
|
|
if exist "%ProgramFiles(x86)%\Git\cmd\git.exe" set "PATH=%ProgramFiles(x86)%\Git\cmd;%PATH%"
|
|
if exist "%LOCALAPPDATA%\Programs\Git\cmd\git.exe" set "PATH=%LOCALAPPDATA%\Programs\Git\cmd;%PATH%"
|
|
where git >nul 2>&1
|
|
if not errorlevel 1 goto :git_found_offpath
|
|
if "%GIT_TRIED%"=="1" goto :git_missing
|
|
where winget >nul 2>&1
|
|
if errorlevel 1 goto :git_missing
|
|
echo.
|
|
echo [--] Git is not installed.
|
|
set "DOIT="
|
|
set /p "DOIT= Install it now with winget? [Y/n] "
|
|
if /i "%DOIT%"=="n" goto :git_missing
|
|
set "GIT_TRIED=1"
|
|
echo Installing Git ^(a UAC prompt may appear^)...
|
|
winget install --id Git.Git -e --source winget --accept-source-agreements --accept-package-agreements --silent
|
|
goto :git_probe
|
|
|
|
:git_found_offpath
|
|
echo [ok] git ^(found off PATH, added for this run^)
|
|
goto :git_done
|
|
|
|
:git_missing
|
|
echo [X] Git not found on PATH, and not in any of:
|
|
echo %ProgramFiles%\Git\cmd
|
|
echo %LOCALAPPDATA%\Programs\Git\cmd
|
|
echo.
|
|
echo Install it from https://git-scm.com/download/win
|
|
echo If you JUST installed it: close this window, open a new Command
|
|
echo Prompt and run the script again - an open window keeps its old PATH.
|
|
goto :fail
|
|
|
|
:git_done
|
|
echo [ok] git
|
|
|
|
REM --------------------------------------------------------------- node check
|
|
REM winget's LTS package is deliberate: better-sqlite3 publishes prebuilt
|
|
REM binaries for LTS Node, so installing LTS sidesteps the node-gyp build.
|
|
:node_probe
|
|
where node >nul 2>&1
|
|
if not errorlevel 1 goto :node_found
|
|
if exist "%ProgramFiles%\nodejs\node.exe" set "PATH=%ProgramFiles%\nodejs;%PATH%"
|
|
if exist "%LOCALAPPDATA%\Programs\nodejs\node.exe" set "PATH=%LOCALAPPDATA%\Programs\nodejs;%PATH%"
|
|
where node >nul 2>&1
|
|
if not errorlevel 1 goto :node_found
|
|
if "%NODE_TRIED%"=="1" goto :node_missing
|
|
where winget >nul 2>&1
|
|
if errorlevel 1 goto :node_missing
|
|
echo.
|
|
echo [--] Node.js is not installed.
|
|
set "DOIT="
|
|
set /p "DOIT= Install Node 22 LTS now with winget? [Y/n] "
|
|
if /i "%DOIT%"=="n" goto :node_missing
|
|
set "NODE_TRIED=1"
|
|
echo Installing Node LTS ^(a UAC prompt may appear^)...
|
|
winget install --id OpenJS.NodeJS.LTS -e --source winget --accept-source-agreements --accept-package-agreements --silent
|
|
goto :node_probe
|
|
|
|
:node_missing
|
|
echo [X] Node.js not found on PATH, and not in any of:
|
|
echo %ProgramFiles%\nodejs
|
|
echo %LOCALAPPDATA%\Programs\nodejs
|
|
echo.
|
|
echo Install Node 22 LTS from https://nodejs.org/ then re-run.
|
|
echo If you JUST installed it, open a NEW Command Prompt first.
|
|
goto :fail
|
|
|
|
:node_found
|
|
if exist "%ProgramFiles%\nodejs\node.exe" set "PATH=%ProgramFiles%\nodejs;%PATH%"
|
|
if exist "%LOCALAPPDATA%\Programs\nodejs\node.exe" set "PATH=%LOCALAPPDATA%\Programs\nodejs;%PATH%"
|
|
where node >nul 2>&1
|
|
if not errorlevel 1 goto :node_found
|
|
echo [X] Node.js not found on PATH, and not in any of:
|
|
echo %ProgramFiles%\nodejs
|
|
echo %LOCALAPPDATA%\Programs\nodejs
|
|
echo.
|
|
echo Install Node 22 LTS from https://nodejs.org/ then re-run.
|
|
echo If you JUST installed it, open a NEW Command Prompt first.
|
|
goto :fail
|
|
:node_found
|
|
for /f "tokens=* usebackq" %%v in (`node -p "process.versions.node"`) do set "NODEVER=%%v"
|
|
for /f "tokens=1 delims=." %%m in ("%NODEVER%") do set "NODEMAJOR=%%m"
|
|
echo [ok] node v%NODEVER%
|
|
|
|
REM better-sqlite3 ships prebuilt binaries only for released Node ABIs. On a
|
|
REM newer major it falls back to node-gyp, which needs Visual Studio Build
|
|
REM Tools - a long, confusing failure if it is not installed.
|
|
if %NODEMAJOR% GEQ 23 goto :node_warn
|
|
goto :node_ok
|
|
|
|
:node_warn
|
|
echo.
|
|
echo [!] Node %NODEMAJOR% is newer than better-sqlite3's prebuilt binaries.
|
|
echo Install may try to compile from source and fail without Visual
|
|
echo Studio Build Tools. Node 22 LTS is the safe choice here.
|
|
echo.
|
|
set "GOON="
|
|
set /p "GOON= Continue anyway? [y/N] "
|
|
if /i not "%GOON%"=="y" goto :fail
|
|
:node_ok
|
|
|
|
REM ------------------------------------------------------------------- python
|
|
REM Only the clicker needs Python; the dashboard runs without it.
|
|
REM
|
|
REM Detection is deliberately "run it and see" rather than `where python`:
|
|
REM Windows ships a stub python.exe in WindowsApps that only opens the Microsoft
|
|
REM Store. `where` finds it, running it does nothing useful. Asking it to print
|
|
REM its major version separates a real interpreter from the stub. The py
|
|
REM launcher is preferred when present - it is not shadowed by the stub.
|
|
:py_probe
|
|
set "PYCMD="
|
|
for /f "tokens=*" %%v in ('py -3 -c "import sys;print(sys.version_info[0])" 2^>nul') do if "%%v"=="3" set "PYCMD=py -3"
|
|
if not defined PYCMD for /f "tokens=*" %%v in ('python -c "import sys;print(sys.version_info[0])" 2^>nul') do if "%%v"=="3" set "PYCMD=python"
|
|
if defined PYCMD goto :py_found
|
|
if "%PY_TRIED%"=="1" goto :py_skip
|
|
where winget >nul 2>&1
|
|
if errorlevel 1 goto :py_skip
|
|
echo.
|
|
echo [--] Python is not installed ^(needed only for the clicker^).
|
|
set "DOIT="
|
|
set /p "DOIT= Install Python 3.12 now with winget? [Y/n] "
|
|
if /i "%DOIT%"=="n" goto :py_skip
|
|
set "PY_TRIED=1"
|
|
echo Installing Python ^(a UAC prompt may appear^)...
|
|
winget install --id Python.Python.3.12 -e --source winget --accept-source-agreements --accept-package-agreements --silent
|
|
goto :py_probe
|
|
|
|
:py_skip
|
|
echo [--] python not found - the dashboard will still work.
|
|
echo Needed only for the clicker ^(clicker\runner.py^).
|
|
goto :py_end
|
|
|
|
:py_found
|
|
for /f "tokens=*" %%v in ('%PYCMD% -c "import sys;print(sys.version.split()[0])" 2^>nul') do set "PYVER=%%v"
|
|
echo [ok] python %PYVER% ^(via "%PYCMD%"^)
|
|
:py_end
|
|
|
|
REM ------------------------------------------------------------------- prompts
|
|
echo.
|
|
set "MASTER_URL="
|
|
set /p "MASTER_URL= Master dashboard URL [%DEFAULT_MASTER%]: "
|
|
if "%MASTER_URL%"=="" set "MASTER_URL=%DEFAULT_MASTER%"
|
|
|
|
set "INSTANCE="
|
|
set /p "INSTANCE= Instance name [%COMPUTERNAME%]: "
|
|
if "%INSTANCE%"=="" set "INSTANCE=%COMPUTERNAME%"
|
|
|
|
echo.
|
|
echo Installing to: %TARGET%
|
|
echo.
|
|
|
|
REM -------------------------------------------------------------- clone / pull
|
|
if exist "%TARGET%\.git" (
|
|
echo [1/5] Existing checkout found - pulling latest...
|
|
pushd "%TARGET%"
|
|
git pull --ff-only
|
|
if errorlevel 1 (
|
|
popd
|
|
echo [X] git pull failed. Resolve local changes and re-run.
|
|
goto :fail
|
|
)
|
|
popd
|
|
) else (
|
|
echo [1/5] Cloning %REPO_URL% ...
|
|
git clone "%REPO_URL%" "%TARGET%"
|
|
if errorlevel 1 (
|
|
echo [X] Clone failed. Check network access to git.juicerroom.com.
|
|
goto :fail
|
|
)
|
|
)
|
|
|
|
pushd "%TARGET%"
|
|
|
|
REM ------------------------------------------------------------------- install
|
|
echo.
|
|
echo [2/5] Installing npm dependencies ^(this takes a few minutes^)...
|
|
REM playwright is declared but unreferenced anywhere in the source; skipping its
|
|
REM browser download saves several hundred MB and a lot of time.
|
|
set "PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1"
|
|
call npm install
|
|
if errorlevel 1 (
|
|
echo.
|
|
echo [X] npm install failed.
|
|
echo If the error mentions node-gyp, MSBuild, or better_sqlite3.cpp,
|
|
echo the native module could not find a prebuilt binary. Either switch
|
|
echo to Node 22 LTS, or install "Desktop development with C++" from the
|
|
echo Visual Studio Build Tools installer.
|
|
popd
|
|
goto :fail
|
|
)
|
|
|
|
REM --------------------------------------------------------------------- build
|
|
echo.
|
|
echo [3/5] Building...
|
|
call npm run build
|
|
if errorlevel 1 (
|
|
echo [X] Build failed.
|
|
popd
|
|
goto :fail
|
|
)
|
|
|
|
REM ------------------------------------------------------------------ settings
|
|
echo.
|
|
echo [4/5] Writing instance settings...
|
|
node scripts\seed-settings.js "%MASTER_URL%" "%INSTANCE%"
|
|
if errorlevel 1 (
|
|
echo [X] Could not write settings to autotrader.sqlite.
|
|
popd
|
|
goto :fail
|
|
)
|
|
|
|
REM ------------------------------------------------------ python deps (option)
|
|
echo.
|
|
if not defined PYCMD goto :deps_skip
|
|
echo [5/5] Installing clicker Python dependencies...
|
|
REM requirements.txt guards its pyobjc entries with sys_platform == "darwin",
|
|
REM so on Windows this resolves to pyautogui and its wheels only.
|
|
%PYCMD% -m pip install --upgrade --quiet --disable-pip-version-check pip
|
|
%PYCMD% -m pip install --quiet --disable-pip-version-check -r clicker\requirements.txt
|
|
if errorlevel 1 goto :deps_failed
|
|
%PYCMD% -c "import pyautogui" 2>nul
|
|
if errorlevel 1 goto :deps_failed
|
|
echo pyautogui imports cleanly.
|
|
goto :deps_done
|
|
|
|
:deps_failed
|
|
echo [!] Python dependency install failed - the dashboard still works,
|
|
echo the clicker will not. Retry by hand with:
|
|
echo %PYCMD% -m pip install -r clicker\requirements.txt
|
|
goto :deps_done
|
|
|
|
:deps_skip
|
|
echo [5/5] Skipping Python dependencies ^(python not found^).
|
|
|
|
:deps_done
|
|
|
|
REM ---------------------------------------------------------------- start file
|
|
> "%~dp0start-autofirmer.bat" (
|
|
echo @echo off
|
|
echo title AutoFirmer - %INSTANCE%
|
|
echo cd /d "%TARGET%"
|
|
echo echo Dashboard starting on http://localhost:3000
|
|
echo call npm run start
|
|
echo pause
|
|
)
|
|
|
|
popd
|
|
|
|
echo.
|
|
echo ============================================
|
|
echo Done.
|
|
echo ============================================
|
|
echo.
|
|
echo Instance name : %INSTANCE%
|
|
echo Reporting to : %MASTER_URL%
|
|
echo Installed in : %TARGET%
|
|
echo.
|
|
echo Start it with : start-autofirmer.bat
|
|
echo Dashboard at : http://localhost:3000
|
|
echo.
|
|
echo Still manual:
|
|
echo - Load the Chrome extension: chrome://extensions, enable Developer
|
|
echo mode, "Load unpacked", select %TARGET%\extension
|
|
echo - Add your firm credentials on the dashboard's Settings page
|
|
echo - Run the clicker when needed: python clicker\runner.py
|
|
echo.
|
|
pause
|
|
exit /b 0
|
|
|
|
:fail
|
|
echo.
|
|
echo Setup did not complete.
|
|
echo.
|
|
pause
|
|
exit /b 1
|