Files
my-botty/install.bat
T

387 lines
14 KiB
Batchfile

@echo off
setlocal enabledelayedexpansion
:: Always run from the folder this script lives in
cd /d "%~dp0"
echo ============================================
echo Botty - Dependency Installer
echo ============================================
echo.
:: --- Detect Windows version ---
for /f "tokens=3" %%A in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v CurrentBuild 2^>nul') do set "WIN_BUILD=%%A"
if not defined WIN_BUILD (
echo WARNING: Could not detect Windows build number.
set "WIN_BUILD=0"
)
echo Detected Windows build: %WIN_BUILD%
set /a "WIN_BUILD_NUM=%WIN_BUILD%" 2>nul || set "WIN_BUILD_NUM=0"
if %WIN_BUILD_NUM% GEQ 22000 (
echo Detected Windows 11 -- using relative mouse mode ^(no ABSOLUTE flag^)
set "WIN11=1"
set "REQ_FILE=requirements-win11.txt"
set "ENV_FILE=environment-win11.yml"
) else (
echo Detected Windows 10 or earlier — using absolute mouse mode
set "WIN11=0"
set "REQ_FILE=requirements-win10.txt"
set "ENV_FILE=environment-win10.yml"
)
if not exist "%REQ_FILE%" set "REQ_FILE=requirements.txt"
if not exist "%ENV_FILE%" set "ENV_FILE=environment.yml"
echo Requirements profile: %REQ_FILE%
echo Environment profile: %ENV_FILE%
echo.
:: --- Find conda ---
:: Miniforge3 JustMe default: %LOCALAPPDATA%\miniforge3 (newer) or
:: %USERPROFILE%\miniforge3 (older)
set "CONDA_EXE="
for %%C in (
"%LOCALAPPDATA%\miniforge3\Scripts\conda.exe"
"%USERPROFILE%\miniforge3\Scripts\conda.exe"
"%LOCALAPPDATA%\miniconda3\Scripts\conda.exe"
"%USERPROFILE%\miniconda3\Scripts\conda.exe"
"%USERPROFILE%\anaconda3\Scripts\conda.exe"
"%ProgramData%\miniforge3\Scripts\conda.exe"
"%ProgramData%\miniconda3\Scripts\conda.exe"
"%ProgramData%\anaconda3\Scripts\conda.exe"
) do (
if exist %%C (
set "CONDA_EXE=%%~C"
goto :found_conda
)
)
echo conda not found — installing Miniforge3 automatically...
echo This is a one-time setup (~100 MB). Please wait.
echo.
:: --- Method 1: winget (cleanest; available on Win10 1709+ and all Win11) ---
winget --version >nul 2>&1
if %errorlevel% equ 0 (
echo Installing via winget...
winget install --id CondaForge.Miniforge3 --exact --silent ^
--accept-package-agreements --accept-source-agreements
if !errorlevel! equ 0 goto :rescan_conda
echo winget install failed — falling back to direct download.
echo.
)
:: --- Method 2: direct download + silent NSIS install ---
:: Uses curl (built into Win10/11) with PowerShell as fallback.
:: $ProgressPreference=SilentlyContinue is critical — without it PowerShell's
:: progress bar drops download speed from ~50 MB/s to ~1 MB/s.
:: start /wait "" is required: plain "installer /S" can return before install
:: finishes. /D= intentionally omitted — NSIS /D= breaks on paths with spaces.
set "MF_INSTALLER=%TEMP%\Miniforge3-installer.exe"
set "MF_URL=https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Windows-x86_64.exe"
echo Downloading Miniforge3...
curl -Lk --progress-bar "%MF_URL%" -o "%MF_INSTALLER%" 2>&1
if %errorlevel% neq 0 (
echo curl failed, trying PowerShell...
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$ProgressPreference='SilentlyContinue'; try { Invoke-WebRequest -Uri '%MF_URL%' -OutFile '%MF_INSTALLER%' -UseBasicParsing; exit 0 } catch { Write-Host $_.Exception.Message; exit 1 }"
)
if not exist "%MF_INSTALLER%" (
echo.
echo ERROR: Could not download Miniforge3. Check your internet connection, or
echo install it manually then re-run install.bat:
echo https://github.com/conda-forge/miniforge/releases/latest
echo.
pause
exit /b 1
)
echo Installing Miniforge3 (this takes ~1 minute)...
start /wait "" "%MF_INSTALLER%" /S /InstallationType=JustMe /AddToPath=0 /RegisterPython=0 /NoShortcuts=1 /NoRegistry=1
if %errorlevel% neq 0 (
echo.
echo ERROR: Miniforge3 installer failed (exit code %errorlevel%).
echo Try running it manually: %MF_INSTALLER%
echo.
pause
exit /b 1
)
del /q "%MF_INSTALLER%" >nul 2>&1
echo Miniforge3 installed.
:rescan_conda
echo.
:: Re-scan for conda now that Miniforge is installed
for %%C in (
"%LOCALAPPDATA%\miniforge3\Scripts\conda.exe"
"%USERPROFILE%\miniforge3\Scripts\conda.exe"
"%LOCALAPPDATA%\miniconda3\Scripts\conda.exe"
"%USERPROFILE%\miniconda3\Scripts\conda.exe"
"%USERPROFILE%\anaconda3\Scripts\conda.exe"
"%ProgramData%\miniforge3\Scripts\conda.exe"
"%ProgramData%\miniconda3\Scripts\conda.exe"
"%ProgramData%\anaconda3\Scripts\conda.exe"
) do (
if exist %%C (
set "CONDA_EXE=%%~C"
goto :found_conda
)
)
echo ERROR: Miniforge3 installed but conda.exe still not found. Please restart
echo the installer or contact support.
pause
exit /b 1
:found_conda
echo Found conda: %CONDA_EXE%
echo.
:: --- Test conda works ---
echo Testing conda...
"%CONDA_EXE%" --version >nul 2>&1
if %errorlevel% neq 0 (
echo.
echo ERROR: conda found but failed to run. Your conda installation may be broken.
echo Try re-installing Miniforge: https://github.com/conda-forge/miniforge
echo.
pause
exit /b 1
)
echo conda is working.
echo.
:: --- Find botty Python ---
set "PYTHON="
for %%C in (
"%LOCALAPPDATA%\miniforge3\envs\botty\python.exe"
"%LOCALAPPDATA%\miniconda3\envs\botty\python.exe"
"%USERPROFILE%\miniforge3\envs\botty\python.exe"
"%USERPROFILE%\miniconda3\envs\botty\python.exe"
"%USERPROFILE%\anaconda3\envs\botty\python.exe"
"%ProgramData%\miniforge3\envs\botty\python.exe"
"%ProgramData%\miniconda3\envs\botty\python.exe"
"%ProgramData%\anaconda3\envs\botty\python.exe"
) do (
if exist %%C (
set "PYTHON=%%~C"
goto :check_env
)
)
:: --- Create botty env ---
echo Creating 'botty' conda environment...
"%CONDA_EXE%" env create -f "%ENV_FILE%"
if %errorlevel% neq 0 (
echo.
echo ERROR: conda env create failed. See output above.
pause
exit /b 1
)
:check_env
:: Re-scan for Python after env creation
set "PYTHON="
for %%C in (
"%LOCALAPPDATA%\miniforge3\envs\botty\python.exe"
"%LOCALAPPDATA%\miniconda3\envs\botty\python.exe"
"%USERPROFILE%\miniforge3\envs\botty\python.exe"
"%USERPROFILE%\miniconda3\envs\botty\python.exe"
"%USERPROFILE%\anaconda3\envs\botty\python.exe"
"%ProgramData%\miniforge3\envs\botty\python.exe"
"%ProgramData%\miniconda3\envs\botty\python.exe"
"%ProgramData%\anaconda3\envs\botty\python.exe"
) do (
if exist %%C (
set "PYTHON=%%~C"
goto :env_ready
)
)
echo.
echo ERROR: botty env was created but python.exe was not found.
pause
exit /b 1
:env_ready
echo Botty Python: %PYTHON%
:: --- Install pip requirements ---
:: --progress-bar off: pip's progress bar uses \r to redraw in place; when this
:: script's output is redirected to a file (e.g. run_install_capture.bat) those
:: redraws become millions of lines and the log balloons to many GB. Turning the
:: bar off keeps the install log small without hiding warnings/errors.
echo.
echo Installing Botty requirements from %REQ_FILE%...
"%CONDA_EXE%" run -n botty python -m pip install --progress-bar off -r "%REQ_FILE%"
if %errorlevel% neq 0 (
echo.
echo ERROR: pip requirements install failed for %REQ_FILE%.
pause
exit /b 1
)
echo.
echo Botty osdetect:
"%CONDA_EXE%" run -n botty python -c "import sys; sys.path.insert(0, 'src'); from utils.os_detect import describe_current_os; print(describe_current_os())"
:: --- OCR setup ---
:: Two OCR backends, tried in order at runtime:
:: 1. tesserocr — C extension calling tesseract DLLs directly (fast)
:: 2. pytesseract — subprocess calling tesseract.exe (always works if exe exists)
:: At least one must work. Install.bat sets up both and reports which is ready.
echo.
echo Setting up OCR...
:: Find the botty env directory
set "BOTTY_ENV_DIR="
for %%C in (
"%LOCALAPPDATA%\miniforge3\envs\botty"
"%LOCALAPPDATA%\miniconda3\envs\botty"
"%USERPROFILE%\miniforge3\envs\botty"
"%USERPROFILE%\miniconda3\envs\botty"
"%USERPROFILE%\anaconda3\envs\botty"
"%ProgramData%\miniforge3\envs\botty"
"%ProgramData%\miniconda3\envs\botty"
"%ProgramData%\anaconda3\envs\botty"
) do (
if exist %%C (
set "BOTTY_ENV_DIR=%%~C"
goto :env_found
)
)
echo ERROR: Could not find botty env directory.
pause
exit /b 1
:env_found
set "TESS_PATH=%BOTTY_ENV_DIR%\Library\bin;%BOTTY_ENV_DIR%\Library\lib;%BOTTY_ENV_DIR%\DLLs;%BOTTY_ENV_DIR%\Scripts"
:: --- Backend 1: tesserocr (fast path, best-effort) ---
:: tesserocr uses the C++ API of tesseract and needs an MSVC-compiled tesseract DLL.
:: The bundled dependencies folder provides:
:: tesseract52.dll — MSVC tesseract 5.2.0 (conda-forge, compiled vs2019)
:: tesserocr.cp310-...pyd — MSVC tesserocr 2.5.2 linked against tesseract52.dll
:: (both require leptonica-1.78.0.dll from the conda tesseract=4.x install below)
:: If any step fails the bot still works via pytesseract below.
:: Remove any existing pip/wheel tesserocr
"%PYTHON%" -m pip uninstall tesserocr -y >nul 2>&1
:: conda tesseract 4.x provides leptonica-1.78.0.dll (MSVC) which tesseract52.dll needs
"%CONDA_EXE%" install -n botty "tesseract=4.*" -c conda-forge -y >nul 2>&1
:: conda tesseract.exe crashes on Win10 and Win11 — disable it, keep the DLLs
if exist "%BOTTY_ENV_DIR%\Library\bin\tesseract.exe" (
rename "%BOTTY_ENV_DIR%\Library\bin\tesseract.exe" "tesseract_disabled.exe" >nul 2>&1
)
:: Deploy the MSVC tesseract52.dll (tesserocr.pyd imports exactly this name)
if exist "dependencies\tesseract52.dll" (
copy /y "dependencies\tesseract52.dll" "%BOTTY_ENV_DIR%\Library\bin\tesseract52.dll" >nul
)
:: Deploy the conda-forge tesserocr .pyd (compiled against tesseract52.dll)
if exist "dependencies\tesserocr.cp310-win_amd64.pyd" (
copy /y "dependencies\tesserocr.cp310-win_amd64.pyd" "%BOTTY_ENV_DIR%\lib\site-packages\tesserocr.cp310-win_amd64.pyd" >nul
) else if exist "dependencies\tesserocr-2.5.2-cp310-cp310-win_amd64.whl" (
"%CONDA_EXE%" run -n botty python -m pip install --quiet --force-reinstall --no-deps "dependencies\tesserocr-2.5.2-cp310-cp310-win_amd64.whl" >nul 2>&1
)
:: --- Backend 2: pytesseract (reliable fallback) ---
:: Needs tesseract.exe from winget. Works on any Python version.
:: On Win10: winget may not be available -- if install fails, offer manual link.
"%CONDA_EXE%" run -n botty python -m pip install --progress-bar off pytesseract >nul 2>&1
if %errorlevel% neq 0 (
echo WARNING: Could not install pytesseract Python wrapper.
)
if not exist "C:\Program Files\Tesseract-OCR\tesseract.exe" (
echo Installing Tesseract OCR via winget...
winget install --id tesseract-ocr.tesseract --silent --accept-package-agreements --accept-source-agreements 2>nul
if !errorlevel! neq 0 (
echo winget failed -- on Windows 10 you may need to install manually:
echo https://github.com/tesseract-ocr/tesseract/releases
echo Download the win64 installer, run it, keep the default install path.
)
)
:: --- Verify OCR: at least one backend must work ---
echo.
echo Checking OCR backends...
set "PATH=%TESS_PATH%;%PATH%"
set "OCR_READY=0"
"%CONDA_EXE%" run -n botty python -c "import os; os.add_dll_directory(r'%BOTTY_ENV_DIR%\Library\bin'); from tesserocr import PyTessBaseAPI, OEM; PyTessBaseAPI(psm=7,oem=OEM.LSTM_ONLY,path='assets/tessdata',lang='hover-eng_inconsolata_inv_th_fast').End()" >nul 2>&1
if %errorlevel% == 0 (
echo tesserocr: OK ^(fast path^)
set "OCR_READY=1"
) else (
echo tesserocr: not available ^(DLL issue -- bot will use pytesseract instead^)
)
if exist "C:\Program Files\Tesseract-OCR\tesseract.exe" (
"%CONDA_EXE%" run -n botty python -c "import pytesseract; pytesseract.pytesseract.tesseract_cmd=r'C:\Program Files\Tesseract-OCR\tesseract.exe'; pytesseract.get_tesseract_version()" >nul 2>&1
if !errorlevel! == 0 (
echo pytesseract: OK ^(reliable fallback^)
set "OCR_READY=1"
) else (
echo pytesseract: tesseract.exe found but call failed
)
) else (
echo pytesseract: tesseract.exe not found -- install from link above if needed
)
if "%OCR_READY%"=="0" (
echo.
echo WARNING: No OCR backend is working. Item hover text will not be read.
echo Install Tesseract OCR: https://github.com/tesseract-ocr/tesseract/releases
echo Then re-run install.bat.
)
:: --- Verify all dependencies ---
echo.
echo Verifying all dependencies...
set "ALL_OK=1"
for %%M in (cv2 mss numpy transitions rapidfuzz pydantic pytesseract yaml) do (
set "PATH=%TESS_PATH%;%PATH%"
"%CONDA_EXE%" run -n botty python -c "import %%M" >nul 2>&1
if !errorlevel! neq 0 (
echo FAILED: %%M
set "ALL_OK=0"
) else (
echo %%M: OK
)
)
:: discord.py imports aiohttp which calls ssl.create_default_context() at import
:: time. A malformed cert in the Windows store triggers ASN1 NOT_ENOUGH_DATA.
:: The bot patches this at runtime via _patch_ssl(); check import with the patch.
set "PATH=%TESS_PATH%;%PATH%"
"%CONDA_EXE%" run -n botty python -c "import ssl; ssl.SSLContext.load_default_certs = lambda *a, **kw: None; import discord" >nul 2>&1
if !errorlevel! neq 0 (
echo FAILED: discord
set "ALL_OK=0"
) else (
echo discord: OK
)
if "%OCR_READY%"=="0" set "ALL_OK=0"
if "%ALL_OK%"=="1" (
echo.
echo All dependencies verified.
) else (
echo.
echo WARNING: Some dependencies failed above.
echo This is often a PATH issue. Try running from a fresh CMD/PowerShell:
echo conda activate botty
echo python -c "import cv2"
echo.
)
:install_done
echo.
echo ============================================
echo Installation complete!
echo Run botty with: run_botty.bat
echo ============================================
echo.