scan-alert-hardening: different-finder re-alert within 250m window + fingerprint 24h block (12/12 scenarios pass)

This commit is contained in:
2026-08-07 17:29:47 +10:00
parent f646af3ec6
commit 61737825ea
9 changed files with 140 additions and 33 deletions

View File

@@ -63,6 +63,7 @@
<div id="contact-area" class="mt-4">
<form hx-post="/t/{{.Data.TagCode}}/contact" hx-target="#contact-area" hx-swap="innerHTML" class="flex gap-2">
<input type="hidden" name="fingerprint" value="">
<input name="phone" type="tel" placeholder="Leave your number for the owner (optional)" class="flex-1 rounded border border-stone-300 px-3 py-2 text-sm" pattern="[0-9+ ]{8,16}">
<button type="submit" class="rounded bg-stone-900 px-4 py-2 text-sm font-semibold text-white hover:bg-stone-700">Send number</button>
</form>
@@ -78,11 +79,24 @@
(function () {
var code = {{.Data.TagCode | printf "%q"}};
var btn = document.getElementById("recheck-btn");
// Lightweight anti-spam fingerprint (UA/language/timezone/screen/platform hash).
function fingerprint() {
var parts = [navigator.userAgent, navigator.language, new Date().getTimezoneOffset(),
screen.width + "x" + screen.height, navigator.platform || "", navigator.hardwareConcurrency || ""];
return parts.join("|").split("").reduce(function (h, c) {
return ((h << 5) - h + c.charCodeAt(0)) | 0;
}, 0).toString(36);
}
var fp = fingerprint();
var fpInput = document.querySelector('input[name="fingerprint"]');
if (fpInput) fpInput.value = fp;
function sendScan(lat, lng) {
var body = {fingerprint: fp};
if (lat != null) { body.lat = lat; body.lng = lng; }
fetch("/t/" + code + "/scan", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(lat != null ? {lat: lat, lng: lng} : {})
body: JSON.stringify(body)
});
}
function tryLocation() {