commit 184a0039a129d604eadc6e30c6a6c1a7274ea6b6
parent 40d7b0a18047e7c294229d172ca0f9f59a0dc198
Author: breadcat <breadcat@users.noreply.github.com>
Date: Sun, 21 Sep 2025 11:05:51 +0100
Add settings feature for upload dir, db path
Diffstat:
4 files changed, 212 insertions(+), 6 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -2,3 +2,4 @@ uploads/
*.db
+config.json
diff --git a/main.go b/main.go
@@ -11,6 +11,8 @@ import (
"strings"
"io"
"net/url"
+ "encoding/json"
+ "io/ioutil"
_ "github.com/mattn/go-sqlite3"
)
@@ -18,6 +20,7 @@ import (
var (
db *sql.DB
tmpl *template.Template
+ config Config
)
type File struct {
@@ -27,6 +30,12 @@ type File struct {
Tags map[string]string
}
+type Config struct {
+ DatabasePath string `json:"database_path"`
+ UploadDir string `json:"upload_dir"`
+ ServerPort string `json:"server_port"`
+}
+
type TagDisplay struct {
Value string
Count int
@@ -38,8 +47,13 @@ type PageData struct {
}
func main() {
+ // Load configuration first
+ if err := loadConfig(); err != nil {
+ log.Fatalf("Failed to load config: %v", err)
+ }
+
var err error
- db, err = sql.Open("sqlite3", "./database.db")
+ db, err = sql.Open("sqlite3", config.DatabasePath)
if err != nil {
log.Fatal(err)
}
@@ -71,7 +85,8 @@ func main() {
log.Fatal(err)
}
- os.MkdirAll("uploads", 0755)
+ // Use configured upload directory
+ os.MkdirAll(config.UploadDir, 0755)
os.MkdirAll("static", 0755)
tmpl = template.Must(template.New("").Funcs(template.FuncMap{
@@ -93,12 +108,19 @@ func main() {
http.HandleFunc("/tag/", tagFilterHandler)
http.HandleFunc("/untagged", untaggedFilesHandler)
http.HandleFunc("/search", searchHandler)
+ http.HandleFunc("/settings", settingsHandler)
- http.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir("uploads"))))
+ // Use configured upload directory for file serving
+ http.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir(config.UploadDir))))
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
- log.Println("Server started at http://localhost:8080")
- http.ListenAndServe(":8080", nil)
+ log.Printf("Server started at http://localhost%s", config.ServerPort)
+ log.Printf("Database: %s", config.DatabasePath)
+ log.Printf("Upload directory: %s", config.UploadDir)
+ http.ListenAndServe(config.ServerPort, nil)
+}
+
+
func searchHandler(w http.ResponseWriter, r *http.Request) {
query := strings.TrimSpace(r.URL.Query().Get("q"))
@@ -648,4 +670,128 @@ func tagFilterHandler(w http.ResponseWriter, r *http.Request) {
}
tmpl.ExecuteTemplate(w, "list.html", pageData)
+}
+
+func loadConfig() error {
+ // Set defaults
+ config = Config{
+ DatabasePath: "./database.db",
+ UploadDir: "uploads",
+ ServerPort: ":8080",
+ }
+
+ // Try to load existing config
+ if data, err := ioutil.ReadFile("config.json"); err == nil {
+ if err := json.Unmarshal(data, &config); err != nil {
+ return err
+ }
+ }
+
+ // Ensure upload directory exists
+ return os.MkdirAll(config.UploadDir, 0755)
+}
+
+func saveConfig() error {
+ data, err := json.MarshalIndent(config, "", " ")
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile("config.json", data, 0644)
+}
+
+func validateConfig(newConfig Config) error {
+ // Validate database path is not empty
+ if newConfig.DatabasePath == "" {
+ return fmt.Errorf("database path cannot be empty")
+ }
+
+ // Validate upload directory is not empty
+ if newConfig.UploadDir == "" {
+ return fmt.Errorf("upload directory cannot be empty")
+ }
+
+ // Validate server port format
+ if newConfig.ServerPort == "" || !strings.HasPrefix(newConfig.ServerPort, ":") {
+ return fmt.Errorf("server port must be in format ':8080'")
+ }
+
+ // Try to create upload directory if it doesn't exist
+ if err := os.MkdirAll(newConfig.UploadDir, 0755); err != nil {
+ return fmt.Errorf("cannot create upload directory: %v", err)
+ }
+
+ return nil
+}
+
+// Add this settings handler function
+func settingsHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method == http.MethodPost {
+ // Handle settings update
+ newConfig := Config{
+ DatabasePath: strings.TrimSpace(r.FormValue("database_path")),
+ UploadDir: strings.TrimSpace(r.FormValue("upload_dir")),
+ ServerPort: strings.TrimSpace(r.FormValue("server_port")),
+ }
+
+ // Validate new configuration
+ if err := validateConfig(newConfig); err != nil {
+ pageData := PageData{
+ Title: "Settings",
+ Data: struct {
+ Config Config
+ Error string
+ }{config, err.Error()},
+ }
+ tmpl.ExecuteTemplate(w, "settings.html", pageData)
+ return
+ }
+
+ // Check if database path changed and requires restart
+ needsRestart := (newConfig.DatabasePath != config.DatabasePath ||
+ newConfig.ServerPort != config.ServerPort)
+
+ // Save new configuration
+ config = newConfig
+ if err := saveConfig(); err != nil {
+ pageData := PageData{
+ Title: "Settings",
+ Data: struct {
+ Config Config
+ Error string
+ }{config, "Failed to save configuration: " + err.Error()},
+ }
+ tmpl.ExecuteTemplate(w, "settings.html", pageData)
+ return
+ }
+
+ // Show success message
+ var message string
+ if needsRestart {
+ message = "Settings saved successfully! Please restart the server for database/port changes to take effect."
+ } else {
+ message = "Settings saved successfully!"
+ }
+
+ pageData := PageData{
+ Title: "Settings",
+ Data: struct {
+ Config Config
+ Error string
+ Success string
+ }{config, "", message},
+ }
+ tmpl.ExecuteTemplate(w, "settings.html", pageData)
+ return
+ }
+
+ // Show settings form
+ pageData := PageData{
+ Title: "Settings",
+ Data: struct {
+ Config Config
+ Error string
+ Success string
+ }{config, "", ""},
+ }
+ tmpl.ExecuteTemplate(w, "settings.html", pageData)
}
\ No newline at end of file
diff --git a/templates/_header.html b/templates/_header.html
@@ -23,5 +23,5 @@ ul.tag-menu li ul li a:hover{background:#ddd}
</style>
</head>
<body>
-<p><a href="/upload">Upload new file</a> | <a href="/">Files</a> | <a href="/tags">Tags</a> | <a href="/untagged">Untagged</a> | <a href="/search">Search</a></p>
+<p><a href="/upload">Upload new file</a> | <a href="/">Files</a> | <a href="/tags">Tags</a> | <a href="/untagged">Untagged</a> | <a href="/search">Search</a> | <a href="/settings">Settings</a></p>
{{end}}
\ No newline at end of file
diff --git a/templates/settings.html b/templates/settings.html
@@ -0,0 +1,58 @@
+{{template "_header" .}}
+<h1>Settings</h1>
+
+{{if .Data.Error}}
+<div style="background-color: #f8d7da; color: #721c24; padding: 10px; border: 1px solid #f5c6cb; border-radius: 4px; margin-bottom: 20px;">
+ <strong>Error:</strong> {{.Data.Error}}
+</div>
+{{end}}
+
+{{if .Data.Success}}
+<div style="background-color: #d4edda; color: #155724; padding: 10px; border: 1px solid #c3e6cb; border-radius: 4px; margin-bottom: 20px;">
+ <strong>Success:</strong> {{.Data.Success}}
+</div>
+{{end}}
+
+<form method="post" style="max-width: 600px;">
+ <div style="margin-bottom: 20px;">
+ <label for="database_path" style="display: block; font-weight: bold; margin-bottom: 5px;">Database Path:</label>
+ <input type="text" id="database_path" name="database_path" value="{{.Data.Config.DatabasePath}}" required
+ style="width: 100%; padding: 8px; font-size: 14px;"
+ placeholder="./database.db">
+ <small style="color: #666;">Path to SQLite database file (requires restart if changed)</small>
+ </div>
+
+ <div style="margin-bottom: 20px;">
+ <label for="upload_dir" style="display: block; font-weight: bold; margin-bottom: 5px;">Upload Directory:</label>
+ <input type="text" id="upload_dir" name="upload_dir" value="{{.Data.Config.UploadDir}}" required
+ style="width: 100%; padding: 8px; font-size: 14px;"
+ placeholder="uploads">
+ <small style="color: #666;">Directory where uploaded files are stored</small>
+ </div>
+
+ <div style="margin-bottom: 20px;">
+ <label for="server_port" style="display: block; font-weight: bold; margin-bottom: 5px;">Server Port:</label>
+ <input type="text" id="server_port" name="server_port" value="{{.Data.Config.ServerPort}}" required
+ style="width: 100%; padding: 8px; font-size: 14px;"
+ placeholder=":8080">
+ <small style="color: #666;">Port for web server (format: :8080, requires restart if changed)</small>
+ </div>
+
+ <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px;">
+ Save Settings
+ </button>
+</form>
+
+<div style="margin-top: 40px; padding: 20px; background-color: #f8f9fa; border-radius: 5px;">
+ <h3>Current Configuration:</h3>
+ <ul>
+ <li><strong>Database:</strong> {{.Data.Config.DatabasePath}}</li>
+ <li><strong>Upload Directory:</strong> {{.Data.Config.UploadDir}}</li>
+ <li><strong>Server Port:</strong> {{.Data.Config.ServerPort}}</li>
+ </ul>
+
+ <h4>Configuration File:</h4>
+ <p>Settings are stored in <code>config.json</code> in the application directory.</p>
+</div>
+
+{{template "_footer"}}
+\ No newline at end of file