2024-04-26 23:18:02 +02:00
|
|
|
// Configuration and Messages
|
2024-04-27 01:13:00 +02:00
|
|
|
const debugEnabled = false
|
2024-04-26 23:18:02 +02:00
|
|
|
const mouseDebugEnabled = false
|
|
|
|
|
const zsrCheckEnabled = false
|
2024-04-27 13:43:10 +02:00
|
|
|
const interactionThreshold = 5 // Time in seconds
|
2024-04-26 23:18:02 +02:00
|
|
|
const interactionCountThreshold = 5 // Number of interactions
|
|
|
|
|
let botDetected = false
|
|
|
|
|
|
|
|
|
|
const messages = {
|
|
|
|
|
de: {
|
2024-04-19 00:10:40 +02:00
|
|
|
required: 'Bitte füllen Sie dieses Feld aus',
|
|
|
|
|
email: 'Bitte geben Sie eine gültige E-Mail-Adresse ein',
|
2024-04-26 23:18:02 +02:00
|
|
|
success: 'Die Bestellung wurde erfolgreich übermittelt!',
|
|
|
|
|
thankyou: 'Vielen Dank für Ihre Bestellung!',
|
|
|
|
|
zsrTooltip: 'Bitte geben Sie eine gültige ZSR-Nummer, oder "beantragt" ein.',
|
|
|
|
|
captcha: 'Geben Sie den angezeigten Captcha-Code ein',
|
|
|
|
|
captchaButton: 'Überprüfen',
|
|
|
|
|
},
|
|
|
|
|
fr: {
|
2024-04-19 00:10:40 +02:00
|
|
|
required: 'Veuillez remplir ce champ',
|
|
|
|
|
email: 'Veuillez saisir une adresse email valide',
|
2024-04-26 23:18:02 +02:00
|
|
|
success: 'La commande a bien été envoyée!',
|
|
|
|
|
thankyou: 'Merci de votre commande!',
|
|
|
|
|
zsrTooltip: 'Veuillez saisir une ZSR-Nummer valide, ou indiquer "demandé".',
|
|
|
|
|
captcha: 'Entrez le code Captcha affiché',
|
|
|
|
|
captchaButton: 'Vérifier',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DOM Selectors
|
|
|
|
|
const debugLabel = document.createElement('div')
|
|
|
|
|
const submitButton = document.getElementById('bestellformular-btn')
|
|
|
|
|
const form = document.querySelector('form#bestellformular')
|
|
|
|
|
const notification = document.getElementById('notification')
|
|
|
|
|
const zsrTooltip = document.getElementById('zsr-tooltip')
|
|
|
|
|
const honeypotInput1 = document.getElementById('age')
|
|
|
|
|
const honeypotInput2 = document.getElementById('hobbies')
|
|
|
|
|
const verifyEmailInput = document.getElementById('verify_email')
|
|
|
|
|
const emailInput = document.getElementById('email')
|
|
|
|
|
const textInputs = document.querySelectorAll('input[type="text"]')
|
|
|
|
|
const captcha = document.querySelectorAll('.captcha')
|
|
|
|
|
const captchaInput = document.querySelectorAll('.captcha-input')
|
|
|
|
|
const captchaVerifyButton = document.querySelectorAll('.captcha-verify')
|
2024-04-26 23:49:39 +02:00
|
|
|
const botBadge = document.createElement('div')
|
|
|
|
|
if (debugEnabled) {
|
|
|
|
|
botBadge.className = 'bot-badge'
|
|
|
|
|
document.body.appendChild(botBadge)
|
|
|
|
|
botBadge.setAttribute(
|
|
|
|
|
'style',
|
|
|
|
|
'position: fixed; top: 0; right: 0; z-index: 9999; background-color: red; color: white; font-weight: bold; height:20px; width:20px'
|
|
|
|
|
)
|
|
|
|
|
}
|
2024-04-26 23:18:02 +02:00
|
|
|
|
|
|
|
|
// Utility variables
|
|
|
|
|
let startTime = Date.now()
|
|
|
|
|
let interactionCount = 0
|
|
|
|
|
let userInteracted = false
|
|
|
|
|
let lastInteractionTime = null
|
|
|
|
|
const mousePositions = []
|
|
|
|
|
const interactionTimes = []
|
|
|
|
|
let isStraightLine = true
|
|
|
|
|
|
|
|
|
|
// Utility functions
|
|
|
|
|
function log(thing) {
|
|
|
|
|
console.log(thing)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getCurrentLangMessages() {
|
|
|
|
|
log(messages[document.documentElement.lang.split('-')[0]])
|
|
|
|
|
return messages[document.documentElement.lang.split('-')[0]]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setUserInteracted() {
|
|
|
|
|
const currentTime = Date.now()
|
|
|
|
|
if (lastInteractionTime) {
|
|
|
|
|
const timeDiff = (currentTime - lastInteractionTime) / 1000 // time in seconds
|
|
|
|
|
interactionTimes.push(timeDiff)
|
|
|
|
|
log('Time since last interaction: ' + timeDiff + ' seconds')
|
2024-04-19 00:10:40 +02:00
|
|
|
}
|
2024-04-26 23:18:02 +02:00
|
|
|
lastInteractionTime = currentTime
|
|
|
|
|
userInteracted = true
|
|
|
|
|
interactionCount++
|
2024-04-26 23:49:39 +02:00
|
|
|
checkForBotBehavior()
|
2024-04-26 23:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleMouseMove(event) {
|
|
|
|
|
mousePositions.push({ x: event.clientX, y: event.clientY })
|
|
|
|
|
if (debugEnabled && mouseDebugEnabled) log('Mouse Position:', { x: event.clientX, y: event.clientY })
|
|
|
|
|
|
|
|
|
|
if (mousePositions.length > 2) {
|
|
|
|
|
const len = mousePositions.length
|
|
|
|
|
const { x: x1, y: y1 } = mousePositions[len - 3]
|
|
|
|
|
const { x: x2, y: y2 } = mousePositions[len - 2]
|
|
|
|
|
const { x: x3, y: y3 } = mousePositions[len - 1]
|
|
|
|
|
|
|
|
|
|
// Calculate the area of the triangle formed by three consecutive points
|
|
|
|
|
const area = 0.5 * Math.abs(x1 * y2 + x2 * y3 + x3 * y1 - y1 * x2 - y2 * x3 - y3 * x1)
|
|
|
|
|
if (debugEnabled && mouseDebugEnabled) log('Triangle Area:', area)
|
|
|
|
|
|
|
|
|
|
if (area > 0.5) {
|
|
|
|
|
// Threshold for detecting non-straight line, adjust as needed
|
|
|
|
|
isStraightLine = false
|
|
|
|
|
if (debugEnabled && mouseDebugEnabled) log('Detected non-straight line movement.')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function validateZSRNumber(form) {
|
|
|
|
|
const zsrNumber = form.elements['zsr_nummer'].value
|
|
|
|
|
return /^\d+$|^beantragt$/i.test(zsrNumber)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkForBotBehavior() {
|
|
|
|
|
let timeSpent = (Date.now() - startTime) / 1000
|
|
|
|
|
botDetected =
|
|
|
|
|
!userInteracted ||
|
|
|
|
|
interactionCount === 0 ||
|
|
|
|
|
timeSpent < interactionThreshold ||
|
|
|
|
|
(isStraightLine && mousePositions.length > 0) ||
|
|
|
|
|
honeypotInput1.value !== '' ||
|
|
|
|
|
honeypotInput2.value !== '' ||
|
|
|
|
|
verifyEmailInput.value !== ''
|
|
|
|
|
if (debugEnabled)
|
2024-04-26 23:49:39 +02:00
|
|
|
if (!botDetected) {
|
|
|
|
|
botBadge.style.backgroundColor = 'green'
|
|
|
|
|
} else {
|
|
|
|
|
botBadge.style.backgroundColor = 'red'
|
|
|
|
|
}
|
|
|
|
|
console.log(
|
|
|
|
|
'Bot Detected: ' +
|
|
|
|
|
botDetected +
|
|
|
|
|
' userInteracted:' +
|
|
|
|
|
userInteracted +
|
|
|
|
|
' interactionCount:' +
|
|
|
|
|
interactionCount +
|
|
|
|
|
' timeSpent:' +
|
|
|
|
|
timeSpent +
|
|
|
|
|
' isStraightLine:' +
|
|
|
|
|
isStraightLine +
|
|
|
|
|
' mousePositions:' +
|
|
|
|
|
mousePositions.length +
|
|
|
|
|
' honeypotInput1:' +
|
|
|
|
|
honeypotInput1.value +
|
|
|
|
|
' honeypotInput2:' +
|
|
|
|
|
honeypotInput2.value +
|
|
|
|
|
' verifyEmailInput:' +
|
|
|
|
|
verifyEmailInput.value
|
|
|
|
|
)
|
2024-04-26 23:18:02 +02:00
|
|
|
}
|
|
|
|
|
function handleSubmit(e) {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
const currentMessages = getCurrentLangMessages()
|
|
|
|
|
|
|
|
|
|
if (zsrCheckEnabled && !validateZSRNumber(form)) {
|
|
|
|
|
zsrTooltip.className = 'input-tooltip visible'
|
|
|
|
|
zsrTooltip.setAttribute('data-tooltip', currentMessages.zsrTooltip)
|
|
|
|
|
zsrTooltip.scrollIntoView({
|
|
|
|
|
behavior: 'smooth',
|
|
|
|
|
block: 'center',
|
|
|
|
|
inline: 'nearest',
|
2024-04-20 12:13:44 +02:00
|
|
|
})
|
2024-04-26 23:18:02 +02:00
|
|
|
return
|
|
|
|
|
}
|
2024-04-20 12:13:44 +02:00
|
|
|
|
2024-04-26 23:18:02 +02:00
|
|
|
checkForBotBehavior()
|
2024-02-23 06:34:03 +00:00
|
|
|
|
2024-04-26 23:18:02 +02:00
|
|
|
const data = new FormData(form)
|
|
|
|
|
data.append('tra', botDetected)
|
|
|
|
|
fetch(form.action, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
mode: 'cors',
|
|
|
|
|
body: data,
|
|
|
|
|
})
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (!response.ok) throw new Error('Network response was not ok')
|
|
|
|
|
return response.json()
|
|
|
|
|
})
|
|
|
|
|
.then((data) => {
|
|
|
|
|
submitButton.disabled = true
|
|
|
|
|
submitButton.innerHTML = `
|
|
|
|
|
<svg class="svg-spin" fill="#ffffff" width="30px" height="30px" viewBox="0 0 9.6 9.6" id="Flat" xmlns="http://www.w3.org/2000/svg"><path d="M5.1 1.2v1.2a0.3 0.3 0 0 1 -0.6 0V1.2a0.3 0.3 0 0 1 0.6 0m3.3 3.3h-1.2a0.3 0.3 0 0 0 0 0.6h1.2a0.3 0.3 0 0 0 0 -0.6m-1.691 1.785a0.3 0.3 0 0 0 -0.424 0.424l0.849 0.849a0.3 0.3 0 1 0 0.424 -0.424ZM4.8 6.9a0.3 0.3 0 0 0 -0.3 0.3v1.2a0.3 0.3 0 0 0 0.6 0v-1.2a0.3 0.3 0 0 0 -0.3 -0.3m-1.909 -0.615L2.042 7.133a0.3 0.3 0 0 0 0.424 0.424l0.849 -0.849a0.3 0.3 0 0 0 -0.424 -0.424M2.7 4.8a0.3 0.3 0 0 0 -0.3 -0.3H1.2a0.3 0.3 0 0 0 0 0.6h1.2a0.3 0.3 0 0 0 0.3 -0.3m-0.233 -2.758a0.3 0.3 0 0 0 -0.424 0.424l0.849 0.849a0.3 0.3 0 0 0 0.424 -0.424Z"/></svg>
|
|
|
|
|
`
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
// if data.success is true, show a success message
|
|
|
|
|
if (data.success) {
|
|
|
|
|
submitButton.style.display = 'none'
|
|
|
|
|
notification.innerHTML = `<span>${currentMessages.thankyou}</span>`
|
|
|
|
|
notification.className = 'bg-green-500 text-white px-4 py-2 rounded block'
|
|
|
|
|
} else {
|
|
|
|
|
submitButton.style.display = 'none'
|
|
|
|
|
notification.textContent = data.message
|
|
|
|
|
notification.className = 'bg-blue-500 text-white px-4 py-2 rounded block'
|
|
|
|
|
}
|
|
|
|
|
}, 3000)
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
submitButton.style.display = 'none'
|
|
|
|
|
notification.textContent = 'Fehler beim Senden der Nachricht.'
|
|
|
|
|
notification.className = 'bg-blue-500 text-white px-4 py-2 rounded block'
|
|
|
|
|
console.error(error)
|
|
|
|
|
})
|
|
|
|
|
}
|
2024-04-19 00:10:40 +02:00
|
|
|
|
2024-04-26 23:18:02 +02:00
|
|
|
function init() {
|
|
|
|
|
// Event Listeners
|
2024-04-19 00:10:40 +02:00
|
|
|
document.addEventListener('mousedown', setUserInteracted)
|
|
|
|
|
document.addEventListener('touchstart', setUserInteracted)
|
|
|
|
|
document.addEventListener('keydown', setUserInteracted)
|
2024-04-26 23:18:02 +02:00
|
|
|
document.addEventListener('mousemove', handleMouseMove)
|
|
|
|
|
form.addEventListener('submit', handleSubmit)
|
|
|
|
|
emailInput.addEventListener('invalid', () => {
|
|
|
|
|
const currentMessages = getCurrentLangMessages()
|
|
|
|
|
emailInput.setCustomValidity(currentMessages.email)
|
|
|
|
|
})
|
|
|
|
|
textInputs.forEach((input) => {
|
|
|
|
|
input.addEventListener('invalid', () => {
|
|
|
|
|
const currentMessages = getCurrentLangMessages()
|
|
|
|
|
input.setCustomValidity(currentMessages.required)
|
2024-04-19 00:10:40 +02:00
|
|
|
})
|
|
|
|
|
})
|
2024-04-26 23:18:02 +02:00
|
|
|
log('captchaInput', captchaInput)
|
|
|
|
|
captchaInput?.forEach((input) => {
|
|
|
|
|
input.setAttribute('placeholder', getCurrentLangMessages().captcha)
|
|
|
|
|
})
|
|
|
|
|
captchaVerifyButton?.forEach((button) => {
|
|
|
|
|
button.textContent = getCurrentLangMessages().captchaButton
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
|
init()
|
2024-04-19 00:10:40 +02:00
|
|
|
})
|