Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
83144471eb | |||
74198b6b04 | |||
0d4014c07a | |||
912a0eb6d5 | |||
22d217f13c | |||
aed8f6f856 | |||
299cadb278 | |||
6a468cd718 | |||
85822fefa2 | |||
8b75a1a156 | |||
ff9f9847b4 | |||
0290ff5f36 |
BIN
2025-01-12_11-42.jpeg
Normal file
After Width: | Height: | Size: 7.8 KiB |
@ -29,6 +29,8 @@ COPY --from=builder /app/ek-suche /app/ek-suche
|
||||
|
||||
# Kopiere die index.html und den public-Ordner vom Builder
|
||||
COPY --from=builder /app/index.html /app/index.html
|
||||
COPY --from=builder /app/popup.html /app/popup.html
|
||||
COPY --from=builder /app/public/ /app/public/
|
||||
|
||||
|
||||
# Stelle sicher, dass die Anwendung ausführbar ist
|
||||
|
555
index.html
94
main.go
@ -14,8 +14,6 @@ var serverConfig = map[string]string{
|
||||
"serverURL": os.Getenv("SERVER_URL"),
|
||||
}
|
||||
|
||||
var secret = os.Getenv("SECRET")
|
||||
|
||||
func main() {
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
@ -23,19 +21,38 @@ func main() {
|
||||
}
|
||||
|
||||
// Set up routes
|
||||
http.HandleFunc("/", handleRoot)
|
||||
http.HandleFunc("/config", handleConfig)
|
||||
http.HandleFunc("/login", handleLogin)
|
||||
http.HandleFunc("/search", handleSearch)
|
||||
http.HandleFunc("/favicon.ico", handleFavicon)
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", handleRoot)
|
||||
mux.HandleFunc("/config", handleConfig)
|
||||
mux.HandleFunc("/popup", handlePopupInstructions)
|
||||
mux.HandleFunc("/search", handleSearch)
|
||||
mux.HandleFunc("/favicon.ico", handleFavicon)
|
||||
|
||||
// Serve static files from 'public' directory
|
||||
fs := http.FileServer(http.Dir("./public"))
|
||||
http.Handle("/public/", http.StripPrefix("/public/", fs))
|
||||
mux.Handle("/public/", http.StripPrefix("/public/", fs))
|
||||
|
||||
// Wende die Sicherheitsheader-Middleware auf alle Routen an
|
||||
secureMux := secureHeaders(mux)
|
||||
|
||||
// Start the server
|
||||
log.Printf("Server is running at http://0.0.0.0:%s\n", port)
|
||||
log.Fatal(http.ListenAndServe("0.0.0.0:"+port, nil))
|
||||
log.Fatal(http.ListenAndServe("0.0.0.0:"+port, secureMux))
|
||||
}
|
||||
|
||||
// Middleware für Sicherheitsheader
|
||||
func secureHeaders(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Setze die Sicherheitsheader
|
||||
w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self';")
|
||||
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("X-Frame-Options", "DENY")
|
||||
w.Header().Set("X-XSS-Protection", "1; mode=block")
|
||||
|
||||
// Führe den nächsten Handler aus
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func handleRoot(w http.ResponseWriter, r *http.Request) {
|
||||
@ -50,30 +67,6 @@ func handleConfig(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{"serverIP":"%s","serverURL":"%s"}`, serverConfig["serverIP"], serverConfig["serverURL"])
|
||||
}
|
||||
|
||||
func handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPost {
|
||||
username := r.FormValue("username")
|
||||
password := r.FormValue("password")
|
||||
|
||||
if username == os.Getenv("USER") && password == os.Getenv("PASSWORD") {
|
||||
http.Redirect(w, r, "/stats", http.StatusSeeOther)
|
||||
} else {
|
||||
http.Error(w, "Ungültiges Passwort oder Benutzername", http.StatusForbidden)
|
||||
}
|
||||
} else {
|
||||
// Show login form
|
||||
tmpl := `
|
||||
<form action="/login" method="post">
|
||||
<label for="username">Benutzername:</label><br>
|
||||
<input type="text" id="username" name="username"><br>
|
||||
<label for="password">Passwort:</label><br>
|
||||
<input type="password" id="password" name="password"><br>
|
||||
<input type="submit" value="Anmelden">
|
||||
</form>`
|
||||
fmt.Fprint(w, tmpl)
|
||||
}
|
||||
}
|
||||
|
||||
func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query().Get("query")
|
||||
websites := r.URL.Query()["websites"]
|
||||
@ -101,12 +94,20 @@ func handleFavicon(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func handlePopupInstructions(w http.ResponseWriter, r *http.Request) {
|
||||
tmpl := template.Must(template.ParseFiles("popup.html"))
|
||||
if err := tmpl.Execute(w, nil); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func generateSearchUrl(website, query string) string {
|
||||
searchUrls := map[string]string{
|
||||
// ----- Eletronik ----
|
||||
"conrad": fmt.Sprintf("https://www.conrad.de/de/search.html?search=%s", query),
|
||||
"reichelt": fmt.Sprintf("https://www.reichelt.de/index.html?ACTION=446&SEARCH=%s", query),
|
||||
"kosatec": fmt.Sprintf("https://shop.kosatec.de/search?search=%s", query),
|
||||
"conrad": fmt.Sprintf("https://www.conrad.de/de/search.html?search=%s", query),
|
||||
"reichelt": fmt.Sprintf("https://www.reichelt.de/index.html?ACTION=446&SEARCH=%s", query),
|
||||
"kosatec": fmt.Sprintf("https://shop.kosatec.de/search?search=%s", query),
|
||||
"schreiber": fmt.Sprintf("https://www.schreiber-electronics.de/search?sSearch=%s", query),
|
||||
// ----- Verpackungen ------
|
||||
"papstar": fmt.Sprintf("https://www.papstar-shop.de/catalogsearch/result/?q=%s", query),
|
||||
|
||||
@ -116,14 +117,9 @@ func generateSearchUrl(website, query string) string {
|
||||
"fkr": fmt.Sprintf("https://shop.fkr-baucentrum.de/suche/?q=%s", query),
|
||||
"contorion": fmt.Sprintf("https://www.contorion.de/search?q=%s", query),
|
||||
"esska": fmt.Sprintf("https://www.esska.de/shop/search/%s", query),
|
||||
"toolineo": fmt.Sprintf("https://toolineo.de/#search:query=%s", query),
|
||||
"voelkner": fmt.Sprintf("https://www.voelkner.de/search/search.html?keywords=%s", query),
|
||||
"megabad": fmt.Sprintf("https://www.megabad.com/search/?query=sdyc/#/q/%s", query),
|
||||
//knauss: "https://knauss.info/dksearch?sSearch=${query}"",
|
||||
"baubeschlag": fmt.Sprintf("https://www.baubeschlagshop.de/fts.php?criteria=%s", query),
|
||||
"ips": fmt.Sprintf("https://www.ips-kts.com/de/suche?query=%s", query),
|
||||
"haefele": fmt.Sprintf("https://www.haefele.de/prod-live/web/WFS/Haefele-HDE-Site/de_DE/-/EUR/ViewParametricSearch-Browse?SearchTerm=%s", query),
|
||||
"delker": fmt.Sprintf("https://www.delker2business.com/nwsearch/execute?query=%s", query),
|
||||
"haefele": fmt.Sprintf("https://www.haefele.de/prod-live/web/WFS/Haefele-HDE-Site/de_DE/-/EUR/ViewParametricSearch-Browse?SearchTerm=%s", query),
|
||||
|
||||
// ------ Küche --------
|
||||
"esmeyer": fmt.Sprintf("https://www.esmeyer-shop.de/search?search=%s", query),
|
||||
@ -143,9 +139,7 @@ func generateSearchUrl(website, query string) string {
|
||||
"rossmann": fmt.Sprintf("https://www.rossmann.de/de/search/?text=%s", query),
|
||||
|
||||
// ----- Schilder ------
|
||||
"brewes": fmt.Sprintf("https://www.brewes.de/catalogsearch/result?q=%s", query),
|
||||
"schildershop24": fmt.Sprintf("https://www.schildershop24.de/?action=Query&-query.&query.stichwort=%s", query),
|
||||
"vkfrenzel": fmt.Sprintf("https://www.vkf-renzel.de/index.php?lang=0&cl=rasearch&searchparam=%s", query),
|
||||
"vkfrenzel": fmt.Sprintf("https://www.vkf-renzel.de/index.php?lang=0&cl=rasearch&searchparam=%s", query),
|
||||
|
||||
// ----- Landwirtschaft -------
|
||||
"siepmann": fmt.Sprintf("https://www.siepmann.net/siepmann_shop.php?suchfeld=%s", query),
|
||||
@ -154,14 +148,10 @@ func generateSearchUrl(website, query string) string {
|
||||
"kox": "https://www.kox-direct.de/?query=${query}&sid=6d0b4366af8bb99af514529b7e61ad&act=search",
|
||||
|
||||
// ----- Arbeitsschutz -------
|
||||
"engelbert": fmt.Sprintf("https://www.engelbert-strauss.de/s/suche?query=%s", query),
|
||||
"arbeitsplatzmattenprofi": fmt.Sprintf("https://arbeitsplatzmatten-profi.com/?s=%s", query),
|
||||
"ara": fmt.Sprintf("https://ara-arbeitsschutz.de/navi.php?qs=%s", query),
|
||||
|
||||
"engelbert": fmt.Sprintf("https://www.engelbert-strauss.de/s/suche?query=%s", query),
|
||||
// ------ Med. Artikel -------
|
||||
"oekonomed": fmt.Sprintf("https://shop.oekonomed.de/de/advanced_search_result.php?keywords=%s&inc_subcat=1", query),
|
||||
"praxisdienst": fmt.Sprintf("https://www.praxisdienst.de/index.php?stoken=268B7DE4&sid=hf02v2hm41hv6v8j3nttfgej8c&lang=0&cl=search&listorderby=reset&searchparam=%s", query),
|
||||
"gerl": fmt.Sprintf("https://gerl-dental.de/search?query=%s", query),
|
||||
|
||||
// ----- Möbel -------
|
||||
"ikea": fmt.Sprintf("https://www.ikea.com/de/de/search/?q=%s", query),
|
||||
@ -184,6 +174,10 @@ func generateSearchUrl(website, query string) string {
|
||||
// ----- Saatgut ------
|
||||
"saatgutshop": fmt.Sprintf("https://www.saatgut-shop.de/advanced_search_result.php?categories_id=0&keywords=%s&inc_subcat=1", query),
|
||||
"saatgutmanufaktur": fmt.Sprintf("https://shop.saatgut-manufaktur.de/advanced_search_result.php?keywords=%s&inc_subcat=1", query),
|
||||
|
||||
// ------ Bücher ------
|
||||
"buchammarkt": fmt.Sprintf("https://bam-mr.buchkatalog.de/search?q=%s", query),
|
||||
"thalia": fmt.Sprintf("https://www.thalia.de/suche?sq=%s", query),
|
||||
}
|
||||
|
||||
if url, ok := searchUrls[website]; ok {
|
||||
|
170
popup.html
Normal file
@ -0,0 +1,170 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pop-ups erlauben</title>
|
||||
<style>
|
||||
/* Allgemeine Stile */
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #3498db;
|
||||
position: relative;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 1vh;
|
||||
font-size: 1vw;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: disc;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.browser-instructions {
|
||||
background-color: white;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
margin: 1vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 70%;
|
||||
margin: 0 auto;
|
||||
padding: 1vh 0;
|
||||
}
|
||||
|
||||
/* Responsive Bild */
|
||||
.responsive-image {
|
||||
max-width: 100%; /* Bild wird nie breiter als sein Container */
|
||||
height: auto; /* Höhe wird proportional angepasst */
|
||||
display: block; /* Entfernt unnötigen Abstand unter dem Bild */
|
||||
margin: 10px 0; /* Optional: Abstand oben und unten */
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 2vh;
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
font-size: 1.5vw;
|
||||
margin-top: 5vh;
|
||||
}
|
||||
|
||||
/* Tablet-Layout (Bildschirmbreite bis 1200px) */
|
||||
@media (max-width: 1200px) {
|
||||
.container {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
header {
|
||||
font-size: 2vw;
|
||||
}
|
||||
|
||||
.browser-instructions {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile-Layout (Bildschirmbreite bis 768px) */
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
header {
|
||||
font-size: 3vw;
|
||||
padding: 2vh;
|
||||
}
|
||||
|
||||
.browser-instructions {
|
||||
padding: 10px;
|
||||
margin: 2vh;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sehr kleine Bildschirme (Bildschirmbreite bis 480px) */
|
||||
@media (max-width: 480px) {
|
||||
.container {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
header {
|
||||
font-size: 4vw;
|
||||
padding: 3vh;
|
||||
}
|
||||
|
||||
.browser-instructions {
|
||||
padding: 8px;
|
||||
margin: 3vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Pop-ups erlauben</h1>
|
||||
</header>
|
||||
|
||||
<div class="browser-instructions">
|
||||
<p> Wenn du bei der ersten Suche mehrere Webseiten auswählst wird oben in der Adressleiste eine Meldung erscheinen das die Pop-Ups blockiert wurden. Damit alle suchergebnisse angezeigt werden musst du die Pop-Ups erlauben.</p>
|
||||
<p>Wenn die Pop-Ups erlaubt wurden lade die Seite neu.</p>
|
||||
</div>
|
||||
<div class="browser-instructions">
|
||||
<h2>Google Chrome</h2>
|
||||
<ul>
|
||||
<li>Klicke auf das Pop-Up-Symbol in der Adressleiste.</li>
|
||||
<img src="https://einkauf.diefleckenbuehler.de/public/chrome-popup.jpg" alt="Pop-ups in Firefox erlauben" class="responsive-image">
|
||||
<li>Hier <strong>Pop-ups und Weiterleitungen</strong> immer zulassen.</li>
|
||||
<img src="https://einkauf.diefleckenbuehler.de/public/chrome.jpg" alt="Pop-ups in Firefox erlauben" class="responsive-image">
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="browser-instructions">
|
||||
<h2>Mozilla Firefox</h2>
|
||||
<ul>
|
||||
<li>Klicke auf das Einstellungen-Symbol in der Adressleiste.</li>
|
||||
<img src="https://einkauf.diefleckenbuehler.de/public/firefox-popup.jpg" alt="Pop-ups in Firefox erlauben" class="responsive-image">
|
||||
<li>Scrolle zu <strong>Pop-ups blockieren</strong> und stelle es auf <strong>Erlauben</strong>.</li>
|
||||
|
||||
<img src="https://einkauf.diefleckenbuehler.de/public/firefox.jpg" alt="Pop-ups in Firefox erlauben" class="responsive-image">
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="browser-instructions">
|
||||
<h2>Microsoft Edge</h2>
|
||||
<ul>
|
||||
<li>Klicke auf das Pop-Up-Symbol in der Adressleiste.</li>
|
||||
<img src="https://einkauf.diefleckenbuehler.de/public/edge-popup.jpg" alt="Pop-ups in Firefox erlauben" class="responsive-image">
|
||||
<li>Hier <strong>Pop-ups und Weiterleitungen</strong> immer zulassen.</li>
|
||||
<img src="https://einkauf.diefleckenbuehler.de/public/edge.jpg" alt="Pop-ups in Firefox erlauben" class="responsive-image">
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="browser-instructions">
|
||||
<h2>Safari (macOS)</h2>
|
||||
<ul>
|
||||
<p>Klicke auf das Pop-Up-Symbol in der Adressleiste. Damit werden die Pop-Ups erlaubt</p>
|
||||
<img src="https://einkauf.diefleckenbuehler.de/public/safari.jpg" alt="Pop-ups in Firefox erlauben" class="responsive-image">
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>© 2025 Einkauf Suche - Alle Rechte vorbehalten</p>
|
||||
</footer>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
public/chrome-popup.jpg
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
public/chrome.jpg
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
public/edge-popup.jpg
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
public/edge.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
public/firefox-popup.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/firefox.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
public/safari.jpg
Normal file
After Width: | Height: | Size: 9.3 KiB |