package handler import ( "fmt" "log" "net/http" "strconv" "strings" "vidarchive/internal/models" ) func (h *Handler) Settings(w http.ResponseWriter, r *http.Request) { presets, err := h.presetSvc.GetAll() if err != nil { h.serverError(w, r, "list presets", err) return } settings, err := h.settingsSvc.GetAll() if err != nil { h.serverError(w, r, "load settings", err) return } h.renderWithRequest(w, r, "settings", PageData{ Title: "Settings", ActiveTab: "settings", Data: struct { Presets []*models.Preset Settings *models.Settings }{ Presets: presets, Settings: settings, }, }) } func (h *Handler) CreatePreset(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } preset := &models.Preset{} if err := applyPresetForm(preset, r); err != nil { redirectWithError(w, r, "/settings", err.Error(), nil) return } if err := h.presetSvc.Create(preset); err != nil { redirectWithError(w, r, "/settings", "Couldn't create this preset.", err) return } redirectWithSuccess(w, r, "/settings", "Preset created.") } // applyPresetForm copies the preset form fields onto p and validates them. It is // shared by create and update so the two can't drift apart as fields are added. func applyPresetForm(p *models.Preset, r *http.Request) error { name := strings.TrimSpace(r.FormValue("name")) if name == "" { return fmt.Errorf("A preset needs a name.") } // Mirrors the radio options on the settings form; empty means "unspecified" // and BuildArgs applies its own default. formatMode := r.FormValue("format_mode") switch formatMode { case "", "default", "preset", "custom": default: return fmt.Errorf("Unknown format mode %q.", formatMode) } p.Name = name p.Description = r.FormValue("description") p.FormatMode = formatMode p.Format = r.FormValue("format") p.Quality = r.FormValue("quality") p.CustomFormat = r.FormValue("custom_format") p.AudioFormat = r.FormValue("audio_format") p.SubLangs = r.FormValue("sub_langs") p.CustomFlags = r.FormValue("custom_flags") p.IsDefault = r.FormValue("is_default") == "1" p.ExtractAudio = r.FormValue("extract_audio") == "1" p.EmbedSubs = r.FormValue("embed_subs") == "1" p.EmbedThumbnail = r.FormValue("embed_thumbnail") == "1" p.EmbedMetadata = r.FormValue("embed_metadata") == "1" p.WriteInfoJSON = r.FormValue("write_info_json") == "1" p.WriteComments = r.FormValue("write_comments") == "1" p.CommentSort = strings.TrimSpace(r.FormValue("comment_sort")) p.CommentExtractorArgs = strings.TrimSpace(r.FormValue("comment_extractor_args")) p.MaxComments = 0 if raw := strings.TrimSpace(r.FormValue("max_comments")); raw != "" { maxComments, err := strconv.Atoi(raw) if err != nil || maxComments < 0 { return fmt.Errorf("Max comments must be a non-negative number.") } p.MaxComments = maxComments } // Comments are stored in the info JSON sidecar. Keep the dependent options // consistent even when a client submits the form without JavaScript. if !p.WriteInfoJSON || !p.WriteComments { p.WriteComments = false p.CommentSort = "" p.MaxComments = 0 p.CommentExtractorArgs = "" } return nil } func (h *Handler) UpdatePreset(w http.ResponseWriter, r *http.Request) { id, ok := parseID(w, r) if !ok { return } if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } preset, err := h.presetSvc.GetByID(id) if err != nil { http.Error(w, "Not found", http.StatusNotFound) return } if err := applyPresetForm(preset, r); err != nil { redirectWithError(w, r, "/settings", err.Error(), nil) return } if err := h.presetSvc.Update(preset); err != nil { redirectWithError(w, r, "/settings", "Couldn't update this preset.", err) return } redirectWithSuccess(w, r, "/settings", "Preset updated.") } func (h *Handler) DeletePreset(w http.ResponseWriter, r *http.Request) { id, ok := parseID(w, r) if !ok { return } if err := h.presetSvc.Delete(id); err != nil { redirectWithError(w, r, "/settings", "Couldn't delete this preset.", err) return } redirectWithSuccess(w, r, "/settings", "Preset deleted.") } func (h *Handler) UpdateSettings(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } var firstErr error record := func(err error) { if err != nil && firstErr == nil { firstErr = err } } if interval := r.FormValue("refresh_interval"); interval != "" { record(h.settingsSvc.SetRefreshInterval(interval)) } record(h.settingsSvc.SetAutoRefreshLibrary(r.FormValue("auto_refresh_library") == "1")) record(h.settingsSvc.SetAutoRefreshDownloads(r.FormValue("auto_refresh_downloads") == "1")) record(h.settingsSvc.SetCookies(r.FormValue("cookies"))) if firstErr != nil { log.Printf("UpdateSettings: %v", firstErr) flashError(w, "Some settings couldn't be saved: "+firstErr.Error()) } else { flashSuccess(w, "Settings saved.") } http.Redirect(w, r, "/settings", http.StatusSeeOther) } func (h *Handler) Theme(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } theme := r.FormValue("theme") if theme == "" { theme = "auto" } setCookie(w, "theme", theme) referer := r.Header.Get("Referer") if referer == "" { referer = "/" } http.Redirect(w, r, referer, http.StatusSeeOther) }