diff --git a/.aiignore b/.aiignore
index 71ddf39..3236782 100644
--- a/.aiignore
+++ b/.aiignore
@@ -10,3 +10,9 @@
dist/
build/
out/
+.idea
+node_modules/
+.vscode/
+.git
+.github
+scripts
diff --git a/.dockerignore b/.dockerignore
index d46082c..0ad7b8c 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -4,6 +4,7 @@ models/
# Exclude build artifacts
target/
+build/
*.class
*.jar
diff --git a/.gitignore b/.gitignore
index 566eb98..a4011b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,4 +31,5 @@ bin/
NUL
target/
+build/
.idea/
\ No newline at end of file
diff --git a/.mvn/jvm.config b/.mvn/jvm.config
deleted file mode 100644
index 5e13934..0000000
--- a/.mvn/jvm.config
+++ /dev/null
@@ -1,6 +0,0 @@
---add-opens=java.base/java.lang=ALL-UNNAMED
---add-opens=java.base/java.util=ALL-UNNAMED
---add-opens=java.base/java.util.concurrent=ALL-UNNAMED
---add-opens=java.base/java.net=ALL-UNNAMED
---add-opens=java.base/java.io=ALL-UNNAMED
---enable-native-access=ALL-UNNAMED
\ No newline at end of file
diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
deleted file mode 100644
index b901097..0000000
--- a/.mvn/wrapper/MavenWrapperDownloader.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2007-present the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import java.net.*;
-import java.io.*;
-import java.nio.channels.*;
-import java.util.Properties;
-
-public class MavenWrapperDownloader {
-
- private static final String WRAPPER_VERSION = "0.5.6";
- /**
- * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
- */
- private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
- + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
-
- /**
- * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
- * use instead of the default one.
- */
- private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
- ".mvn/wrapper/maven-wrapper.properties";
-
- /**
- * Path where the maven-wrapper.jar will be saved to.
- */
- private static final String MAVEN_WRAPPER_JAR_PATH =
- ".mvn/wrapper/maven-wrapper.jar";
-
- /**
- * Name of the property which should be used to override the default download url for the wrapper.
- */
- private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
-
- public static void main(String args[]) {
- System.out.println("- Downloader started");
- File baseDirectory = new File(args[0]);
- System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
-
- // If the maven-wrapper.properties exists, read it and check if it contains a custom
- // wrapperUrl parameter.
- File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
- String url = DEFAULT_DOWNLOAD_URL;
- if(mavenWrapperPropertyFile.exists()) {
- FileInputStream mavenWrapperPropertyFileInputStream = null;
- try {
- mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
- Properties mavenWrapperProperties = new Properties();
- mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
- url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
- } catch (IOException e) {
- System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
- } finally {
- try {
- if(mavenWrapperPropertyFileInputStream != null) {
- mavenWrapperPropertyFileInputStream.close();
- }
- } catch (IOException e) {
- // Ignore ...
- }
- }
- }
- System.out.println("- Downloading from: " + url);
-
- File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
- if(!outputFile.getParentFile().exists()) {
- if(!outputFile.getParentFile().mkdirs()) {
- System.out.println(
- "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
- }
- }
- System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
- try {
- downloadFileFromURL(url, outputFile);
- System.out.println("Done");
- System.exit(0);
- } catch (Throwable e) {
- System.out.println("- Error downloading");
- e.printStackTrace();
- System.exit(1);
- }
- }
-
- private static void downloadFileFromURL(String urlString, File destination) throws Exception {
- if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
- String username = System.getenv("MVNW_USERNAME");
- char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
- Authenticator.setDefault(new Authenticator() {
- @Override
- protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(username, password);
- }
- });
- }
- URL website = new URL(urlString);
- ReadableByteChannel rbc;
- rbc = Channels.newChannel(website.openStream());
- FileOutputStream fos = new FileOutputStream(destination);
- fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
- fos.close();
- rbc.close();
- }
-
-}
diff --git a/.mvn/wrapper/maven-wrapper.config b/.mvn/wrapper/maven-wrapper.config
deleted file mode 100644
index bb2c375..0000000
--- a/.mvn/wrapper/maven-wrapper.config
+++ /dev/null
@@ -1 +0,0 @@
-jvmArguments=-Djava.util.logging.manager=org.jboss.logmanager.LogManager --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED
\ No newline at end of file
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
deleted file mode 100644
index eebc3c1..0000000
Binary files a/.mvn/wrapper/maven-wrapper.jar and /dev/null differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
deleted file mode 100644
index 4d39061..0000000
--- a/.mvn/wrapper/maven-wrapper.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
-wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar
\ No newline at end of file
diff --git a/.mvn/wrapper/maven-wrapper_old.jar b/.mvn/wrapper/maven-wrapper_old.jar
deleted file mode 100644
index 2cc7d4a..0000000
Binary files a/.mvn/wrapper/maven-wrapper_old.jar and /dev/null differ
diff --git a/README.md b/README.md
index 48fc19c..b2300d7 100644
--- a/README.md
+++ b/README.md
@@ -119,8 +119,8 @@ mvn clean package
```
This creates:
-- `target/troostwijk-scraper-1.0-SNAPSHOT.jar` - Regular JAR
-- `target/troostwijk-scraper-1.0-SNAPSHOT-jar-with-dependencies.jar` - Executable JAR with all dependencies
+- `../build/auctiora/auctiora-1.0-SNAPSHOT.jar` - Regular JAR
+- `../build/auctiora/auctiora-1.0-SNAPSHOT-jar-with-dependencies.jar` - Executable JAR with all dependencies
## Running
@@ -128,7 +128,7 @@ This creates:
```bash
java -Djava.library.path="/path/to/opencv/lib" \
- -jar target/troostwijk-scraper-1.0-SNAPSHOT-jar-with-dependencies.jar
+ -jar ../build/auctiora/troostwijk-scraper-1.0-SNAPSHOT-jar-with-dependencies.jar
```
### With Email Notifications
@@ -137,7 +137,7 @@ java -Djava.library.path="/path/to/opencv/lib" \
export NOTIFICATION_CONFIG="smtp:your@gmail.com:app_password:your@gmail.com"
java -Djava.library.path="/path/to/opencv/lib" \
- -jar target/troostwijk-scraper-1.0-SNAPSHOT-jar-with-dependencies.jar
+ -jar ../build/auctiora/troostwijk-scraper-1.0-SNAPSHOT-jar-with-dependencies.jar
```
### Using Maven
diff --git a/docs/QUARKUS_GUIDE.md b/docs/QUARKUS_GUIDE.md
index d0aa95a..7a4c8cc 100644
--- a/docs/QUARKUS_GUIDE.md
+++ b/docs/QUARKUS_GUIDE.md
@@ -36,11 +36,11 @@ mvn quarkus:dev
mvn clean package
# Run
-java -jar target/quarkus-app/quarkus-run.jar
+java -jar ../build/auctiora/quarkus-app/quarkus-run.jar
# Or use fast-jar (recommended for production)
mvn clean package -Dquarkus.package.jar.type=fast-jar
-java -jar target/quarkus-app/quarkus-run.jar
+java -jar ../build/auctiora/quarkus-app/quarkus-run.jar
```
### Option 3: Docker
@@ -545,7 +545,7 @@ quarkus.log.category."com.auction".level=DEBUG
mvn package -Pnative
# Run native executable
-./target/troostwijk-scraper-1.0-SNAPSHOT-runner
+../build/auctiora/troostwijk-scraper-1.0-SNAPSHOT-runner
```
---
diff --git a/mvnw b/mvnw
deleted file mode 100644
index 41c0f0c..0000000
--- a/mvnw
+++ /dev/null
@@ -1,310 +0,0 @@
-#!/bin/sh
-# ----------------------------------------------------------------------------
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-# ----------------------------------------------------------------------------
-
-# ----------------------------------------------------------------------------
-# Maven Start Up Batch script
-#
-# Required ENV vars:
-# ------------------
-# JAVA_HOME - location of a JDK home dir
-#
-# Optional ENV vars
-# -----------------
-# M2_HOME - location of maven2's installed home dir
-# MAVEN_OPTS - parameters passed to the Java VM when running Maven
-# e.g. to debug Maven itself, use
-# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
-# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
-# ----------------------------------------------------------------------------
-
-if [ -z "$MAVEN_SKIP_RC" ] ; then
-
- if [ -f /etc/mavenrc ] ; then
- . /etc/mavenrc
- fi
-
- if [ -f "$HOME/.mavenrc" ] ; then
- . "$HOME/.mavenrc"
- fi
-
-fi
-
-# OS specific support. $var _must_ be set to either true or false.
-cygwin=false;
-darwin=false;
-mingw=false
-case "`uname`" in
- CYGWIN*) cygwin=true ;;
- MINGW*) mingw=true;;
- Darwin*) darwin=true
- # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
- # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
- if [ -z "$JAVA_HOME" ]; then
- if [ -x "/usr/libexec/java_home" ]; then
- export JAVA_HOME="`/usr/libexec/java_home`"
- else
- export JAVA_HOME="/Library/Java/Home"
- fi
- fi
- ;;
-esac
-
-if [ -z "$JAVA_HOME" ] ; then
- if [ -r /etc/gentoo-release ] ; then
- JAVA_HOME=`java-config --jre-home`
- fi
-fi
-
-if [ -z "$M2_HOME" ] ; then
- ## resolve links - $0 may be a link to maven's home
- PRG="$0"
-
- # need this for relative symlinks
- while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG="`dirname "$PRG"`/$link"
- fi
- done
-
- saveddir=`pwd`
-
- M2_HOME=`dirname "$PRG"`/..
-
- # make it fully qualified
- M2_HOME=`cd "$M2_HOME" && pwd`
-
- cd "$saveddir"
- # echo Using m2 at $M2_HOME
-fi
-
-# For Cygwin, ensure paths are in UNIX format before anything is touched
-if $cygwin ; then
- [ -n "$M2_HOME" ] &&
- M2_HOME=`cygpath --unix "$M2_HOME"`
- [ -n "$JAVA_HOME" ] &&
- JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
- [ -n "$CLASSPATH" ] &&
- CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
-fi
-
-# For Mingw, ensure paths are in UNIX format before anything is touched
-if $mingw ; then
- [ -n "$M2_HOME" ] &&
- M2_HOME="`(cd "$M2_HOME"; pwd)`"
- [ -n "$JAVA_HOME" ] &&
- JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
-fi
-
-if [ -z "$JAVA_HOME" ]; then
- javaExecutable="`which javac`"
- if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
- # readlink(1) is not available as standard on Solaris 10.
- readLink=`which readlink`
- if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
- if $darwin ; then
- javaHome="`dirname \"$javaExecutable\"`"
- javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
- else
- javaExecutable="`readlink -f \"$javaExecutable\"`"
- fi
- javaHome="`dirname \"$javaExecutable\"`"
- javaHome=`expr "$javaHome" : '\(.*\)/bin'`
- JAVA_HOME="$javaHome"
- export JAVA_HOME
- fi
- fi
-fi
-
-if [ -z "$JAVACMD" ] ; then
- if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- else
- JAVACMD="`which java`"
- fi
-fi
-
-if [ ! -x "$JAVACMD" ] ; then
- echo "Error: JAVA_HOME is not defined correctly." >&2
- echo " We cannot execute $JAVACMD" >&2
- exit 1
-fi
-
-if [ -z "$JAVA_HOME" ] ; then
- echo "Warning: JAVA_HOME environment variable is not set."
-fi
-
-CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
-
-# traverses directory structure from process work directory to filesystem root
-# first directory with .mvn subdirectory is considered project base directory
-find_maven_basedir() {
-
- if [ -z "$1" ]
- then
- echo "Path not specified to find_maven_basedir"
- return 1
- fi
-
- basedir="$1"
- wdir="$1"
- while [ "$wdir" != '/' ] ; do
- if [ -d "$wdir"/.mvn ] ; then
- basedir=$wdir
- break
- fi
- # workaround for JBEAP-8937 (on Solaris 10/Sparc)
- if [ -d "${wdir}" ]; then
- wdir=`cd "$wdir/.."; pwd`
- fi
- # end of workaround
- done
- echo "${basedir}"
-}
-
-# concatenates all lines of a file
-concat_lines() {
- if [ -f "$1" ]; then
- echo "$(tr -s '\n' ' ' < "$1")"
- fi
-}
-
-BASE_DIR=`find_maven_basedir "$(pwd)"`
-if [ -z "$BASE_DIR" ]; then
- exit 1;
-fi
-
-##########################################################################################
-# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
-# This allows using the maven wrapper in projects that prohibit checking in binary data.
-##########################################################################################
-if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Found .mvn/wrapper/maven-wrapper.jar"
- fi
-else
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
- fi
- if [ -n "$MVNW_REPOURL" ]; then
- jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
- else
- jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
- fi
- while IFS="=" read key value; do
- case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
- esac
- done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Downloading from: $jarUrl"
- fi
- wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
- if $cygwin; then
- wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
- fi
-
- if command -v wget > /dev/null; then
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Found wget ... using wget"
- fi
- if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
- wget "$jarUrl" -O "$wrapperJarPath"
- else
- wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
- fi
- elif command -v curl > /dev/null; then
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Found curl ... using curl"
- fi
- if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
- curl -o "$wrapperJarPath" "$jarUrl" -f
- else
- curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
- fi
-
- else
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Falling back to using Java to download"
- fi
- javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
- # For Cygwin, switch paths to Windows format before running javac
- if $cygwin; then
- javaClass=`cygpath --path --windows "$javaClass"`
- fi
- if [ -e "$javaClass" ]; then
- if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
- if [ "$MVNW_VERBOSE" = true ]; then
- echo " - Compiling MavenWrapperDownloader.java ..."
- fi
- # Compiling the Java class
- ("$JAVA_HOME/bin/javac" "$javaClass")
- fi
- if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
- # Running the downloader
- if [ "$MVNW_VERBOSE" = true ]; then
- echo " - Running MavenWrapperDownloader.java ..."
- fi
- ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
- fi
- fi
- fi
-fi
-##########################################################################################
-# End of extension
-##########################################################################################
-
-export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
-if [ "$MVNW_VERBOSE" = true ]; then
- echo $MAVEN_PROJECTBASEDIR
-fi
-MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin; then
- [ -n "$M2_HOME" ] &&
- M2_HOME=`cygpath --path --windows "$M2_HOME"`
- [ -n "$JAVA_HOME" ] &&
- JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
- [ -n "$CLASSPATH" ] &&
- CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
- [ -n "$MAVEN_PROJECTBASEDIR" ] &&
- MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
-fi
-
-# Provide a "standardized" way to retrieve the CLI args that will
-# work with both Windows and non-Windows executions.
-MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
-export MAVEN_CMD_LINE_ARGS
-
-WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
-
-exec "$JAVACMD" \
- $MAVEN_OPTS \
- -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
- "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
- ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
deleted file mode 100644
index 5ec13a2..0000000
--- a/mvnw.cmd
+++ /dev/null
@@ -1,187 +0,0 @@
-@REM ----------------------------------------------------------------------------
-@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements. See the NOTICE file
-@REM distributed with this work for additional information
-@REM regarding copyright ownership. The ASF licenses this file
-@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
-@REM with the License. You may obtain a copy of the License at
-@REM
-@REM http://www.apache.org/licenses/LICENSE-2.0
-@REM
-@REM Unless required by applicable law or agreed to in writing,
-@REM software distributed under the License is distributed on an
-@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-@REM KIND, either express or implied. See the License for the
-@REM specific language governing permissions and limitations
-@REM under the License.
-@REM ----------------------------------------------------------------------------
-
-@REM ----------------------------------------------------------------------------
-@REM Apache Maven Wrapper startup batch script, version 3.3.4
-@REM
-@REM Required ENV vars:
-@REM JAVA_HOME - location of a JDK home dir
-@REM
-@REM Optional ENV vars
-@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
-@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
-@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
-@REM e.g. to debug Maven itself, use
-@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
-@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
-@REM ----------------------------------------------------------------------------
-
-@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
-@echo off
-@REM set title of command window
-title %0
-@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
-@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
-
-@REM set %HOME% to equivalent of $HOME
-if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
-
-@REM Execute a user defined script before this one
-if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
-@REM check for pre script, once with legacy .bat ending and once with .cmd ending
-if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
-if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
-:skipRcPre
-
-@setlocal
-
-set ERROR_CODE=0
-
-@REM To isolate internal variables from possible post scripts, we use another setlocal
-@setlocal
-
-@REM ==== START VALIDATION ====
-if not "%JAVA_HOME%" == "" goto OkJHome
-
-echo.
-echo Error: JAVA_HOME not found in your environment. >&2
-echo Please set the JAVA_HOME variable in your environment to match the >&2
-echo location of your Java installation. >&2
-echo.
-goto error
-
-:OkJHome
-if exist "%JAVA_HOME%\bin\java.exe" goto init
-
-echo.
-echo Error: JAVA_HOME is set to an invalid directory. >&2
-echo JAVA_HOME = "%JAVA_HOME%" >&2
-echo Please set the JAVA_HOME variable in your environment to match the >&2
-echo location of your Java installation. >&2
-echo.
-goto error
-
-@REM ==== END VALIDATION ====
-
-:init
-
-@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
-@REM Fallback to current working directory if not found.
-
-set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
-IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
-
-set EXEC_DIR=%CD%
-set WDIR=%EXEC_DIR%
-:findBaseDir
-IF EXIST "%WDIR%"\.mvn goto baseDirFound
-cd ..
-IF "%WDIR%"=="%CD%" goto baseDirNotFound
-set WDIR=%CD%
-goto findBaseDir
-
-:baseDirNotFound
-set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
-cd "%EXEC_DIR%"
-goto endDetectBaseDir
-
-:baseDirFound
-set MAVEN_PROJECTBASEDIR=%WDIR%
-cd "%EXEC_DIR%"
-:endDetectBaseDir
-
-IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
-
-@setlocal EnableExtensions EnableDelayedExpansion
-for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG=!JVM_CONFIG! %%a
-@endlocal & set JVM_CONFIG=%JVM_CONFIG%
-
-:endReadAdditionalConfig
-
-SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
-set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
-set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
-
-set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar"
-
-FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
- IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
-)
-
-@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
-@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
-if exist %WRAPPER_JAR% (
- if "%MVNW_VERBOSE%" == "true" (
- echo Found %WRAPPER_JAR%
- )
-) else (
- if not "%MVNW_REPOURL%" == "" (
- SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar"
- )
- if "%MVNW_VERBOSE%" == "true" (
- echo Couldn't find %WRAPPER_JAR%, downloading it ...
- echo Downloading from: %WRAPPER_URL%
- )
-
- powershell -Command "&{"^
- "$webclient = new-object System.Net.WebClient;"^
- "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
- "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
- "}"^
- "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
- "}"
- if "%MVNW_VERBOSE%" == "true" (
- echo Finished downloading %WRAPPER_JAR%
- )
-)
-@REM End of extension
-
-%MAVEN_JAVA_EXE% ^
- %JVM_CONFIG% ^
- --add-opens=java.base/java.lang=ALL-UNNAMED ^
- --add-opens=java.base/java.util=ALL-UNNAMED ^
- --add-opens=java.base/java.util.concurrent=ALL-UNNAMED ^
- --add-opens=java.base/java.net=ALL-UNNAMED ^
- --add-opens=java.base/java.io=ALL-UNNAMED ^
- %MAVEN_OPTS% ^
- %MAVEN_DEBUG_OPTS% ^
- -classpath %WRAPPER_JAR% ^
- "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
- %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
-if ERRORLEVEL 1 goto error
-goto end
-
-:error
-set ERROR_CODE=1
-
-:end
-@endlocal & set ERROR_CODE=%ERROR_CODE%
-
-if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
-@REM check for post script, once with legacy .bat ending and once with .cmd ending
-if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
-if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
-:skipRcPost
-
-@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
-if "%MAVEN_BATCH_PAUSE%" == "on" pause
-
-if "%MAVEN_VERBOSE%" == "on" echo %ERROR_CODE%
-
-exit /B %ERROR_CODE%
\ No newline at end of file
diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000..c607e7b
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,22 @@
+server {
+ listen 80;
+ server_name localhost;
+ root /usr/share/nginx/html;
+ index index.html;
+
+ # Enable clean URLs without .html extension
+ location / {
+ # Try the exact URI, then with .html, then as directory with index.html, then 404
+ try_files $uri $uri.html $uri/ =404;
+ }
+
+ # Optional: Redirect .html URLs to clean URLs
+ if ($request_uri ~ ^/(.*)\.html(\?|$)) {
+ return 301 /$1$2;
+ }
+
+ # Gzip compression for better performance
+ gzip on;
+ gzip_vary on;
+ gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
+}
diff --git a/pom.xml b/pom.xml
index 25c1925..26824e9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,11 +162,11 @@
slf4j-api
2.0.9
-
+
org.junit.jupiter
@@ -342,6 +342,7 @@
+ ${project.basedir}/../build/${project.artifactId}
src/main/resources
diff --git a/scripts/BFG.ps1 b/scripts/BFG.ps1
deleted file mode 100644
index cf96738..0000000
--- a/scripts/BFG.ps1
+++ /dev/null
@@ -1,33 +0,0 @@
-# BFG.ps1 (run from C:\vibe\auctiora\scripts)
-$ErrorActionPreference = "Stop"
-
-# 1) Download BFG jar once, next to this script
-$bfgJar = Join-Path $PSScriptRoot "bfg.jar"
-if (-not (Test-Path $bfgJar)) {
- Invoke-WebRequest `
- "https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar" `
- -OutFile $bfgJar
-}
-
-# 2) Clone bare mirror next to project root: C:\vibe\auctiora\auctiora.git
-$rootDir = Join-Path $PSScriptRoot ".."
-$mirrorPath = Join-Path $rootDir "auctiora.git"
-
-if (Test-Path $mirrorPath) {
- Remove-Item $mirrorPath -Recurse -Force
-}
-
-git clone --mirror "https://git.appmodel.nl/Tour/auctiora.git" $mirrorPath
-
-# 3) Run BFG in mirror
-Push-Location $mirrorPath
-
-java -jar $bfgJar --strip-blobs-bigger-than 50M .
-
-git reflog expire --expire=now --all
-git gc --prune=now --aggressive
-
-# 4) Force-push cleaned history
-git push --force
-
-Pop-Location
diff --git a/scripts/README.md b/scripts/README.md
deleted file mode 100644
index 3dd20c5..0000000
--- a/scripts/README.md
+++ /dev/null
@@ -1,206 +0,0 @@
-# Auctiora Scripts
-
-Utility scripts for managing the Auctiora auction monitoring system.
-
-## 📦 Available Scripts
-
-### 1. Production Data Sync
-
-Sync production database and images from `athena.lan` to your local development environment.
-
-#### Quick Start
-
-**Linux/Mac (Bash)**:
-```bash
-# Make executable (first time only)
-chmod +x scripts/sync-production-data.sh
-
-# Sync database only
-./scripts/sync-production-data.sh --db-only
-
-# Sync everything
-./scripts/sync-production-data.sh --all
-
-# Sync images only
-./scripts/sync-production-data.sh --images-only
-```
-
-## 🔧 Prerequisites
-
-### Required
-- **SSH Client**: OpenSSH or equivalent
- - Windows: Built-in on Windows 10+, or install [Git Bash](https://git-scm.com/downloads)
- - Linux/Mac: Pre-installed
-- **SCP**: Secure copy (usually comes with SSH)
-- **SSH Access**: SSH key configured for `tour@athena.lan`
-
-### Optional
-- **rsync**: For efficient incremental image sync
- - Windows: Install via [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) or [Cygwin](https://www.cygwin.com/)
- - Linux/Mac: Usually pre-installed
-- **sqlite3**: For showing database statistics
- - Windows: Download from [sqlite.org](https://www.sqlite.org/download.html)
- - Linux: `sudo apt install sqlite3`
- - Mac: Pre-installed
-
-## 📊 What Gets Synced
-
-### Database (`cache.db`)
-- **Size**: ~8.9 GB (as of Dec 2024)
-- **Contains**:
- - Auctions metadata
- - Lots (kavels) with bid information
- - Images metadata and URLs
- - HTTP cache for scraper
-- **Local Path**: `c:\mnt\okcomputer\cache.db`
-
-### Images Directory
-- **Size**: Varies (can be large)
-- **Contains**:
- - Downloaded lot images
- - Organized by lot ID
-- **Local Path**: `c:\mnt\okcomputer\images\`
-
-## 🚀 Usage Examples
-
-## 📁 File Locations
-
-### Remote (Production)
-```
-athena.lan
-├── Docker Volume: shared-auction-data
-│ ├── /data/cache.db (SQLite database)
-│ └── /data/images/ (Image files)
-└── /tmp/ (Temporary staging area)
-```
-
-### Local (Development)
-```
-c:\mnt\okcomputer\
-├── cache.db (SQLite database)
-├── cache.db.backup-* (Automatic backups)
-└── images\ (Image files)
-```
-
-## 🔒 Safety Features
-
-### Automatic Backups
-- Existing local database is automatically backed up before sync
-- Backup format: `cache.db.backup-YYYYMMDD-HHMMSS`
-- Keep recent backups manually or clean up old ones
-
-### Confirmation Prompts
-- PowerShell script prompts for confirmation (unless `-Force` is used)
-- Shows configuration before executing
-- Safe to cancel at any time
-
-### Error Handling
-- Validates SSH connection before starting
-- Cleans up temporary files on remote server
-- Reports clear error messages
-
-## ⚡ Performance Tips
-
-### Faster Image Sync with rsync
-Install rsync for incremental image sync (only new/changed files):
-
-**Windows (WSL)**:
-```powershell
-wsl --install
-wsl -d Ubuntu
-sudo apt install rsync
-```
-
-**Windows (Chocolatey)**:
-```powershell
-choco install rsync
-```
-
-**Benefit**: First sync downloads everything, subsequent syncs only transfer changed files.
-
-Images can be synced separately when needed for image processing tests.
-
-## 🐛 Troubleshooting
-
-### SSH Connection Issues
-```powershell
-# Test SSH connection
-ssh tour@athena.lan "echo 'Connection OK'"
-
-# Check SSH key
-ssh-add -l
-```
-
-### Permission Denied
-```bash
-# Add SSH key (Linux/Mac)
-chmod 600 ~/.ssh/id_rsa
-ssh-add ~/.ssh/id_rsa
-
-# Windows: Use PuTTY or OpenSSH for Windows
-```
-
-### Database Locked Error
-```powershell
-# Make sure no other process is using the database
-Get-Process | Where-Object {$_.Path -like "*java*"} | Stop-Process
-
-# Or restart the monitor
-```
-
-### Slow Image Sync
-- Use rsync instead of scp (see Performance Tips)
-- Consider syncing only database for code development
-- Images only needed for object detection testing
-
-## 📝 Script Details
-
-### sync-production-data.sh (Bash)
-- **Platform**: Linux, Mac, Git Bash on Windows
-- **Best for**: Unix-like environments
-- **Features**: Color output, progress bars, statistics
-
-## 🔄 Automation
-
-### Linux/Mac Cron
-```bash
-# Edit crontab
-crontab -e
-
-# Add daily sync at 7 AM
-0 7 * * * /path/to/auctiora/scripts/sync-production-data.sh --db-only
-```
-
-## 🆘 Support
-
-### Getting Help
-```bash
-# Bash
-./scripts/sync-production-data.sh --help
-```
-
-### Common Commands
-```powershell
-# Check database size
-ls c:\mnt\okcomputer\cache.db -h
-
-# View database contents
-sqlite3 c:\mnt\okcomputer\cache.db
- .tables
- .schema lots
- SELECT COUNT(*) FROM lots;
- .quit
-
-# Check image count
-(Get-ChildItem c:\mnt\okcomputer\images -Recurse -File).Count
-```
-
-## 📚 Related Documentation
-- [Database Architecture](../wiki/DATABASE_ARCHITECTURE.md)
-- [Integration Flowchart](../docs/INTEGRATION_FLOWCHART.md)
-- [Main README](../README.md)
-
----
-
-**Last Updated**: December 2025
-**Maintainer**: Auctiora Development Team
diff --git a/scripts/cleanup-database.sh b/scripts/cleanup-database.sh
deleted file mode 100644
index 1f2c505..0000000
--- a/scripts/cleanup-database.sh
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/bin/bash
-#
-# Database Cleanup Utility
-#
-# Removes invalid/old data from the local database
-#
-# Usage:
-# ./scripts/cleanup-database.sh [--dry-run]
-#
-# Options:
-# --dry-run Show what would be deleted without actually deleting
-#
-
-set -e
-
-# Configuration
-LOCAL_DB_PATH="${1:-c:/mnt/okcomputer/cache.db}"
-DRY_RUN=false
-
-# Colors
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-RED='\033[0;31m'
-BLUE='\033[0;34m'
-NC='\033[0m'
-
-# Parse arguments
-if [ "$1" = "--dry-run" ] || [ "$2" = "--dry-run" ]; then
- DRY_RUN=true
-fi
-
-if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
- grep '^#' "$0" | sed 's/^# \?//'
- exit 0
-fi
-
-echo -e "${BLUE}╔════════════════════════════════════════════════════════╗${NC}"
-echo -e "${BLUE}║ Database Cleanup - Auctiora Monitor ║${NC}"
-echo -e "${BLUE}╚════════════════════════════════════════════════════════╝${NC}"
-echo ""
-
-if [ ! -f "${LOCAL_DB_PATH}" ]; then
- echo -e "${RED}Error: Database not found at ${LOCAL_DB_PATH}${NC}"
- exit 1
-fi
-
-# Backup database before cleanup
-if [ "$DRY_RUN" = false ]; then
- BACKUP_PATH="${LOCAL_DB_PATH}.backup-before-cleanup-$(date +%Y%m%d-%H%M%S)"
- echo -e "${YELLOW}Creating backup: ${BACKUP_PATH}${NC}"
- cp "${LOCAL_DB_PATH}" "${BACKUP_PATH}"
- echo ""
-fi
-
-# Show current state
-echo -e "${BLUE}Current database state:${NC}"
-sqlite3 "${LOCAL_DB_PATH}" </dev/null || true'"
-
- echo -e "${YELLOW}[3/4] Syncing images to local directory (this may take a while)...${NC}"
- # Use rsync for efficient incremental sync
- if command -v rsync &> /dev/null; then
- echo -e "${BLUE} Using rsync for efficient transfer...${NC}"
- rsync -avz --progress ${REMOTE_HOST}:${REMOTE_TMP}/auction-images/ "${LOCAL_IMAGES_PATH}/"
- else
- echo -e "${BLUE} Using scp for transfer (install rsync for faster incremental sync)...${NC}"
- scp -r ${REMOTE_HOST}:${REMOTE_TMP}/auction-images/* "${LOCAL_IMAGES_PATH}/"
- fi
-
- echo -e "${YELLOW}[4/4] Cleaning up remote /tmp...${NC}"
- ssh ${REMOTE_HOST} "rm -rf ${REMOTE_TMP}/auction-images"
-
- # Show image stats
- IMAGE_COUNT=$(find "${LOCAL_IMAGES_PATH}" -type f 2>/dev/null | wc -l)
- IMAGE_SIZE=$(du -sh "${LOCAL_IMAGES_PATH}" 2>/dev/null | cut -f1)
- echo -e "${GREEN}✓ Images synced successfully${NC}"
- echo -e "${BLUE} Total images: ${IMAGE_COUNT}${NC}"
- echo -e "${BLUE} Total size: ${IMAGE_SIZE}${NC}"
-}
-
-# Execute sync based on mode
-START_TIME=$(date +%s)
-
-case "$SYNC_MODE" in
- db)
- echo -e "${BLUE}Mode: Database only${NC}"
- echo ""
- sync_database
- ;;
- images)
- echo -e "${BLUE}Mode: Images only${NC}"
- echo ""
- sync_images
- ;;
- all)
- echo -e "${BLUE}Mode: Database + Images${NC}"
- echo ""
- sync_database
- echo ""
- sync_images
- ;;
-esac
-
-END_TIME=$(date +%s)
-DURATION=$((END_TIME - START_TIME))
-
-echo ""
-echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
-echo -e "${GREEN}║ Sync completed successfully in ${DURATION} seconds ║${NC}"
-echo -e "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
-echo ""
-echo -e "${BLUE}Next steps:${NC}"
-echo -e " 1. Verify data: sqlite3 ${LOCAL_DB_PATH} 'SELECT COUNT(*) FROM lots;'"
-echo -e " 2. Start monitor: mvn quarkus:dev"
-echo -e " 3. Open dashboard: http://localhost:8080"
-echo ""
diff --git a/src/main/java/auctiora/NotificationService.java b/src/main/java/auctiora/NotificationService.java
index 22d9514..773a9d0 100644
--- a/src/main/java/auctiora/NotificationService.java
+++ b/src/main/java/auctiora/NotificationService.java
@@ -14,6 +14,11 @@ import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.util.Date;
import java.util.Properties;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public record NotificationService(Config cfg) {
@@ -24,11 +29,26 @@ public record NotificationService(Config cfg) {
}
public void sendNotification(String msg, String title, int prio) {
- if (cfg.useDesktop()) sendDesktop(title, msg, prio);
if (cfg.useEmail()) sendEmail(title, msg, prio);
}
private void sendDesktop(String title, String msg, int prio) {
+ // During tests, aggregate and send a single summary at JVM shutdown
+ if (isUnderTest()) {
+ TestRunAggregator.recordDesktop(title, msg, prio, cfg);
+ return;
+ }
+ // Optional mute flag for non-test runs
+ if (Boolean.getBoolean("auctiora.desktop.mute")) {
+ log.debug("Desktop notification suppressed: {}", title);
+ return;
+ }
+ // Deliver immediately outside tests
+ deliverDesktop(title, msg, prio);
+ }
+
+ // Raw desktop delivery (no test suppression)
+ private void deliverDesktop(String title, String msg, int prio) {
try {
if (!SystemTray.isSupported()) {
log.info("Desktop not supported: {}", title);
@@ -79,6 +99,17 @@ public record NotificationService(Config cfg) {
}
private void sendEmail(String title, String msg, int prio) {
+ // During tests, aggregate and send a single summary at JVM shutdown
+ if (isUnderTest()) {
+ TestRunAggregator.recordEmail(title, msg, prio, cfg);
+ return;
+ }
+ // Deliver immediately outside tests
+ deliverEmail(title, msg, prio);
+ }
+
+ // Raw email delivery (no test suppression), returns when send attempted
+ private void deliverEmail(String title, String msg, int prio) {
SMTPTransport transport = null;
boolean sent = false;
try {
@@ -190,4 +221,72 @@ public record NotificationService(Config cfg) {
return false;
}
}
+
+ // Aggregates notifications during test runs and emits a single summary at shutdown
+ private static final class TestRunAggregator {
+ private static final AtomicBoolean HOOK_ADDED = new AtomicBoolean(false);
+ private static final List TITLES = Collections.synchronizedList(new ArrayList<>());
+ private static final List MESSAGES = Collections.synchronizedList(new ArrayList<>());
+ private static final AtomicInteger TOTAL = new AtomicInteger(0);
+ private static final AtomicInteger CRITICAL = new AtomicInteger(0);
+ private static volatile Config LAST_EMAIL_CFG;
+
+ static void recordDesktop(String title, String msg, int prio, Config cfg) {
+ record(title, msg, prio, cfg);
+ }
+
+ static void recordEmail(String title, String msg, int prio, Config cfg) {
+ LAST_EMAIL_CFG = cfg != null && cfg.useEmail() ? cfg : LAST_EMAIL_CFG;
+ record(title, msg, prio, cfg);
+ }
+
+ private static void record(String title, String msg, int prio, Config cfg) {
+ TOTAL.incrementAndGet();
+ if (prio > 0) CRITICAL.incrementAndGet();
+ TITLES.add(title != null ? title : "");
+ MESSAGES.add(msg != null ? msg : "");
+ registerShutdownHookOnce();
+ }
+
+ private static void registerShutdownHookOnce() {
+ if (HOOK_ADDED.compareAndSet(false, true)) {
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ try {
+ if (!isUnderTest()) return; // Only summarize during tests
+
+ int total = TOTAL.get();
+ int critical = CRITICAL.get();
+ StringBuilder sb = new StringBuilder();
+ sb.append("Notifications during tests: ").append(total)
+ .append(" total, ").append(critical).append(" critical");
+
+ // Include up to 3 sample titles
+ int limit = Math.min(3, TITLES.size());
+ if (limit > 0) {
+ sb.append("\nExamples:");
+ for (int i = 0; i < limit; i++) {
+ sb.append("\n - ").append(TITLES.get(i));
+ }
+ }
+
+ String summaryTitle = "Test run summary";
+ String summaryBody = sb.toString();
+
+ // One desktop summary
+ try {
+ new NotificationService("desktop").deliverDesktop(summaryTitle, summaryBody, critical > 0 ? 1 : 0);
+ } catch (Exception ignored) {}
+
+ // One email summary (if config available)
+ if (LAST_EMAIL_CFG != null && LAST_EMAIL_CFG.useEmail()) {
+ try {
+ new NotificationService(LAST_EMAIL_CFG).deliverEmail(summaryTitle, summaryBody, critical > 0 ? 1 : 0);
+ } catch (Exception ignored) {}
+ }
+ } catch (Exception ignored) {
+ }
+ }, "notify-summary"));
+ }
+ }
+ }
}
diff --git a/src/main/java/auctiora/db/AuctionRepository.java b/src/main/java/auctiora/db/AuctionRepository.java
index ccf6eec..b97bde2 100644
--- a/src/main/java/auctiora/db/AuctionRepository.java
+++ b/src/main/java/auctiora/db/AuctionRepository.java
@@ -104,10 +104,10 @@ public class AuctionRepository {
return jdbi.withHandle(handle ->
handle.createQuery("SELECT * FROM auctions")
.map((rs, ctx) -> {
- var closingStr = rs.getString("closing_time");
- LocalDateTime closingTime = auctiora.ScraperDataAdapter.parseTimestamp(closingStr);
-
- return new AuctionInfo(
+ var closingStr = rs.getString("closing_time");
+ var closingTime = auctiora.ScraperDataAdapter.parseTimestamp(closingStr);
+
+ return new AuctionInfo(
rs.getLong("auction_id"),
rs.getString("title"),
rs.getString("location"),