Compare commits
3 Commits
59f1c1c38e
...
d2239a670c
| Author | SHA1 | Date | |
|---|---|---|---|
| d2239a670c | |||
| 53430f768f | |||
| a8205447e3 |
File diff suppressed because it is too large
Load Diff
@@ -46,13 +46,13 @@
|
|||||||
"last_updated": "2026-03-22T18:11:22Z"
|
"last_updated": "2026-03-22T18:11:22Z"
|
||||||
},
|
},
|
||||||
"88555ca4-9c88-4bcf-825f-dd19b19b7145": {
|
"88555ca4-9c88-4bcf-825f-dd19b19b7145": {
|
||||||
"user_message_count": 35,
|
"user_message_count": 50,
|
||||||
"agent_message_count": 341,
|
"agent_message_count": 592,
|
||||||
"start_timestamp": "2026-03-21T13:01:32-06:00",
|
"start_timestamp": "2026-03-21T13:01:32-06:00",
|
||||||
"end_timestamp": "2026-03-21T13:01:32-06:00",
|
"end_timestamp": "2026-03-21T13:01:32-06:00",
|
||||||
"markdown_size_bytes": 310211,
|
"markdown_size_bytes": 461149,
|
||||||
"provider": "cursoride",
|
"provider": "cursoride",
|
||||||
"last_updated": "2026-03-22T18:11:22Z"
|
"last_updated": "2026-03-22T19:25:16Z"
|
||||||
},
|
},
|
||||||
"8a226504-a2e0-4b10-b083-a609486034c7": {
|
"8a226504-a2e0-4b10-b083-a609486034c7": {
|
||||||
"user_message_count": 9,
|
"user_message_count": 9,
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"end_timestamp": "2025-06-25T22:09:21-06:00",
|
"end_timestamp": "2025-06-25T22:09:21-06:00",
|
||||||
"markdown_size_bytes": 38319,
|
"markdown_size_bytes": 38319,
|
||||||
"provider": "cursoride",
|
"provider": "cursoride",
|
||||||
"last_updated": "2026-03-22T18:11:10Z"
|
"last_updated": "2026-03-22T18:13:12Z"
|
||||||
},
|
},
|
||||||
"b90a47f3-3c59-4ca3-a099-690412afaab1": {
|
"b90a47f3-3c59-4ca3-a099-690412afaab1": {
|
||||||
"user_message_count": 7,
|
"user_message_count": 7,
|
||||||
|
|||||||
+90
-54
@@ -1,31 +1,44 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal
|
setlocal EnableExtensions
|
||||||
|
REM ANSI colors (needs Windows 10+ console VT or Windows Terminal)
|
||||||
|
for /f %%a in ('powershell -nop -c "[char]0x1b"') do set "ESC=%%a"
|
||||||
|
set "RST=%ESC%[0m"
|
||||||
|
set "BLD=%ESC%[1m"
|
||||||
|
set "DIM=%ESC%[2m"
|
||||||
|
set "RED=%ESC%[91m"
|
||||||
|
set "GRN=%ESC%[92m"
|
||||||
|
set "YLW=%ESC%[93m"
|
||||||
|
set "BLU=%ESC%[94m"
|
||||||
|
set "MAG=%ESC%[95m"
|
||||||
|
set "CYN=%ESC%[96m"
|
||||||
|
set "GRY=%ESC%[90m"
|
||||||
|
set "WHT=%ESC%[97m"
|
||||||
|
|
||||||
REM Always use 'nathan' as NAS username
|
REM Always use 'nathan' as NAS username
|
||||||
set NASUSER=nathan
|
set NASUSER=nathan
|
||||||
|
|
||||||
REM Menu for operation selection
|
REM Menu for operation selection
|
||||||
echo.
|
echo.
|
||||||
echo Select operation:
|
echo %BLD%%YLW%Select operation:%RST%
|
||||||
echo 1. Generate thumbnails only
|
echo %CYN%1.%RST% Generate thumbnails only
|
||||||
echo 2. SSH cleanup only
|
echo %CYN%2.%RST% SSH cleanup only
|
||||||
echo 3. Both (generate thumbnails + SSH cleanup)
|
echo %CYN%3.%RST% Both (generate thumbnails + SSH cleanup)
|
||||||
echo 4. Fix OneDrive thumbnail override (NEW!)
|
echo %CYN%4.%RST% Fix OneDrive thumbnail override %DIM%(NEW^)%RST%
|
||||||
echo.
|
echo.
|
||||||
set /p CHOICE=Enter your choice (1-4):
|
set /p CHOICE=%CYN%Enter your choice ^(1-4^): %RST%
|
||||||
|
|
||||||
if "%CHOICE%"=="1" goto THUMBS_ONLY
|
if "%CHOICE%"=="1" goto THUMBS_ONLY
|
||||||
if "%CHOICE%"=="2" goto SSH_ONLY
|
if "%CHOICE%"=="2" goto SSH_ONLY
|
||||||
if "%CHOICE%"=="3" goto BOTH
|
if "%CHOICE%"=="3" goto BOTH
|
||||||
if "%CHOICE%"=="4" goto FIX_ONEDRIVE
|
if "%CHOICE%"=="4" goto FIX_ONEDRIVE
|
||||||
echo Invalid choice. Exiting.
|
echo %RED%Invalid choice. Exiting.%RST%
|
||||||
exit /b
|
exit /b
|
||||||
|
|
||||||
:THUMBS_ONLY
|
:THUMBS_ONLY
|
||||||
REM Prompt for Windows path
|
REM Prompt for Windows path
|
||||||
set /p WINPATH=Enter the full Windows path to your NAS directory (e.g., R:\YouTube\Streams\MixerTwitch):
|
set /p WINPATH=%CYN%Enter the full Windows path to your NAS directory ^(e.g., R:\YouTube\Streams\MixerTwitch^): %RST%
|
||||||
if "%WINPATH%"=="" (
|
if "%WINPATH%"=="" (
|
||||||
echo No path provided. Exiting.
|
echo %RED%No path provided. Exiting.%RST%
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,9 +47,9 @@ set "RELPATH=%WINPATH:~3%"
|
|||||||
set "RELPATH=%RELPATH:\=/%"
|
set "RELPATH=%RELPATH:\=/%"
|
||||||
set "NASPATH=/volume1/Hydra/%RELPATH%"
|
set "NASPATH=/volume1/Hydra/%RELPATH%"
|
||||||
|
|
||||||
echo Uploading extract_eadir_to_tmp.sh to NAS and seeding...
|
echo %GRN%Uploading extract_eadir_to_tmp.sh to NAS and seeding...%RST%
|
||||||
if not exist "%~dp0extract_eadir_to_tmp.sh" (
|
if not exist "%~dp0extract_eadir_to_tmp.sh" (
|
||||||
echo ERROR: extract_eadir_to_tmp.sh not found next to this batch file.
|
echo %RED%ERROR: extract_eadir_to_tmp.sh not found next to this batch file.%RST%
|
||||||
goto END
|
goto END
|
||||||
)
|
)
|
||||||
ssh Hydra "cat > ~/extract_eadir_to_tmp.sh" < "%~dp0extract_eadir_to_tmp.sh"
|
ssh Hydra "cat > ~/extract_eadir_to_tmp.sh" < "%~dp0extract_eadir_to_tmp.sh"
|
||||||
@@ -48,9 +61,9 @@ goto END
|
|||||||
|
|
||||||
:SSH_ONLY
|
:SSH_ONLY
|
||||||
REM Prompt for Windows path
|
REM Prompt for Windows path
|
||||||
set /p WINPATH=Enter the full Windows path to your NAS directory (e.g., R:\YouTube\Streams\MixerTwitch):
|
set /p WINPATH=%CYN%Enter the full Windows path to your NAS directory ^(e.g., R:\YouTube\Streams\MixerTwitch^): %RST%
|
||||||
if "%WINPATH%"=="" (
|
if "%WINPATH%"=="" (
|
||||||
echo No path provided. Exiting.
|
echo %RED%No path provided. Exiting.%RST%
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -59,27 +72,33 @@ set "RELPATH=%WINPATH:~3%"
|
|||||||
set "RELPATH=%RELPATH:\=/%"
|
set "RELPATH=%RELPATH:\=/%"
|
||||||
set "NASPATH=/volume1/Hydra/%RELPATH%"
|
set "NASPATH=/volume1/Hydra/%RELPATH%"
|
||||||
|
|
||||||
echo DEBUG: WINPATH = %WINPATH%
|
echo %GRY%DEBUG: WINPATH = %WINPATH%%RST%
|
||||||
echo DEBUG: RELPATH = %RELPATH%
|
echo %GRY%DEBUG: RELPATH = %RELPATH%%RST%
|
||||||
echo DEBUG: NASPATH = %NASPATH%
|
echo %GRY%DEBUG: NASPATH = %NASPATH%%RST%
|
||||||
echo.
|
echo.
|
||||||
call :WIN_REMOVE_LOCAL_EADIR
|
call :WIN_REMOVE_LOCAL_EADIR
|
||||||
REM Ensure nascleanup.sh exists on NAS (upload + fix line endings), then run it
|
REM Ensure nascleanup.sh exists on NAS (upload + fix line endings), then run it
|
||||||
echo Uploading nascleanup.sh to NAS and running cleanup...
|
echo %GRN%Uploading nascleanup.sh to NAS and running cleanup...%RST%
|
||||||
if not exist "%~dp0nascleanup.sh" (
|
if not exist "%~dp0nascleanup.sh" (
|
||||||
echo ERROR: nascleanup.sh not found next to this batch file.
|
echo %RED%ERROR: nascleanup.sh not found next to this batch file.%RST%
|
||||||
goto END
|
goto END
|
||||||
)
|
)
|
||||||
ssh Hydra "cat > ~/nascleanup.sh" < "%~dp0nascleanup.sh"
|
ssh Hydra "cat > ~/nascleanup.sh" < "%~dp0nascleanup.sh"
|
||||||
ssh Hydra "bash -lc 'if command -v dos2unix >/dev/null 2>&1; then dos2unix -f ~/nascleanup.sh; else tr -d \"\r\" < ~/nascleanup.sh > ~/nascleanup.sh.tmp && mv ~/nascleanup.sh.tmp ~/nascleanup.sh; fi; chmod +x ~/nascleanup.sh; ~/nascleanup.sh \"%NASPATH%\"'"
|
ssh Hydra "bash -lc 'if command -v dos2unix >/dev/null 2>&1; then dos2unix -f ~/nascleanup.sh; else tr -d \"\r\" < ~/nascleanup.sh > ~/nascleanup.sh.tmp && mv ~/nascleanup.sh.tmp ~/nascleanup.sh; fi; chmod +x ~/nascleanup.sh; ~/nascleanup.sh \"%NASPATH%\"'"
|
||||||
call :WIN_REMOVE_LOCAL_EADIR_TMP
|
if errorlevel 1 (
|
||||||
|
echo %RED%ERROR: nascleanup failed on NAS - check promote ^(eaDir_tmp -^> @eaDir^) messages above.%RST%
|
||||||
|
echo %YLW%Keeping eaDir_tmp on the share so you can retry without re-running FFmpeg.%RST%
|
||||||
|
call :PRINT_HYDRA_CLEAR_EADIR
|
||||||
|
) else (
|
||||||
|
call :WIN_REMOVE_LOCAL_EADIR_TMP
|
||||||
|
)
|
||||||
goto END
|
goto END
|
||||||
|
|
||||||
:BOTH
|
:BOTH
|
||||||
REM Prompt for Windows path
|
REM Prompt for Windows path
|
||||||
set /p WINPATH=Enter the full Windows path to your NAS directory (e.g., R:\YouTube\Streams\MixerTwitch):
|
set /p WINPATH=%CYN%Enter the full Windows path to your NAS directory ^(e.g., R:\YouTube\Streams\MixerTwitch^): %RST%
|
||||||
if "%WINPATH%"=="" (
|
if "%WINPATH%"=="" (
|
||||||
echo No path provided. Exiting.
|
echo %RED%No path provided. Exiting.%RST%
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -88,15 +107,15 @@ set "RELPATH=%WINPATH:~3%"
|
|||||||
set "RELPATH=%RELPATH:\=/%"
|
set "RELPATH=%RELPATH:\=/%"
|
||||||
set "NASPATH=/volume1/Hydra/%RELPATH%"
|
set "NASPATH=/volume1/Hydra/%RELPATH%"
|
||||||
|
|
||||||
echo DEBUG: WINPATH = %WINPATH%
|
echo %GRY%DEBUG: WINPATH = %WINPATH%%RST%
|
||||||
echo DEBUG: RELPATH = %RELPATH%
|
echo %GRY%DEBUG: RELPATH = %RELPATH%%RST%
|
||||||
echo DEBUG: NASPATH = %NASPATH%
|
echo %GRY%DEBUG: NASPATH = %NASPATH%%RST%
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
REM Pre-seed eaDir_tmp from @eaDir on NAS before generation
|
REM Pre-seed eaDir_tmp from @eaDir on NAS before generation
|
||||||
echo Uploading extract_eadir_to_tmp.sh to NAS and seeding...
|
echo %GRN%Uploading extract_eadir_to_tmp.sh to NAS and seeding...%RST%
|
||||||
if not exist "%~dp0extract_eadir_to_tmp.sh" (
|
if not exist "%~dp0extract_eadir_to_tmp.sh" (
|
||||||
echo ERROR: extract_eadir_to_tmp.sh not found next to this batch file.
|
echo %RED%ERROR: extract_eadir_to_tmp.sh not found next to this batch file.%RST%
|
||||||
goto END
|
goto END
|
||||||
)
|
)
|
||||||
ssh Hydra "cat > ~/extract_eadir_to_tmp.sh" < "%~dp0extract_eadir_to_tmp.sh"
|
ssh Hydra "cat > ~/extract_eadir_to_tmp.sh" < "%~dp0extract_eadir_to_tmp.sh"
|
||||||
@@ -110,41 +129,47 @@ call :WIN_REMOVE_LOCAL_EADIR
|
|||||||
|
|
||||||
REM SSH cleanup commands (run separately)
|
REM SSH cleanup commands (run separately)
|
||||||
REM Ensure nascleanup.sh exists on NAS (upload + fix line endings), then run it
|
REM Ensure nascleanup.sh exists on NAS (upload + fix line endings), then run it
|
||||||
echo Uploading nascleanup.sh to NAS and running cleanup...
|
echo %GRN%Uploading nascleanup.sh to NAS and running cleanup...%RST%
|
||||||
if not exist "%~dp0nascleanup.sh" (
|
if not exist "%~dp0nascleanup.sh" (
|
||||||
echo ERROR: nascleanup.sh not found next to this batch file.
|
echo %RED%ERROR: nascleanup.sh not found next to this batch file.%RST%
|
||||||
goto END
|
goto END
|
||||||
)
|
)
|
||||||
ssh Hydra "cat > ~/nascleanup.sh" < "%~dp0nascleanup.sh"
|
ssh Hydra "cat > ~/nascleanup.sh" < "%~dp0nascleanup.sh"
|
||||||
ssh Hydra "bash -lc 'if command -v dos2unix >/dev/null 2>&1; then dos2unix -f ~/nascleanup.sh; else tr -d \"\r\" < ~/nascleanup.sh > ~/nascleanup.sh.tmp && mv ~/nascleanup.sh.tmp ~/nascleanup.sh; fi; chmod +x ~/nascleanup.sh; ~/nascleanup.sh \"%NASPATH%\"'"
|
ssh Hydra "bash -lc 'if command -v dos2unix >/dev/null 2>&1; then dos2unix -f ~/nascleanup.sh; else tr -d \"\r\" < ~/nascleanup.sh > ~/nascleanup.sh.tmp && mv ~/nascleanup.sh.tmp ~/nascleanup.sh; fi; chmod +x ~/nascleanup.sh; ~/nascleanup.sh \"%NASPATH%\"'"
|
||||||
call :WIN_REMOVE_LOCAL_EADIR_TMP
|
if errorlevel 1 (
|
||||||
|
echo %RED%ERROR: nascleanup failed on NAS - check promote ^(eaDir_tmp -^> @eaDir^) messages above.%RST%
|
||||||
|
echo %YLW%Keeping eaDir_tmp on the share so you can retry without re-running FFmpeg.%RST%
|
||||||
|
call :PRINT_HYDRA_CLEAR_EADIR
|
||||||
|
) else (
|
||||||
|
call :WIN_REMOVE_LOCAL_EADIR_TMP
|
||||||
|
)
|
||||||
goto END
|
goto END
|
||||||
|
|
||||||
:FIX_ONEDRIVE
|
:FIX_ONEDRIVE
|
||||||
echo.
|
echo.
|
||||||
echo =================================================================
|
echo %BLD%%MAG%=================================================================%RST%
|
||||||
echo FIX ONEDRIVE THUMBNAIL OVERRIDE
|
echo %BLD%%MAG% FIX ONEDRIVE THUMBNAIL OVERRIDE %RST%
|
||||||
echo =================================================================
|
echo %BLD%%MAG%=================================================================%RST%
|
||||||
echo.
|
echo.
|
||||||
echo This will fix OneDrive overriding your custom thumbnails with
|
echo %WHT%This will fix OneDrive overriding your custom thumbnails with%RST%
|
||||||
echo generic file icons for unsupported formats like .blend files.
|
echo %WHT%generic file icons for unsupported formats like .blend files.%RST%
|
||||||
echo.
|
echo.
|
||||||
echo What this does:
|
echo %CYN%What this does:%RST%
|
||||||
echo - Disables OneDrive cloud thumbnail providers
|
echo %GRY% - Disables OneDrive cloud thumbnail providers%RST%
|
||||||
echo - Restores local thumbnail priority
|
echo %GRY% - Restores local thumbnail priority%RST%
|
||||||
echo - Prevents future thumbnail cache deletion
|
echo %GRY% - Prevents future thumbnail cache deletion%RST%
|
||||||
echo.
|
echo.
|
||||||
set /p CONFIRM=Continue? (y/n):
|
set /p CONFIRM=%YLW%Continue? ^(y/n^): %RST%
|
||||||
if /i not "%CONFIRM%"=="y" goto END
|
if /i not "%CONFIRM%"=="y" goto END
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo Running PowerShell script to fix OneDrive thumbnail override...
|
echo %GRN%Running PowerShell script to fix OneDrive thumbnail override...%RST%
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
REM Check if PowerShell script exists
|
REM Check if PowerShell script exists
|
||||||
if not exist "fix_thumbnail_override.ps1" (
|
if not exist "fix_thumbnail_override.ps1" (
|
||||||
echo ERROR: fix_thumbnail_override.ps1 not found in current directory.
|
echo %RED%ERROR: fix_thumbnail_override.ps1 not found in current directory.%RST%
|
||||||
echo Please ensure the PowerShell script is in the same folder as this batch file.
|
echo %YLW%Please ensure the PowerShell script is in the same folder as this batch file.%RST%
|
||||||
pause
|
pause
|
||||||
goto END
|
goto END
|
||||||
)
|
)
|
||||||
@@ -153,24 +178,34 @@ REM Run PowerShell script as administrator
|
|||||||
powershell -ExecutionPolicy Bypass -Command "Start-Process PowerShell -ArgumentList '-ExecutionPolicy Bypass -File \"%~dp0fix_thumbnail_override.ps1\"' -Verb RunAs"
|
powershell -ExecutionPolicy Bypass -Command "Start-Process PowerShell -ArgumentList '-ExecutionPolicy Bypass -File \"%~dp0fix_thumbnail_override.ps1\"' -Verb RunAs"
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo OneDrive thumbnail override fix initiated.
|
echo %GRN%OneDrive thumbnail override fix initiated.%RST%
|
||||||
echo Please check the PowerShell window for progress and results.
|
echo %GRY%Please check the PowerShell window for progress and results.%RST%
|
||||||
echo.
|
echo.
|
||||||
echo After the fix completes:
|
echo %CYN%After the fix completes:%RST%
|
||||||
echo 1. Restart your computer
|
echo %GRY% 1. Restart your computer%RST%
|
||||||
echo 2. Re-run your thumbnail generation process
|
echo %GRY% 2. Re-run your thumbnail generation process%RST%
|
||||||
echo 3. Your custom thumbnails should now have priority!
|
echo %GRY% 3. Your custom thumbnails should now have priority!%RST%
|
||||||
echo.
|
echo.
|
||||||
goto END
|
goto END
|
||||||
|
|
||||||
|
REM Print ssh Hydra command to wipe @eaDir when NAS cleanup failed (matches NASPATH from pasted R:\ path).
|
||||||
|
:PRINT_HYDRA_CLEAR_EADIR
|
||||||
|
if "%NASPATH%"=="" goto :eof
|
||||||
|
echo %MAG%To clear locked @eaDir on Hydra: ssh in first.%RST%
|
||||||
|
echo %GRY%Permission denied lines above name nested paths ^(e.g. editDesc, gameplay^).%RST%
|
||||||
|
echo %GRY%Clear every @eaDir under the SAME folder you passed to nascleanup ^(NASPATH below^),%RST%
|
||||||
|
echo %GRY%not only the subpath from the first error line.%RST%
|
||||||
|
echo %BLD%%YLW% sudo find "%NASPATH%" -depth -type d -name '@eaDir' -exec sudo rm -rf {} +%RST%
|
||||||
|
goto :eof
|
||||||
|
|
||||||
REM Remove folder-level @eaDir on the pasted Windows path (same files as NAS over SMB).
|
REM Remove folder-level @eaDir on the pasted Windows path (same files as NAS over SMB).
|
||||||
:WIN_REMOVE_LOCAL_EADIR
|
:WIN_REMOVE_LOCAL_EADIR
|
||||||
if "%WINPATH%"=="" goto :eof
|
if "%WINPATH%"=="" goto :eof
|
||||||
if exist "%WINPATH%\@eaDir" (
|
if exist "%WINPATH%\@eaDir" (
|
||||||
echo Removing "%WINPATH%\@eaDir" via Windows ^(SMB share^)...
|
echo %CYN%Removing "%WINPATH%\@eaDir" via Windows ^(SMB share^)...%RST%
|
||||||
rd /s /q "%WINPATH%\@eaDir" 2>nul
|
rd /s /q "%WINPATH%\@eaDir" 2>nul
|
||||||
if exist "%WINPATH%\@eaDir" (
|
if exist "%WINPATH%\@eaDir" (
|
||||||
echo WARNING: Could not remove @eaDir; try PowerShell as admin or delete in Explorer.
|
echo %YLW%WARNING: Could not remove @eaDir; try PowerShell as admin or delete in Explorer.%RST%
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
goto :eof
|
goto :eof
|
||||||
@@ -178,13 +213,14 @@ goto :eof
|
|||||||
REM Remove every eaDir_tmp under pasted path (including subfolders e.g. gameplay\eaDir_tmp).
|
REM Remove every eaDir_tmp under pasted path (including subfolders e.g. gameplay\eaDir_tmp).
|
||||||
:WIN_REMOVE_LOCAL_EADIR_TMP
|
:WIN_REMOVE_LOCAL_EADIR_TMP
|
||||||
if "%WINPATH%"=="" goto :eof
|
if "%WINPATH%"=="" goto :eof
|
||||||
echo Removing all eaDir_tmp folders under "%WINPATH%" ^(recursive, SMB^)...
|
echo %CYN%Removing all eaDir_tmp folders under "%WINPATH%" ^(recursive, SMB^)...%RST%
|
||||||
if not exist "%~dp0remove_eadir_tmp_recursive.ps1" (
|
if not exist "%~dp0remove_eadir_tmp_recursive.ps1" (
|
||||||
echo ERROR: remove_eadir_tmp_recursive.ps1 not found next to this batch file.
|
echo %RED%ERROR: remove_eadir_tmp_recursive.ps1 not found next to this batch file.%RST%
|
||||||
goto :eof
|
goto :eof
|
||||||
)
|
)
|
||||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0remove_eadir_tmp_recursive.ps1" "%WINPATH%"
|
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0remove_eadir_tmp_recursive.ps1" "%WINPATH%"
|
||||||
goto :eof
|
goto :eof
|
||||||
|
|
||||||
:END
|
:END
|
||||||
pause
|
echo %DIM%Press any key to continue . . .%RST%
|
||||||
|
pause >nul
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ fi
|
|||||||
echo "=== Extracting @eaDir thumbnails to eaDir_tmp ==="
|
echo "=== Extracting @eaDir thumbnails to eaDir_tmp ==="
|
||||||
echo "Target: $TARGET_DIR"
|
echo "Target: $TARGET_DIR"
|
||||||
|
|
||||||
# Only TARGET_DIR/@eaDir (not nested .../@eaDir/.../@eaDir from bad prior runs; those hit chmod 555 parents)
|
# Every .../@eaDir under TARGET (e.g. TARGET/@eaDir and TARGET/gameplay/@eaDir). Skip paths inside eaDir_tmp.
|
||||||
find "$TARGET_DIR" -mindepth 1 -maxdepth 1 -type d -name '@eaDir' -print0 | while IFS= read -r -d '' EADIR; do
|
find "$TARGET_DIR" -type d -name '@eaDir' ! -path '*/eaDir_tmp/*' -print0 | while IFS= read -r -d '' EADIR; do
|
||||||
PARENT_DIR="$(dirname "$EADIR")"
|
PARENT_DIR="$(dirname "$EADIR")"
|
||||||
|
|
||||||
# Each immediate subdir under @eaDir corresponds to a source filename
|
# Each immediate subdir under @eaDir corresponds to a source filename
|
||||||
|
|||||||
+43
-27
@@ -28,6 +28,38 @@ flatten_indexer_layout() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Copy one thumbgen tree: PARENT/eaDir_tmp -> PARENT/@eaDir (psthumbgen uses per-folder eaDir_tmp).
|
||||||
|
promote_one_eadir_tmp() {
|
||||||
|
local EADIR_TMP="$1"
|
||||||
|
local PARENT TARGET_AT SRC_JPG DST_JPG
|
||||||
|
PARENT="$(dirname "$EADIR_TMP")"
|
||||||
|
TARGET_AT="$PARENT/@eaDir"
|
||||||
|
[ -d "$EADIR_TMP" ] || return 0
|
||||||
|
chmod -R 755 "$EADIR_TMP" 2>/dev/null || true
|
||||||
|
find "$EADIR_TMP" -type f -exec chmod 644 '{}' \; 2>/dev/null || true
|
||||||
|
echo " -> Flattening eaDir_tmp (indexer may have added .../<file>/@eaDir/) before copy: $EADIR_TMP"
|
||||||
|
flatten_indexer_layout "$EADIR_TMP"
|
||||||
|
echo " -> Replacing $EADIR_TMP -> $TARGET_AT"
|
||||||
|
SRC_JPG=$(find "$EADIR_TMP" -type f -name 'SYNO*.jpg' 2>/dev/null | wc -l | tr -d '[:space:]')
|
||||||
|
rm -rf "$TARGET_AT"
|
||||||
|
mkdir -p "$TARGET_AT"
|
||||||
|
if ! cp -R "$EADIR_TMP/." "$TARGET_AT/"; then
|
||||||
|
echo "ERROR: eaDir_tmp -> @eaDir copy failed (see cp messages above)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " -> Flattening @eaDir after copy (same layout fix)"
|
||||||
|
flatten_indexer_layout "$TARGET_AT"
|
||||||
|
DST_JPG=$(find "$TARGET_AT" -type f -name 'SYNO*.jpg' 2>/dev/null | wc -l | tr -d '[:space:]')
|
||||||
|
if [ "$SRC_JPG" -gt 0 ] && [ "$DST_JPG" -ne "$SRC_JPG" ]; then
|
||||||
|
echo "ERROR: Promote incomplete: $DST_JPG SYNO*.jpg in @eaDir vs $SRC_JPG in eaDir_tmp (expected equal)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
chmod -R 755 "$EADIR_TMP" 2>/dev/null || true
|
||||||
|
find "$EADIR_TMP" -type f -exec chmod u+w '{}' \; 2>/dev/null || true
|
||||||
|
find "$EADIR_TMP" -type d -exec chmod u+w '{}' \; 2>/dev/null || true
|
||||||
|
rm -rf "$EADIR_TMP" 2>/dev/null || sudo -n rm -rf "$EADIR_TMP" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
echo "=== Enhanced Synology Thumbnail Cleanup ==="
|
echo "=== Enhanced Synology Thumbnail Cleanup ==="
|
||||||
echo "Target directory: $TARGET_DIR"
|
echo "Target directory: $TARGET_DIR"
|
||||||
|
|
||||||
@@ -77,33 +109,18 @@ find "$TARGET_DIR" -path '*/@eaDir/*' -type f -exec chmod 644 '{}' \; 2>/dev/nul
|
|||||||
# Now remove them (2>/dev/null: races when parents disappear mid-find)
|
# Now remove them (2>/dev/null: races when parents disappear mid-find)
|
||||||
find "$TARGET_DIR" -type d -name '@eaDir' -exec rm -rf '{}' \; 2>/dev/null || true
|
find "$TARGET_DIR" -type d -name '@eaDir' -exec rm -rf '{}' \; 2>/dev/null || true
|
||||||
|
|
||||||
# 5. Promote only TARGET_DIR/eaDir_tmp -> TARGET_DIR/@eaDir (thumbgen layout; not nested */eaDir_tmp)
|
# 5. Promote every .../eaDir_tmp -> .../@eaDir (thumbgen writes eaDir_tmp next to each video folder, not only TARGET_DIR/eaDir_tmp)
|
||||||
echo "=== Installing custom thumbnails ==="
|
echo "=== Installing custom thumbnails ==="
|
||||||
EADIR_TMP="$TARGET_DIR/eaDir_tmp"
|
INSTALL_ANY=0
|
||||||
if [ -d "$EADIR_TMP" ]; then
|
while IFS= read -r -d '' EADIR_TMP; do
|
||||||
chmod -R 755 "$EADIR_TMP" 2>/dev/null || true
|
INSTALL_ANY=1
|
||||||
find "$EADIR_TMP" -type f -exec chmod 644 '{}' \; 2>/dev/null || true
|
promote_one_eadir_tmp "$EADIR_TMP"
|
||||||
echo " -> Flattening eaDir_tmp (indexer may have added .../<file>/@eaDir/) before copy"
|
done < <(find "$TARGET_DIR" -type d -name 'eaDir_tmp' -print0)
|
||||||
flatten_indexer_layout "$EADIR_TMP"
|
if [ "$INSTALL_ANY" -eq 0 ]; then
|
||||||
TARGET_AT="$TARGET_DIR/@eaDir"
|
echo " -> No eaDir_tmp under $TARGET_DIR; skipping install step"
|
||||||
echo " -> Replacing $EADIR_TMP -> $TARGET_AT"
|
|
||||||
rm -rf "$TARGET_AT"
|
|
||||||
mkdir -p "$TARGET_AT"
|
|
||||||
cp -R "$EADIR_TMP/." "$TARGET_AT/"
|
|
||||||
echo " -> Flattening @eaDir after copy (same layout fix)"
|
|
||||||
flatten_indexer_layout "$TARGET_AT"
|
|
||||||
chmod -R 755 "$EADIR_TMP" 2>/dev/null || true
|
|
||||||
find "$EADIR_TMP" -type f -exec chmod u+w '{}' \; 2>/dev/null || true
|
|
||||||
find "$EADIR_TMP" -type d -exec chmod u+w '{}' \; 2>/dev/null || true
|
|
||||||
if ! rm -rf "$EADIR_TMP" 2>/dev/null; then
|
|
||||||
echo " -> rm eaDir_tmp failed; retrying with sudo -n"
|
|
||||||
sudo -n rm -rf "$EADIR_TMP" 2>/dev/null || echo " -> WARNING: remove stale eaDir_tmp manually: sudo rm -rf \"$EADIR_TMP\""
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " -> No $EADIR_TMP; skipping install step"
|
|
||||||
fi
|
fi
|
||||||
echo "=== Removing stray nested eaDir_tmp directories ==="
|
echo "=== Removing any leftover eaDir_tmp directories ==="
|
||||||
find "$TARGET_DIR" -mindepth 2 -type d -name 'eaDir_tmp' -exec rm -rf '{}' \; 2>/dev/null || true
|
find "$TARGET_DIR" -type d -name 'eaDir_tmp' -exec rm -rf '{}' \; 2>/dev/null || true
|
||||||
|
|
||||||
# 6. Protect custom thumbnails with read-only permissions
|
# 6. Protect custom thumbnails with read-only permissions
|
||||||
echo "=== Adding indexing exclusion hints ==="
|
echo "=== Adding indexing exclusion hints ==="
|
||||||
@@ -124,5 +141,4 @@ elif command -v systemctl >/dev/null 2>&1; then
|
|||||||
sudo -n systemctl start "$u" 2>/dev/null || systemctl start "$u" 2>/dev/null || true
|
sudo -n systemctl start "$u" 2>/dev/null || systemctl start "$u" 2>/dev/null || true
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
echo "Note: If indexing was stopped and needs restarting, use DSM UI or: sudo systemctl restart synoindexd"
|
echo "Note: If indexing was stopped and needs restarting, use DSM UI or: sudo systemctl restart synoindexd"
|
||||||
echo "If rm failed with Permission denied: delete @eaDir and eaDir_tmp on your pasted Windows path (SMB), or: sudo rm -rf ${TARGET_DIR}/eaDir_tmp ${TARGET_DIR}/@eaDir — then re-run option 3."
|
|
||||||
+61
-34
@@ -72,6 +72,29 @@ def _ffmpeg_enabled():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
_ANSI_BLUE = "\033[94m"
|
||||||
|
_ANSI_GREEN = "\033[92m"
|
||||||
|
_ANSI_RST = "\033[0m"
|
||||||
|
|
||||||
|
|
||||||
|
def _print_icaros(msg):
|
||||||
|
print(f"{_ANSI_BLUE}{msg}{_ANSI_RST}")
|
||||||
|
|
||||||
|
|
||||||
|
def _print_ffmpeg(msg):
|
||||||
|
print(f"{_ANSI_GREEN}{msg}{_ANSI_RST}")
|
||||||
|
|
||||||
|
|
||||||
|
def _ffmpeg_first_for_gameplay_path(path):
|
||||||
|
"""Under ...\\gameplay\\, Shell GetThumbnail often fails and Icaros cache misses; go straight to FFmpeg."""
|
||||||
|
if not _ffmpeg_enabled():
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
p = os.path.normpath(path).replace("/", "\\").lower()
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return "\\gameplay\\" in p
|
||||||
|
|
||||||
|
|
||||||
def find_files(dir):
|
def find_files(dir):
|
||||||
# Only process formats that Synology doesn't handle well
|
# Only process formats that Synology doesn't handle well
|
||||||
@@ -133,16 +156,20 @@ def ensure_directory_exists(path):
|
|||||||
|
|
||||||
def create_video_thumbnails(source_path, dest_dir):
|
def create_video_thumbnails(source_path, dest_dir):
|
||||||
"""Generate video thumbnails: Windows Shell (Icaros-backed) first, FFmpeg fallback."""
|
"""Generate video thumbnails: Windows Shell (Icaros-backed) first, FFmpeg fallback."""
|
||||||
|
if _ffmpeg_first_for_gameplay_path(source_path):
|
||||||
|
_print_ffmpeg(f"Using FFmpeg directly (gameplay subtree): {source_path}")
|
||||||
|
create_video_thumbnails_ffmpeg(source_path, dest_dir)
|
||||||
|
return
|
||||||
# Try Windows thumbnail extraction first (leverages Icaros provider when present)
|
# Try Windows thumbnail extraction first (leverages Icaros provider when present)
|
||||||
windows_thumb = extract_windows_thumbnail(source_path)
|
windows_thumb = extract_windows_thumbnail(source_path)
|
||||||
if windows_thumb:
|
if windows_thumb:
|
||||||
print(f" -> SUCCESS: Using Windows/Icaros provider")
|
_print_icaros(f" -> SUCCESS: Using Windows/Icaros provider")
|
||||||
generate_synology_thumbnails(windows_thumb, dest_dir, include_video_screenshot=True)
|
generate_synology_thumbnails(windows_thumb, dest_dir, include_video_screenshot=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Optionally fall back to FFmpeg (disabled by default)
|
# Optionally fall back to FFmpeg (disabled by default)
|
||||||
if _ffmpeg_enabled():
|
if _ffmpeg_enabled():
|
||||||
print(f"Windows/Icaros extraction failed for {source_path}, using FFmpeg...")
|
_print_ffmpeg(f"Windows/Icaros extraction failed for {source_path}, using FFmpeg...")
|
||||||
create_video_thumbnails_ffmpeg(source_path, dest_dir)
|
create_video_thumbnails_ffmpeg(source_path, dest_dir)
|
||||||
else:
|
else:
|
||||||
print(f"Windows/Icaros extraction failed for {source_path}, FFmpeg disabled (THUMBGEN_ENABLE_FFMPEG=0). Skipping.")
|
print(f"Windows/Icaros extraction failed for {source_path}, FFmpeg disabled (THUMBGEN_ENABLE_FFMPEG=0). Skipping.")
|
||||||
@@ -175,15 +202,15 @@ def create_video_thumbnails_ffmpeg(source_path, dest_dir):
|
|||||||
|
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print(f"Warning: FFmpeg failed for {source_path}: {result.stderr}")
|
_print_ffmpeg(f"Warning: FFmpeg failed for {source_path}: {result.stderr}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("Warning: FFmpeg not found. Video thumbnails will be skipped.")
|
_print_ffmpeg("Warning: FFmpeg not found. Video thumbnails will be skipped.")
|
||||||
print("Install FFmpeg: https://ffmpeg.org/download.html")
|
_print_ffmpeg("Install FFmpeg: https://ffmpeg.org/download.html")
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error processing video {source_path}: {e}")
|
_print_ffmpeg(f"Error processing video {source_path}: {e}")
|
||||||
|
|
||||||
|
|
||||||
def create_psd_thumbnails(source_path, dest_dir):
|
def create_psd_thumbnails(source_path, dest_dir):
|
||||||
@@ -315,15 +342,15 @@ def extract_windows_thumbnail(file_path):
|
|||||||
|
|
||||||
# Tier 3: Try Icaros cache extraction
|
# Tier 3: Try Icaros cache extraction
|
||||||
try:
|
try:
|
||||||
print(f" -> Trying Icaros cache extraction...")
|
_print_icaros(f" -> Trying Icaros cache extraction...")
|
||||||
icaros_thumb = extract_icaros_thumbnail(file_path)
|
icaros_thumb = extract_icaros_thumbnail(file_path)
|
||||||
if icaros_thumb:
|
if icaros_thumb:
|
||||||
print(f" -> Found thumbnail in Icaros cache for {filename}")
|
_print_icaros(f" -> Found thumbnail in Icaros cache for {filename}")
|
||||||
return icaros_thumb
|
return icaros_thumb
|
||||||
else:
|
else:
|
||||||
print(f" -> No thumbnail in Icaros cache for {filename}")
|
_print_icaros(f" -> No thumbnail in Icaros cache for {filename}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" -> Icaros cache extraction failed: {e}")
|
_print_icaros(f" -> Icaros cache extraction failed: {e}")
|
||||||
|
|
||||||
print(f" -> Windows thumbnail extraction failed for {filename}")
|
print(f" -> Windows thumbnail extraction failed for {filename}")
|
||||||
return None
|
return None
|
||||||
@@ -679,28 +706,28 @@ def extract_icaros_thumbnail(file_path):
|
|||||||
# Locate Icaros cache directory
|
# Locate Icaros cache directory
|
||||||
icaros_cache_dir = _get_icaros_cache_dir()
|
icaros_cache_dir = _get_icaros_cache_dir()
|
||||||
if not icaros_cache_dir:
|
if not icaros_cache_dir:
|
||||||
print(f" -> No Icaros cache directory found")
|
_print_icaros(f" -> No Icaros cache directory found")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Debug: Show cache directory contents (all files)
|
# Debug: Show cache directory contents (all files)
|
||||||
try:
|
try:
|
||||||
cache_files = os.listdir(icaros_cache_dir)
|
cache_files = os.listdir(icaros_cache_dir)
|
||||||
print(f" -> Icaros cache has {len(cache_files)} files")
|
_print_icaros(f" -> Icaros cache has {len(cache_files)} files")
|
||||||
if len(cache_files) > 0:
|
if len(cache_files) > 0:
|
||||||
print(f" -> All cache files: {cache_files}")
|
_print_icaros(f" -> All cache files: {cache_files}")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Discover .icdb databases by size preference
|
# Discover .icdb databases by size preference
|
||||||
icdb_paths = _list_icdb_databases(icaros_cache_dir)
|
icdb_paths = _list_icdb_databases(icaros_cache_dir)
|
||||||
if not icdb_paths:
|
if not icdb_paths:
|
||||||
print(f" -> No .icdb database files found")
|
_print_icaros(f" -> No .icdb database files found")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Lookup a precise index for this file from Icaros_idx.icdb (SQLite or binary)
|
# Lookup a precise index for this file from Icaros_idx.icdb (SQLite or binary)
|
||||||
mapped_index, preferred_db = _lookup_icaros_index(icaros_cache_dir, file_path)
|
mapped_index, preferred_db = _lookup_icaros_index(icaros_cache_dir, file_path)
|
||||||
if mapped_index is None:
|
if mapped_index is None:
|
||||||
print(f" -> No exact Icaros index entry for this file; skipping Icaros")
|
_print_icaros(f" -> No exact Icaros index entry for this file; skipping Icaros")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Try preferred DB first if provided
|
# Try preferred DB first if provided
|
||||||
@@ -711,16 +738,16 @@ def extract_icaros_thumbnail(file_path):
|
|||||||
for icdb_path in ordered_dbs:
|
for icdb_path in ordered_dbs:
|
||||||
img = extract_from_icdb_database(icdb_path, file_path, forced_index=mapped_index)
|
img = extract_from_icdb_database(icdb_path, file_path, forced_index=mapped_index)
|
||||||
if img:
|
if img:
|
||||||
print(f" -> Found thumbnail in {os.path.basename(icdb_path)} via mapped index")
|
_print_icaros(f" -> Found thumbnail in {os.path.basename(icdb_path)} via mapped index")
|
||||||
return img
|
return img
|
||||||
print(f" -> Mapped index did not resolve a thumbnail in any DB")
|
_print_icaros(f" -> Mapped index did not resolve a thumbnail in any DB")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print(f" -> Required modules not available for .icdb extraction")
|
_print_icaros(f" -> Required modules not available for .icdb extraction")
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" -> Icaros cache extraction error: {e}")
|
_print_icaros(f" -> Icaros cache extraction error: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -814,12 +841,12 @@ def _build_icaros_index_map(cache_dir):
|
|||||||
conn.close()
|
conn.close()
|
||||||
_ICAROS_INDEX_CACHE = mapping
|
_ICAROS_INDEX_CACHE = mapping
|
||||||
if mapping:
|
if mapping:
|
||||||
print(f" -> Loaded Icaros index map for {len(mapping)} files")
|
_print_icaros(f" -> Loaded Icaros index map for {len(mapping)} files")
|
||||||
else:
|
else:
|
||||||
print(f" -> Icaros index database present but no usable mapping found")
|
_print_icaros(f" -> Icaros index database present but no usable mapping found")
|
||||||
return _ICAROS_INDEX_CACHE
|
return _ICAROS_INDEX_CACHE
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" -> Failed to read Icaros index: {e}")
|
_print_icaros(f" -> Failed to read Icaros index: {e}")
|
||||||
_ICAROS_INDEX_CACHE = {}
|
_ICAROS_INDEX_CACHE = {}
|
||||||
return _ICAROS_INDEX_CACHE
|
return _ICAROS_INDEX_CACHE
|
||||||
|
|
||||||
@@ -988,7 +1015,7 @@ def extract_from_icdb_database(icdb_path, file_path, forced_index=None):
|
|||||||
|
|
||||||
# Verify ICDB signature
|
# Verify ICDB signature
|
||||||
if not data.startswith(b'ICDB'):
|
if not data.startswith(b'ICDB'):
|
||||||
print(f" -> Invalid ICDB signature in {icdb_path}")
|
_print_icaros(f" -> Invalid ICDB signature in {icdb_path}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Search for JPEG images in the file
|
# Search for JPEG images in the file
|
||||||
@@ -1002,10 +1029,10 @@ def extract_from_icdb_database(icdb_path, file_path, forced_index=None):
|
|||||||
pos += 1
|
pos += 1
|
||||||
|
|
||||||
if not jpeg_positions:
|
if not jpeg_positions:
|
||||||
print(f" -> No JPEG images found in {icdb_path}")
|
_print_icaros(f" -> No JPEG images found in {icdb_path}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
print(f" -> Found {len(jpeg_positions)} JPEG images in {icdb_path}")
|
_print_icaros(f" -> Found {len(jpeg_positions)} JPEG images in {icdb_path}")
|
||||||
|
|
||||||
# If we have a mapped index, try it directly first
|
# If we have a mapped index, try it directly first
|
||||||
if isinstance(forced_index, int) and len(jpeg_positions) > 0:
|
if isinstance(forced_index, int) and len(jpeg_positions) > 0:
|
||||||
@@ -1021,11 +1048,11 @@ def extract_from_icdb_database(icdb_path, file_path, forced_index=None):
|
|||||||
jpeg_data = data[jpeg_start:jpeg_end]
|
jpeg_data = data[jpeg_start:jpeg_end]
|
||||||
try:
|
try:
|
||||||
img = Image.open(io.BytesIO(jpeg_data))
|
img = Image.open(io.BytesIO(jpeg_data))
|
||||||
print(f" -> Used mapped index {pos_index} from {os.path.basename(icdb_path)}")
|
_print_icaros(f" -> Used mapped index {pos_index} from {os.path.basename(icdb_path)}")
|
||||||
return img.copy()
|
return img.copy()
|
||||||
except Exception:
|
except Exception:
|
||||||
# If mapped position invalid, continue to heuristic
|
# If mapped position invalid, continue to heuristic
|
||||||
print(f" -> Mapped index {pos_index} invalid; falling back to heuristic")
|
_print_icaros(f" -> Mapped index {pos_index} invalid; falling back to heuristic")
|
||||||
|
|
||||||
# Heuristic alphabetical mapping (fallback)
|
# Heuristic alphabetical mapping (fallback)
|
||||||
def get_alphabetical_position(target_file_path):
|
def get_alphabetical_position(target_file_path):
|
||||||
@@ -1079,10 +1106,10 @@ def extract_from_icdb_database(icdb_path, file_path, forced_index=None):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
position = all_files.index(target_rel_path)
|
position = all_files.index(target_rel_path)
|
||||||
print(f" -> Alphabetical position estimate: {position} for {target_filename}")
|
_print_icaros(f" -> Alphabetical position estimate: {position} for {target_filename}")
|
||||||
return position
|
return position
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print(f" -> File {target_filename} not found in current monitored directories")
|
_print_icaros(f" -> File {target_filename} not found in current monitored directories")
|
||||||
# Return a reasonable fallback position
|
# Return a reasonable fallback position
|
||||||
return len(all_files) // 2 # Middle position as fallback
|
return len(all_files) // 2 # Middle position as fallback
|
||||||
|
|
||||||
@@ -1093,16 +1120,16 @@ def extract_from_icdb_database(icdb_path, file_path, forced_index=None):
|
|||||||
if cache_position >= len(jpeg_positions):
|
if cache_position >= len(jpeg_positions):
|
||||||
# Use modulo to wrap around (cache might be from larger file set)
|
# Use modulo to wrap around (cache might be from larger file set)
|
||||||
cache_position = cache_position % len(jpeg_positions)
|
cache_position = cache_position % len(jpeg_positions)
|
||||||
print(f" -> Wrapped position to {cache_position} (cache has {len(jpeg_positions)} entries)")
|
_print_icaros(f" -> Wrapped position to {cache_position} (cache has {len(jpeg_positions)} entries)")
|
||||||
|
|
||||||
jpeg_start = jpeg_positions[cache_position]
|
jpeg_start = jpeg_positions[cache_position]
|
||||||
|
|
||||||
print(f" -> Alphabetical mapping -> JPEG {cache_position} for {os.path.basename(file_path)}")
|
_print_icaros(f" -> Alphabetical mapping -> JPEG {cache_position} for {os.path.basename(file_path)}")
|
||||||
|
|
||||||
# Find the end of the JPEG (FF D9 marker)
|
# Find the end of the JPEG (FF D9 marker)
|
||||||
jpeg_end = data.find(b'\xff\xd9', jpeg_start)
|
jpeg_end = data.find(b'\xff\xd9', jpeg_start)
|
||||||
if jpeg_end == -1:
|
if jpeg_end == -1:
|
||||||
print(f" -> Could not find JPEG end marker")
|
_print_icaros(f" -> Could not find JPEG end marker")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
jpeg_end += 2 # Include the end marker
|
jpeg_end += 2 # Include the end marker
|
||||||
@@ -1110,11 +1137,11 @@ def extract_from_icdb_database(icdb_path, file_path, forced_index=None):
|
|||||||
|
|
||||||
# Try to create PIL Image from the JPEG data
|
# Try to create PIL Image from the JPEG data
|
||||||
img = Image.open(io.BytesIO(jpeg_data))
|
img = Image.open(io.BytesIO(jpeg_data))
|
||||||
print(f" -> Successfully extracted {img.size[0]}x{img.size[1]} JPEG from {icdb_path}")
|
_print_icaros(f" -> Successfully extracted {img.size[0]}x{img.size[1]} JPEG from {icdb_path}")
|
||||||
return img.copy()
|
return img.copy()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" -> Error reading ICDB file {icdb_path}: {e}")
|
_print_icaros(f" -> Error reading ICDB file {icdb_path}: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user