tesserocr never loaded -- install.bat always reported "tesserocr: not
available (DLL issue)" and the bot ran on the pytesseract fallback, which
shells out to tesseract.exe per OCR call instead of using the in-process
C++ API.
Root cause, found by walking the import table with pefile:
tesserocr.pyd -> tesseract52.dll -> leptonica-1.78.0.dll -> tiff.dll
-> libdeflate.dll <- MISSING
Current conda-forge libdeflate (>=1.20) installs the library as
"deflate.dll", but the older tiff.dll from the tesseract=4.x stack still
imports the previous name "libdeflate.dll". Nothing provided that name, so
tiff.dll failed to load and every DLL above it failed with WinError 126
("The specified module could not be found") -- which is why the error
looked like a missing module even though every file was present.
Fix: install libdeflate explicitly alongside tesseract=4.*, then copy
deflate.dll to the legacy name libdeflate.dll when that name is absent.
Same library, same exports.
Verified: removing the alias reproduces the failure exactly; running
install.bat recreates it and the installer now reports "tesserocr: OK
(fast path)". tesserocr initialises and performs real OCR with both bundled
models, and the bot logs "OCR backend: tesserocr (primary)" at startup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
521 lines
20 KiB
Batchfile
521 lines
20 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) ---
|
|
:: --scope user is critical: without it winget defaults to a machine-wide
|
|
:: install (lands in %ProgramData%) which REQUIRES admin. A normal double-click
|
|
:: (no elevation) then fails silently and conda never installs. --scope user
|
|
:: installs to %USERPROFILE%\miniforge3 with no admin needed — which is also one
|
|
:: of the locations :rescan_conda searches.
|
|
:: winget returns non-zero when the package is already installed, so don't
|
|
:: trust the exit code -- rescan for conda and only fall through to the direct
|
|
:: download if it's genuinely still missing. Keep this comment outside the block:
|
|
:: a "::" line inside a ( ) block is a parse error.
|
|
winget --version >nul 2>&1
|
|
if %errorlevel% equ 0 (
|
|
echo Installing via winget...
|
|
winget install --id CondaForge.Miniforge3 --exact --silent --scope user ^
|
|
--accept-package-agreements --accept-source-agreements
|
|
for %%C in (
|
|
"%LOCALAPPDATA%\miniforge3\Scripts\conda.exe"
|
|
"%USERPROFILE%\miniforge3\Scripts\conda.exe"
|
|
"%ProgramData%\miniforge3\Scripts\conda.exe"
|
|
) do if exist %%C goto :rescan_conda
|
|
echo winget did not produce a usable conda — 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"
|
|
|
|
del /q "%MF_INSTALLER%" >nul 2>&1
|
|
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
|
|
)
|
|
|
|
:: Verify the download is a real installer, not a truncated file or an HTML
|
|
:: error page served with a 200. The Miniforge installer is ~78 MB; anything
|
|
:: under 40 MB means the download failed even though a file exists.
|
|
for %%A in ("%MF_INSTALLER%") do set "MF_SIZE=%%~zA"
|
|
if not defined MF_SIZE set "MF_SIZE=0"
|
|
if %MF_SIZE% LSS 41943040 (
|
|
echo.
|
|
echo ERROR: Downloaded Miniforge3 installer is only %MF_SIZE% bytes — the
|
|
echo download was incomplete or blocked. Check your internet/proxy, or install
|
|
echo manually then re-run install.bat:
|
|
echo https://github.com/conda-forge/miniforge/releases/latest
|
|
echo.
|
|
del /q "%MF_INSTALLER%" >nul 2>&1
|
|
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.
|
|
:: libdeflate is required explicitly: the libtiff that ships with tesseract 4.x
|
|
:: imports libdeflate, and without it the whole chain below fails to load.
|
|
"%CONDA_EXE%" install -n botty "tesseract=4.*" libdeflate -c conda-forge -y >nul 2>&1
|
|
|
|
:: libdeflate.dll compatibility alias.
|
|
:: THIS IS WHAT MAKES tesserocr WORK. The DLL chain is:
|
|
:: tesserocr.pyd -> tesseract52.dll -> leptonica-1.78.0.dll -> tiff.dll -> libdeflate.dll
|
|
:: Current conda-forge libdeflate (>=1.20) installs the library as "deflate.dll",
|
|
:: but the older tiff.dll from the tesseract=4.x stack still imports the previous
|
|
:: name "libdeflate.dll". Nothing provides that name, so tiff.dll fails to load,
|
|
:: and every DLL above it in the chain fails with WinError 126 ("The specified
|
|
:: module could not be found") -- which surfaced as tesserocr being permanently
|
|
:: unavailable and the bot silently falling back to the slower pytesseract.
|
|
:: Copying deflate.dll to the old name satisfies the import; the exported symbols
|
|
:: are the same library, verified by tesserocr initialising and running real OCR.
|
|
if not exist "%BOTTY_ENV_DIR%\Library\bin\libdeflate.dll" (
|
|
if exist "%BOTTY_ENV_DIR%\Library\bin\deflate.dll" (
|
|
copy /y "%BOTTY_ENV_DIR%\Library\bin\deflate.dll" "%BOTTY_ENV_DIR%\Library\bin\libdeflate.dll" >nul
|
|
)
|
|
)
|
|
|
|
:: 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) ---
|
|
:: This is the backend that actually carries OCR on most machines (tesserocr's
|
|
:: MSVC DLL chain frequently fails), so it must install without admin rights and
|
|
:: without winget -- neither is guaranteed on a clean Win10 box.
|
|
"%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.
|
|
)
|
|
|
|
:: Try winget machine scope, then user scope -- the latter needs no admin.
|
|
:: winget's exit code is unreliable, being non-zero when the package is already
|
|
:: installed, so after each attempt we re-resolve tesseract.exe instead of
|
|
:: trusting errorlevel.
|
|
:: NOTE: comments must stay OUTSIDE the parenthesised blocks below. A "::" line
|
|
:: inside a ( ) block is a parse error, and any parenthesis in the comment text
|
|
:: closes the block early.
|
|
call :find_tesseract
|
|
if not defined TESS_EXE (
|
|
echo Installing Tesseract OCR...
|
|
winget --version >nul 2>&1
|
|
if !errorlevel! equ 0 (
|
|
winget install --id tesseract-ocr.tesseract --exact --silent ^
|
|
--accept-package-agreements --accept-source-agreements >nul 2>&1
|
|
call :find_tesseract
|
|
if not defined TESS_EXE (
|
|
winget install --id tesseract-ocr.tesseract --exact --silent --scope user ^
|
|
--accept-package-agreements --accept-source-agreements >nul 2>&1
|
|
call :find_tesseract
|
|
)
|
|
)
|
|
)
|
|
|
|
:: Last resort: direct download of the official NSIS installer. Covers clean
|
|
:: Win10 machines where winget is missing or fails.
|
|
:: The size check guards against a truncated download or an HTML error page;
|
|
:: the installer is ~50 MB.
|
|
:: NOTE on /D=: measured behaviour is that the official Tesseract installer
|
|
:: self-elevates (it requests admin) and the elevated relaunch DISCARDS /D=, so
|
|
:: it always lands machine-wide in "C:\Program Files\Tesseract-OCR" regardless
|
|
:: of TS_DEST. /D= is kept as best-effort only. The practical consequence is
|
|
:: that Tesseract needs admin/UAC -- there is no per-user install path with the
|
|
:: official installer. Either outcome is fine at runtime because find_tesseract
|
|
:: and src\d2r_image\ocr.py both search the machine-wide and per-user paths.
|
|
:: /D= must still come last and unquoted, and breaks on paths with spaces, so
|
|
:: it is only passed when the target path has none.
|
|
if not defined TESS_EXE (
|
|
echo winget unavailable or failed -- downloading Tesseract directly...
|
|
set "TS_INSTALLER=%TEMP%\tesseract-setup.exe"
|
|
set "TS_URL=https://github.com/tesseract-ocr/tesseract/releases/download/5.5.0/tesseract-ocr-w64-setup-5.5.0.20241111.exe"
|
|
set "TS_DEST=%LOCALAPPDATA%\Programs\Tesseract-OCR"
|
|
del /q "!TS_INSTALLER!" >nul 2>&1
|
|
curl -Lk --progress-bar "!TS_URL!" -o "!TS_INSTALLER!" 2>&1
|
|
if not exist "!TS_INSTALLER!" (
|
|
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
|
"$ProgressPreference='SilentlyContinue'; try { Invoke-WebRequest -Uri '!TS_URL!' -OutFile '!TS_INSTALLER!' -UseBasicParsing; exit 0 } catch { exit 1 }"
|
|
)
|
|
set "TS_SIZE=0"
|
|
if exist "!TS_INSTALLER!" for %%A in ("!TS_INSTALLER!") do set "TS_SIZE=%%~zA"
|
|
if !TS_SIZE! GEQ 20971520 (
|
|
echo !TS_DEST! | find " " >nul
|
|
if !errorlevel! equ 0 (
|
|
start /wait "" "!TS_INSTALLER!" /S
|
|
) else (
|
|
start /wait "" "!TS_INSTALLER!" /S /D=!TS_DEST!
|
|
)
|
|
del /q "!TS_INSTALLER!" >nul 2>&1
|
|
call :find_tesseract
|
|
)
|
|
)
|
|
|
|
if defined TESS_EXE (
|
|
echo Tesseract: !TESS_EXE!
|
|
) else (
|
|
echo WARNING: Tesseract could not be installed automatically. Install manually:
|
|
echo https://github.com/tesseract-ocr/tesseract/releases
|
|
echo Download the win64 installer, run it, then re-run install.bat.
|
|
)
|
|
|
|
:: --- 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 defined TESS_EXE (
|
|
"%CONDA_EXE%" run -n botty python -c "import pytesseract; pytesseract.pytesseract.tesseract_cmd=r'!TESS_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.
|
|
goto :eof
|
|
|
|
:: --- Resolve tesseract.exe into TESS_EXE ---
|
|
:: Checks machine-wide (winget default / manual install) and per-user (winget
|
|
:: --scope user / our direct NSIS fallback) locations, plus PATH. Sets TESS_EXE
|
|
:: to the first hit, or clears it if none found.
|
|
:find_tesseract
|
|
set "TESS_EXE="
|
|
for %%T in (
|
|
"C:\Program Files\Tesseract-OCR\tesseract.exe"
|
|
"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe"
|
|
"%LOCALAPPDATA%\Programs\Tesseract-OCR\tesseract.exe"
|
|
"%ProgramData%\Tesseract-OCR\tesseract.exe"
|
|
) do (
|
|
if exist %%T (
|
|
set "TESS_EXE=%%~T"
|
|
goto :eof
|
|
)
|
|
)
|
|
for /f "delims=" %%T in ('where tesseract 2^>nul') do (
|
|
set "TESS_EXE=%%T"
|
|
goto :eof
|
|
)
|
|
goto :eof
|