package main import ( "html/template" "net/http" "strings" "time" ) type UserSettings struct { Theme string SiteLanguage string SearchLanguage string SafeSearch string IsThemeDark bool } func loadUserSettings(w http.ResponseWriter, r *http.Request) UserSettings { var settings UserSettings saveRequired := false // Load theme if cookie, err := r.Cookie("theme"); err == nil { settings.Theme = cookie.Value } else { settings.Theme = "dark" saveRequired = true } // Determine if the selected theme is dark settings.IsThemeDark = settings.Theme == "dark" || settings.Theme == "night" || settings.Theme == "black" // Load site language if cookie, err := r.Cookie("site_language"); err == nil { settings.SiteLanguage = cookie.Value } else { // If no site language is set, use Accept-Language or default to "en" acceptLang := r.Header.Get("Accept-Language") if acceptLang != "" { settings.SiteLanguage = normalizeLangCode(strings.Split(acceptLang, ",")[0]) } else { settings.SiteLanguage = "en" // Default language } saveRequired = true } // Load search language (can be empty) if cookie, err := r.Cookie("search_language"); err == nil { settings.SearchLanguage = cookie.Value } // Load safe search if cookie, err := r.Cookie("safe"); err == nil { settings.SafeSearch = cookie.Value } else { settings.SafeSearch = "" saveRequired = true } if saveRequired { saveUserSettings(w, settings) } return settings } func saveUserSettings(w http.ResponseWriter, settings UserSettings) { expiration := time.Now().Add(90 * 24 * time.Hour) http.SetCookie(w, &http.Cookie{ Name: "theme", Value: settings.Theme, Path: "/", Expires: expiration, Secure: true, SameSite: http.SameSiteStrictMode, }) http.SetCookie(w, &http.Cookie{ Name: "site_language", Value: settings.SiteLanguage, Path: "/", Expires: expiration, Secure: true, SameSite: http.SameSiteStrictMode, }) http.SetCookie(w, &http.Cookie{ Name: "search_language", Value: settings.SearchLanguage, Path: "/", Expires: expiration, Secure: true, SameSite: http.SameSiteStrictMode, }) http.SetCookie(w, &http.Cookie{ Name: "safe", Value: settings.SafeSearch, Path: "/", Expires: expiration, Secure: true, SameSite: http.SameSiteStrictMode, }) printDebug("settings saved: %v", settings) } func handleSaveSettings(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { // Load current settings settings := loadUserSettings(w, r) // Update only the settings that were submitted in the form if theme := r.FormValue("theme"); theme != "" { settings.Theme = theme } // Update site language if provided if siteLang := r.FormValue("site_lang"); siteLang != "" { settings.SiteLanguage = siteLang } else { // If site_lang is empty, try to get from Accept-Language header acceptLang := r.Header.Get("Accept-Language") if acceptLang != "" { settings.SiteLanguage = strings.Split(acceptLang, ",")[0] } } // Update search language if provided if searchLang := r.FormValue("search_lang"); searchLang != "" { settings.SearchLanguage = searchLang } // Update safe search if provided if safe := r.FormValue("safe"); safe != "" { settings.SafeSearch = safe } // Save the updated settings saveUserSettings(w, settings) // Redirect back to the previous page or settings page http.Redirect(w, r, r.FormValue("past"), http.StatusSeeOther) } } func handleSettings(w http.ResponseWriter, r *http.Request) { // Load user settings settings = loadUserSettings(w, r) data := struct { LanguageOptions []LanguageOption CurrentSiteLang string CurrentSearchLang string Theme string Safe string IsThemeDark bool }{ LanguageOptions: languageOptions, CurrentSiteLang: settings.SiteLanguage, CurrentSearchLang: settings.SearchLanguage, Theme: settings.Theme, Safe: settings.SafeSearch, IsThemeDark: settings.IsThemeDark, } printDebug("Rendering settings with data: %+v", data) tmpl, err := template.ParseFiles("templates/settings.html") if err != nil { printErr("Error parsing template: %s", err) http.Error(w, "Internal Server Error", 500) return } err = tmpl.Execute(w, data) if err != nil { printErr("Error executing template: %s", err) http.Error(w, "Internal Server Error", 500) return } } // Helper function to normalize language codes func normalizeLangCode(lang string) string { lang = strings.ToLower(lang) // First, check if the language code is already valid if isValidLangCode(lang) { return lang } // Strip regional codes (e.g., en-US -> en) if strings.Contains(lang, "-") { lang = strings.Split(lang, "-")[0] } // Re-check if the normalized version is valid if isValidLangCode(lang) { return lang } // If the language is not recognized, default to "en" return "en" } // Helper function to check if a language code exists in the language options func isValidLangCode(lang string) bool { for _, opt := range languageOptions { if opt.Code == lang { return true } } return false }