aktualizacja struktury katalogów i dodanie mimifikacji

This commit is contained in:
mateusz779 2024-11-07 01:39:39 +01:00
parent 8c68b7a2e8
commit 400620946a
8 changed files with 324 additions and 328 deletions

View File

@ -1,27 +1,25 @@
# Author:Mateusz Kędziora https://mkedziora.pl # Author:Mateusz Kędziora https://mkedziora.pl
FROM golang:1.23.2-alpine AS builder FROM golang:1.23.2-alpine AS builder
WORKDIR /app WORKDIR /app
COPY go.mod go.sum* ./ COPY go.mod go.sum* ./
RUN go mod download RUN go mod download
COPY *.go ./ COPY *.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -o main . RUN CGO_ENABLED=0 GOOS=linux go build -o main .
# Etap minifikacji
FROM node:alpine AS minifier
WORKDIR /app
RUN npm install -g minify
COPY public/ ./public/
RUN find ./public -name "*.html" -exec minify -o {} {} \;
RUN find ./public/css -name "*.css" -exec minify -o {} {} \;
RUN find ./public/js -name "*.js" -exec minify -o {} {} \;
FROM alpine:latest FROM alpine:latest
RUN apk --no-cache add ca-certificates RUN apk --no-cache add ca-certificates
WORKDIR /root/ WORKDIR /root/
COPY --from=builder /app/main . COPY --from=builder /app/main .
COPY --from=minifier /app/public/ ./public/
COPY public/ ./public
EXPOSE 8000 EXPOSE 8000
CMD ["./main"] CMD ["./main"]

16
main.go
View File

@ -132,12 +132,20 @@ func main() {
http.ServeFile(w, r, "public/app.html") http.ServeFile(w, r, "public/app.html")
}) })
http.HandleFunc("/style_index.css", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/css/index.css", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/style_index.css") http.ServeFile(w, r, "public/css/index.css")
}) })
http.HandleFunc("/style_app.css", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/css/app.css", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/style_app.css") http.ServeFile(w, r, "public/css/app.css")
})
http.HandleFunc("/js/index.js", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/js/index.js")
})
http.HandleFunc("/js/app.js", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/js/app.js")
}) })
go func() { go func() {

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>App</title> <title>App</title>
<meta name="robots" content="noindex" /> <meta name="robots" content="noindex" />
<link href="/style_app.css" rel="stylesheet" /> <link href="/css/app.css" rel="stylesheet" />
</head> </head>
<body> <body>
<div class="container"> <div class="container">
@ -14,74 +14,6 @@
<a href="" id="url" rel="noopener noreferrer" target="_blank"></a> <a href="" id="url" rel="noopener noreferrer" target="_blank"></a>
<button id="startBtn">Start listening</button> <button id="startBtn">Start listening</button>
</div> </div>
<script> <script src="/js/app.js"></script>
let lastData = "";
// Pobieranie parametru id z URL
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get("id");
let new_url = "";
let fetchingData;
let newWindow;
document
.getElementById("startBtn")
.addEventListener("click", function () {
document.getElementById("info").textContent =
"Waiting for a new address...";
newWindow = window.open("about:blank", "_blank", "");
fetchingData = setInterval(checkForNewAddress, 1000);
});
function checkForNewAddress() {
// Dodanie parametru id do URL zapytania
const apiUrl = id
? `/api/get?id=${encodeURIComponent(id)}`
: "/api/get";
fetch(apiUrl, {
method: "GET",
headers: {
"Cache-Control": "no-cache",
Pragma: "no-cache",
},
})
.then((response) => {
if (!response.ok) {
throw new Error("Brak danych");
}
return response.json();
})
.then((data) => {
if (data.data && data.data !== lastData) {
lastData = data.data;
console.log("Nowy adres:", data.data);
// Przejście do nowego adresu z resetowaniem nagłówków
const url = new URL(data.data);
const a = document.getElementById("url");
a.href = url;
a.textContent = url;
console.log(newWindow);
if (newWindow) {
console.log("ustawiono nowy adres");
newWindow.location.href = id
? `/api/url?id=${encodeURIComponent(id)}`
: "/api/url";
}
document.getElementById("info").textContent =
"The page has opened; if not, click the link below. Link waiting is disabled.";
clearInterval(fetchingData);
}
})
.catch((error) => {
console.error("Błąd:", error);
});
}
// Sprawdzaj co sekundę
</script>
</body> </body>
</html> </html>

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex" /> <meta name="robots" content="noindex" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js"></script>
<link href="/style_index.css" rel="stylesheet" /> <link href="/css/index.css" rel="stylesheet" />
</head> </head>
<body> <body>
<div class="controls"> <div class="controls">
@ -56,246 +56,6 @@
<div id="status"></div> <div id="status"></div>
<script> <script src="/js/index.js"></script>
let currentStream = null;
let html5QrcodeScanner = null;
const statusDiv = document.getElementById("status");
const startButton = document.getElementById("startButton");
const stopButton = document.getElementById("stopButton");
const submitUrlButton = document.getElementById("submitUrl");
const manualUrlInput = document.getElementById("manualUrl");
// Funkcja do obsługi i wyświetlania błędów
function handleError(error) {
console.error("Wystąpił błąd:", error);
let errorMessage = "Wystąpił nieoczekiwany błąd.";
if (error instanceof Error) {
switch (error.name) {
case "NotAllowedError":
errorMessage =
"Dostęp do kamery został zabroniony. Sprawdź ustawienia przeglądarki.";
break;
case "NotFoundError":
errorMessage =
"Nie znaleziono kamery. Sprawdź czy urządzenie ma kamerę.";
break;
case "NotReadableError":
errorMessage =
"Kamera jest obecnie używana przez inną aplikację.";
break;
case "OverconstrainedError":
errorMessage =
"Nie znaleziono odpowiedniej kamery. Spróbuj ponownie.";
break;
default:
errorMessage =
error.message ||
"Wystąpił problem z kamerą. Spróbuj odświeżyć stronę.";
}
}
statusDiv.textContent = errorMessage;
return errorMessage;
}
async function sendUrl(url) {
try {
statusDiv.textContent = "Wysyłanie danych...";
const id = document.getElementById("idInput").value.trim();
const expire = document.getElementById("expireInput").value.trim();
const body = { value: url };
if (id) body.id = id;
if (expire) body.expire = expire;
const response = await fetch("/api/set", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (response.ok) {
statusDiv.textContent = "Sukces! URL został przesłany.";
return true;
} else {
throw new Error("Błąd podczas wysyłania danych na serwer");
}
} catch (error) {
handleError(error);
return false;
}
}
async function stopScanner() {
try {
if (html5QrcodeScanner) {
await html5QrcodeScanner.stop();
html5QrcodeScanner.clear();
html5QrcodeScanner = null;
}
if (currentStream) {
const tracks = currentStream.getTracks();
tracks.forEach((track) => {
if (track.readyState === "live") {
track.stop();
}
});
currentStream = null;
}
document.querySelector(".zoom-control").style.display = "none";
startButton.style.display = "block";
stopButton.style.display = "none";
const readerElement = document.getElementById("reader");
if (readerElement) {
readerElement.innerHTML = "";
}
} catch (error) {
handleError(error);
}
}
startButton.addEventListener("click", async function () {
const zoomControl = document.querySelector(".zoom-control");
const zoomSlider = document.getElementById("zoomSlider");
const zoomValue = document.querySelector(".zoom-value");
try {
// Najpierw zatrzymaj poprzedni skaner
await stopScanner();
// Poczekaj chwilę przed ponownym uruchomieniem
await new Promise((resolve) => setTimeout(resolve, 500));
// Sprawdź dostępne urządzenia
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter(
(device) => device.kind === "videoinput"
);
if (videoDevices.length === 0) {
throw new Error("Nie znaleziono żadnej kamery w urządzeniu");
}
// Preferuj tylną kamerę
const camera =
videoDevices.find(
(device) =>
device.label.toLowerCase().includes("back") ||
device.label.toLowerCase().includes("tylna")
) || videoDevices[videoDevices.length - 1];
const stream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: camera.deviceId,
facingMode: { ideal: "environment" },
},
});
currentStream = stream;
const track = stream.getVideoTracks()[0];
if (!track) {
throw new Error("Nie udało się uzyskać dostępu do kamery");
}
// Sprawdź możliwości kamery
const capabilities = track.getCapabilities();
if (capabilities && capabilities.zoom) {
zoomControl.style.display = "block";
zoomSlider.min = capabilities.zoom.min;
zoomSlider.max = capabilities.zoom.max;
zoomSlider.step =
(capabilities.zoom.max - capabilities.zoom.min) / 100;
zoomSlider.value = capabilities.zoom.min;
zoomValue.textContent = `${capabilities.zoom.min}x`;
zoomSlider.addEventListener("input", async (e) => {
try {
const zoomValue = parseFloat(e.target.value);
await track.applyConstraints({
advanced: [{ zoom: zoomValue }],
});
document.querySelector(
".zoom-value"
).textContent = `${zoomValue.toFixed(1)}x`;
} catch (error) {
console.warn("Nie udało się ustawić zoomu:", error);
}
});
} else {
zoomControl.style.display = "none";
}
html5QrcodeScanner = new Html5Qrcode("reader");
const qrConfig = {
fps: 10,
qrbox: { width: 250, height: 250 },
aspectRatio: 1.0,
};
startButton.style.display = "none";
stopButton.style.display = "block";
statusDiv.textContent = "Skaner jest aktywny...";
await html5QrcodeScanner.start(
{ facingMode: "environment" },
qrConfig,
async (decodedText) => {
await stopScanner();
if (await sendUrl(decodedText)) {
manualUrlInput.value = decodedText;
}
},
(error) => {
// Ignorujemy błędy skanowania, bo pojawiają się często gdy nie ma kodu QR w kadrze
console.debug("Skanowanie:", error);
}
);
} catch (error) {
await stopScanner();
handleError(error);
}
});
stopButton.addEventListener("click", stopScanner);
window.addEventListener("beforeunload", stopScanner);
document.addEventListener("visibilitychange", () => {
if (document.hidden && html5QrcodeScanner) {
stopScanner();
}
});
submitUrlButton.addEventListener("click", async () => {
const url = manualUrlInput.value.trim();
if (!url) {
statusDiv.textContent = "Proszę wprowadzić URL";
return;
}
try {
new URL(url); // Sprawdź poprawność URL
await sendUrl(url);
} catch (error) {
if (error instanceof TypeError) {
statusDiv.textContent = "Wprowadzony URL jest nieprawidłowy";
} else {
handleError(error);
}
}
});
manualUrlInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
submitUrlButton.click();
}
});
</script>
</body> </body>
</html> </html>

58
public/js/app.js Normal file
View File

@ -0,0 +1,58 @@
let lastData = "";
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get("id");
let new_url = "";
let fetchingData;
let newWindow;
document.getElementById("startBtn").addEventListener("click", function () {
document.getElementById("info").textContent = "Waiting for a new address...";
newWindow = window.open("about:blank", "_blank", "");
fetchingData = setInterval(checkForNewAddress, 1000);
});
function checkForNewAddress() {
// Dodanie parametru id do URL zapytania
const apiUrl = id ? `/api/get?id=${encodeURIComponent(id)}` : "/api/get";
fetch(apiUrl, {
method: "GET",
headers: {
"Cache-Control": "no-cache",
Pragma: "no-cache",
},
})
.then((response) => {
if (!response.ok) {
throw new Error("Brak danych");
}
return response.json();
})
.then((data) => {
if (data.data && data.data !== lastData) {
lastData = data.data;
console.log("Nowy adres:", data.data);
// Przejście do nowego adresu z resetowaniem nagłówków
const url = new URL(data.data);
const a = document.getElementById("url");
a.href = url;
a.textContent = url;
console.log(newWindow);
if (newWindow) {
console.log("ustawiono nowy adres");
newWindow.location.href = id
? `/api/url?id=${encodeURIComponent(id)}`
: "/api/url";
}
document.getElementById("info").textContent =
"The page has opened; if not, click the link below. Link waiting is disabled.";
clearInterval(fetchingData);
}
})
.catch((error) => {
console.error("Błąd:", error);
});
}

240
public/js/index.js Normal file
View File

@ -0,0 +1,240 @@
let currentStream = null;
let html5QrcodeScanner = null;
const statusDiv = document.getElementById("status");
const startButton = document.getElementById("startButton");
const stopButton = document.getElementById("stopButton");
const submitUrlButton = document.getElementById("submitUrl");
const manualUrlInput = document.getElementById("manualUrl");
const urlParams = new URLSearchParams(window.location.search);
const idParam = urlParams.get("id");
document.getElementById("idInput").value = idParam || "";
// Funkcja do obsługi i wyświetlania błędów
function handleError(error) {
console.error("Wystąpił błąd:", error);
let errorMessage = "Wystąpił nieoczekiwany błąd.";
if (error instanceof Error) {
switch (error.name) {
case "NotAllowedError":
errorMessage =
"Dostęp do kamery został zabroniony. Sprawdź ustawienia przeglądarki.";
break;
case "NotFoundError":
errorMessage =
"Nie znaleziono kamery. Sprawdź czy urządzenie ma kamerę.";
break;
case "NotReadableError":
errorMessage = "Kamera jest obecnie używana przez inną aplikację.";
break;
case "OverconstrainedError":
errorMessage = "Nie znaleziono odpowiedniej kamery. Spróbuj ponownie.";
break;
default:
errorMessage =
error.message ||
"Wystąpił problem z kamerą. Spróbuj odświeżyć stronę.";
}
}
statusDiv.textContent = errorMessage;
return errorMessage;
}
async function sendUrl(url) {
try {
statusDiv.textContent = "Wysyłanie danych...";
const id = document.getElementById("idInput").value.trim();
const expire = document.getElementById("expireInput").value.trim();
const body = { value: url };
if (id) body.id = id;
if (expire) body.expire = expire;
const response = await fetch("/api/set", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (response.ok) {
statusDiv.textContent = "Sukces! URL został przesłany.";
return true;
} else {
throw new Error("Błąd podczas wysyłania danych na serwer");
}
} catch (error) {
handleError(error);
return false;
}
}
async function stopScanner() {
try {
if (html5QrcodeScanner) {
await html5QrcodeScanner.stop();
html5QrcodeScanner.clear();
html5QrcodeScanner = null;
}
if (currentStream) {
const tracks = currentStream.getTracks();
tracks.forEach((track) => {
if (track.readyState === "live") {
track.stop();
}
});
currentStream = null;
}
document.querySelector(".zoom-control").style.display = "none";
startButton.style.display = "block";
stopButton.style.display = "none";
const readerElement = document.getElementById("reader");
if (readerElement) {
readerElement.innerHTML = "";
}
} catch (error) {
handleError(error);
}
}
startButton.addEventListener("click", async function () {
const zoomControl = document.querySelector(".zoom-control");
const zoomSlider = document.getElementById("zoomSlider");
const zoomValue = document.querySelector(".zoom-value");
try {
// Najpierw zatrzymaj poprzedni skaner
await stopScanner();
// Poczekaj chwilę przed ponownym uruchomieniem
await new Promise((resolve) => setTimeout(resolve, 500));
// Sprawdź dostępne urządzenia
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter(
(device) => device.kind === "videoinput"
);
if (videoDevices.length === 0) {
throw new Error("Nie znaleziono żadnej kamery w urządzeniu");
}
// Preferuj tylną kamerę
const camera =
videoDevices.find(
(device) =>
device.label.toLowerCase().includes("back") ||
device.label.toLowerCase().includes("tylna")
) || videoDevices[videoDevices.length - 1];
const stream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: camera.deviceId,
facingMode: { ideal: "environment" },
},
});
currentStream = stream;
const track = stream.getVideoTracks()[0];
if (!track) {
throw new Error("Nie udało się uzyskać dostępu do kamery");
}
// Sprawdź możliwości kamery
const capabilities = track.getCapabilities();
if (capabilities && capabilities.zoom) {
zoomControl.style.display = "block";
zoomSlider.min = capabilities.zoom.min;
zoomSlider.max = capabilities.zoom.max;
zoomSlider.step = (capabilities.zoom.max - capabilities.zoom.min) / 100;
zoomSlider.value = capabilities.zoom.min;
zoomValue.textContent = `${capabilities.zoom.min}x`;
zoomSlider.addEventListener("input", async (e) => {
try {
const zoomValue = parseFloat(e.target.value);
await track.applyConstraints({
advanced: [{ zoom: zoomValue }],
});
document.querySelector(
".zoom-value"
).textContent = `${zoomValue.toFixed(1)}x`;
} catch (error) {
console.warn("Nie udało się ustawić zoomu:", error);
}
});
} else {
zoomControl.style.display = "none";
}
html5QrcodeScanner = new Html5Qrcode("reader");
const qrConfig = {
fps: 10,
qrbox: { width: 250, height: 250 },
aspectRatio: 1.0,
};
startButton.style.display = "none";
stopButton.style.display = "block";
statusDiv.textContent = "Skaner jest aktywny...";
await html5QrcodeScanner.start(
{ facingMode: "environment" },
qrConfig,
async (decodedText) => {
await stopScanner();
if (await sendUrl(decodedText)) {
manualUrlInput.value = decodedText;
}
},
(error) => {
// Ignorujemy błędy skanowania, bo pojawiają się często gdy nie ma kodu QR w kadrze
console.debug("Skanowanie:", error);
}
);
} catch (error) {
await stopScanner();
handleError(error);
}
});
stopButton.addEventListener("click", stopScanner);
window.addEventListener("beforeunload", stopScanner);
document.addEventListener("visibilitychange", () => {
if (document.hidden && html5QrcodeScanner) {
stopScanner();
}
});
submitUrlButton.addEventListener("click", async () => {
const url = manualUrlInput.value.trim();
if (!url) {
statusDiv.textContent = "Proszę wprowadzić URL";
return;
}
try {
new URL(url); // Sprawdź poprawność URL
await sendUrl(url);
} catch (error) {
if (error instanceof TypeError) {
statusDiv.textContent = "Wprowadzony URL jest nieprawidłowy";
} else {
handleError(error);
}
}
});
manualUrlInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
submitUrlButton.click();
}
});