From 337c9f604005c72d65db5136c821a923b74c9b4c Mon Sep 17 00:00:00 2001 From: olikol <78661364+olikols07@users.noreply.github.com> Date: Thu, 28 Aug 2025 13:26:16 +0200 Subject: [PATCH] Added Image metadata and made spice lvl editable Also added db support --- .example.env | 5 +++ .gitignore | 3 +- api/FileHandlers.go | 47 ++-------------------------- api/MetadataSaving.go | 52 +++++++++++++++++++++++++++++++ api/UploadHandlers.go | 2 ++ config/env.go | 45 +++++++++++++++++++++++++++ db/db.go | 58 +++++++++++++++++++++++++++++++++++ go.mod | 5 +++ go.sum | 8 +++++ main.go | 9 +++++- static/js/image_upload.js | 2 +- static/js/images.js | 38 +++++++++++++---------- website/templates/admin.html | 4 ++- website/templates/images.html | 40 +++++++++++++++++------- 14 files changed, 243 insertions(+), 75 deletions(-) create mode 100644 .example.env create mode 100644 api/MetadataSaving.go create mode 100644 config/env.go create mode 100644 db/db.go create mode 100644 go.sum diff --git a/.example.env b/.example.env new file mode 100644 index 0000000..db8b3a2 --- /dev/null +++ b/.example.env @@ -0,0 +1,5 @@ +POSTGRES_USER= +POSTGRES_PWD= +POSTGRES_DB= +POSTGRES_HOST= +POSTGRES_PORT= \ No newline at end of file diff --git a/.gitignore b/.gitignore index a98563f..d021f00 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /tmp -/uploads/* \ No newline at end of file +/uploads/* +.env \ No newline at end of file diff --git a/api/FileHandlers.go b/api/FileHandlers.go index 0bb414f..accc421 100644 --- a/api/FileHandlers.go +++ b/api/FileHandlers.go @@ -1,57 +1,16 @@ package api import ( + "Advertisement_Panel/db" "encoding/json" "net/http" - "os" - "path/filepath" ) -type FileData struct { - ImageNames []string - SpicyImageNames []string - AsciiFiles []AsciiEntry -} - -type AsciiEntry struct { - Name string - FontSize int -} - -const staticDir = "static" - // move FileData and AsciiEntry here if you want, or leave in main.go func FileHandler(w http.ResponseWriter, r *http.Request) { - data := FileData{ - ImageNames: []string{}, - SpicyImageNames: []string{}, - AsciiFiles: []AsciiEntry{}, - } + var data []db.ImagesEntry - files, _ := os.ReadDir(filepath.Join(staticDir, "images")) - for _, file := range files { - fileName := file.Name() - data.ImageNames = append(data.ImageNames, filepath.Join("/", staticDir, "images", fileName)) - } - files, _ = os.ReadDir(filepath.Join("uploads")) - for _, file := range files { - fileName := file.Name() - data.ImageNames = append(data.ImageNames, filepath.Join("/uploads", fileName)) - } - - files, _ = os.ReadDir(filepath.Join(staticDir, "spicy")) - for _, file := range files { - fileName := file.Name() - data.ImageNames = append(data.ImageNames, filepath.Join("/", staticDir, "spicy", fileName)) - } - - files, _ = os.ReadDir(filepath.Join(staticDir, "ascii_art")) - for _, file := range files { - fileName := file.Name() - data.AsciiFiles = append(data.AsciiFiles, - AsciiEntry{Name: filepath.Join("/", staticDir, "ascii_art", fileName), FontSize: 12}, - ) - } + data = db.GetImageMetadata() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(data) diff --git a/api/MetadataSaving.go b/api/MetadataSaving.go new file mode 100644 index 0000000..21fe2e2 --- /dev/null +++ b/api/MetadataSaving.go @@ -0,0 +1,52 @@ +package api + +import ( + "Advertisement_Panel/db" + "encoding/json" + "io" + "log" + "net/http" +) + +func SaveMetadataHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Failed to read request body", http.StatusBadRequest) + return + } + defer r.Body.Close() + + var newMetadata []db.ImagesEntry + log.Println(string(body)) + err = json.Unmarshal(body, &newMetadata) + + if err != nil { + log.Println("Error unmarshalling JSON:", err) + http.Error(w, "Failed to parse JSON", http.StatusBadRequest) + return + } + + var currentMetadata []db.ImagesEntry + currentMetadata = db.GetImageMetadata() + + for _, newEntry := range newMetadata { + for _, currentEntry := range currentMetadata { + if newEntry.ID == currentEntry.ID { + if newEntry.SpiceLevel != currentEntry.SpiceLevel { + _, err := db.DB.Exec("UPDATE images SET spice_level = $1 WHERE id = $2", newEntry.SpiceLevel, newEntry.ID) + if err != nil { + http.Error(w, "Failed to update database", http.StatusInternalServerError) + return + } + } + break + } + } + } + +} diff --git a/api/UploadHandlers.go b/api/UploadHandlers.go index 0051d54..1d7b011 100644 --- a/api/UploadHandlers.go +++ b/api/UploadHandlers.go @@ -1,6 +1,7 @@ package api import ( + "Advertisement_Panel/db" "fmt" "io" "net/http" @@ -33,4 +34,5 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) { } fmt.Fprint(w, "") fmt.Fprintf(w, "Image uploaded successfully: %s", header.Filename) + db.DB.Exec("INSERT INTO images (path, spice_level) VALUES ($1, $2)", "/uploads/"+header.Filename, 0) } diff --git a/config/env.go b/config/env.go new file mode 100644 index 0000000..b4da19a --- /dev/null +++ b/config/env.go @@ -0,0 +1,45 @@ +package config + +import ( + "os" + // this will automatically load your .env file: + _ "github.com/joho/godotenv/autoload" +) + +type Config struct { + Logs LogConfig + DB PostgresConfig + Port string +} + +type LogConfig struct { + Style string + Level string +} + +type PostgresConfig struct { + Username string + Password string + Db string + Host string + Port string +} + +var Cfg *Config + +func LoadConfig() { + Cfg = &Config{ + Port: os.Getenv("PORT"), + Logs: LogConfig{ + Style: os.Getenv("LOG_STYLE"), + Level: os.Getenv("LOG_LEVEL"), + }, + DB: PostgresConfig{ + Username: os.Getenv("POSTGRES_USER"), + Password: os.Getenv("POSTGRES_PWD"), + Db: os.Getenv("POSTGRES_DB"), + Host: os.Getenv("POSTGRES_HOST"), + Port: os.Getenv("POSTGRES_PORT"), + }, + } +} diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..8f36e2b --- /dev/null +++ b/db/db.go @@ -0,0 +1,58 @@ +package db + +import ( + "Advertisement_Panel/config" + "database/sql" + "fmt" + "log" + + _ "github.com/lib/pq" +) + +type ImagesEntry struct { + ID int `json:"id"` + Path string `json:"path"` + SpiceLevel int `json:"spice_level"` +} + +var DB *sql.DB + +func Init() { + log.Println("Initializing database connection...") + connStr := fmt.Sprintf("host=%s port=%s user=%s "+ + "password=%s dbname=%s sslmode=disable", + config.Cfg.DB.Host, config.Cfg.DB.Port, config.Cfg.DB.Username, config.Cfg.DB.Password, config.Cfg.DB.Db) + log.Println(connStr) + var err error + + DB, err = sql.Open("postgres", connStr) + + if err != nil { + log.Println("Error connecting to the database: ", err) + } +} + +func GetImageMetadata() []ImagesEntry { + rows, err := DB.Query("SELECT id, path, spice_level FROM images") + if err != nil { + log.Fatal(err) + } + defer rows.Close() + + var data []ImagesEntry + + for rows.Next() { + var id int + var path string + var spiceLevel int + if err := rows.Scan(&id, &path, &spiceLevel); err != nil { + log.Fatal(err) + } + + data = append(data, ImagesEntry{ID: id, Path: path, SpiceLevel: spiceLevel}) + } + if err := rows.Err(); err != nil { + log.Fatal(err) + } + return data +} diff --git a/go.mod b/go.mod index 9827139..6a62227 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module Advertisement_Panel go 1.24 + +require ( + github.com/joho/godotenv v1.5.1 + github.com/lib/pq v1.10.9 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6b95218 --- /dev/null +++ b/go.sum @@ -0,0 +1,8 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= diff --git a/main.go b/main.go index ddf8c70..809559b 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,8 @@ package main import ( "Advertisement_Panel/api" + "Advertisement_Panel/config" + "Advertisement_Panel/db" "fmt" "html/template" "net/http" @@ -14,6 +16,9 @@ func main() { fmt.Print("Now running server!\n") + config.LoadConfig() + db.Init() + // Serves index http.HandleFunc("/", index_handler) @@ -32,7 +37,9 @@ func main() { http.HandleFunc("/admin/", admin_handler) // Handles image upload - http.HandleFunc("/upload", api.UploadHandler) + http.HandleFunc("/api/upload", api.UploadHandler) + // Handles metadata saving + http.HandleFunc("/api/save-metadata", api.SaveMetadataHandler) fmt.Print("Webserver running on http://localhost:8080\n") diff --git a/static/js/image_upload.js b/static/js/image_upload.js index 0171377..1300d97 100644 --- a/static/js/image_upload.js +++ b/static/js/image_upload.js @@ -32,7 +32,7 @@ uploadForm.on("submit", function(e) { formData.append("image", currentFile); $.ajax({ - url: "/upload", + url: "/api/upload", type: "POST", data: formData, processData: false, diff --git a/static/js/images.js b/static/js/images.js index ebf7fbd..3c666cd 100644 --- a/static/js/images.js +++ b/static/js/images.js @@ -1,7 +1,6 @@ let galleryTable = $("#imagesGallery") let refreshButton = $("#refresh-gallery") - -let filesList = [] +let saveButton = $("#save-gallery") let fileMetaData = [] @@ -10,44 +9,51 @@ async function fetchImages() { url: '/files', type: 'GET', success: function(response) { - filesList = response; - console.log(filesList); + fileMetaData = response; + console.log(fileMetaData); }, error: function() { alert('Error fetching images.'); } }); - filesList.ImageNames.forEach((filePath, i) => { + fileMetaData.forEach((file, i) => { let newRow = $(`