feat: init commit

This commit is contained in:
DaanSelen
2026-04-20 16:58:20 +02:00
parent 5b84b3ed1d
commit 4b783b50fb
14 changed files with 495 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
package api
import (
"eden-server/internal/runtime"
"fmt"
"log/slog"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
func KickoffApi(env runtime.Environment, db *gorm.DB) {
router := gin.Default()
router.LoadHTMLFiles("./web/templates/index.html")
spawnRoutes(router, env, db)
err := router.Run(fmt.Sprintf("%s:%s", env.Hostname, env.Port))
if err != nil {
slog.Error("failed to start the Gin server due to: " + err.Error())
}
}
+87
View File
@@ -0,0 +1,87 @@
package api
import (
"eden-server/internal/database"
"eden-server/internal/runtime"
"log/slog"
"net/http"
"path/filepath"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"gorm.io/gorm"
)
// 0: unspecified
// 1: video
// 2: presentation
// 3: internet URL
func categorizeFile(ext string) string {
switch ext {
case ".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4a":
return "video"
case ".pptx", ".ppt", ".key", ".odp":
return "presentation"
default:
return "unspecified"
}
}
func spawnRoutes(r *gin.Engine, env runtime.Environment, db *gorm.DB) {
// The Root endpoint '/' displays a simple HTML template.
// from root: ./templates/index.html
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html",
gin.H{
"title": env.Codename,
"version": env.Version,
},
)
})
// prefix: api
// Display the information on what is going on at the moment
r.GET("/api/status", func(c *gin.Context) {
state, err := database.GetAppState(db)
if err != nil {
slog.Warn("unable to determine state")
}
c.JSON(http.StatusOK, state)
})
// define the upload route
r.POST("/api/upload", func(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
slog.Error("missing file upload", "error", err)
c.JSON(http.StatusBadRequest, gin.H{"msg": "file is required"})
return
}
ext := filepath.Ext(file.Filename)
catName := categorizeFile(ext)
safeName := uuid.New().String()[:8] + "_" + catName + ext
destPath := filepath.Join(env.WorkDir, "content", "fresh", safeName)
if err := c.SaveUploadedFile(file, destPath); err != nil {
slog.Error("failed to receive the file over http:", "error", err)
c.JSON(http.StatusInternalServerError, gin.H{"msg": "internal error"})
} else {
database.RegisterFile(db, catName, destPath)
c.JSON(http.StatusCreated, gin.H{"msg": "file has succesfully been uploaded"})
}
})
// define a route to check what is registered
r.GET("/api/available", func(c *gin.Context) {
files, err := database.GetFiles(db)
if err != nil {
slog.Error("failed to retrieve available files", "error", err)
c.JSON(http.StatusInternalServerError, gin.H{"msg": "internal error"})
return
}
c.JSON(http.StatusOK, files)
})
}
+36
View File
@@ -0,0 +1,36 @@
package database
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/schema"
)
func KickoffDatabase() (*gorm.DB, error) {
db, err := gorm.Open(sqlite.Open("garden.db"), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
})
if err != nil {
return nil, err
}
if err := db.AutoMigrate(&AppState{}); err != nil {
return nil, err
}
if err := db.AutoMigrate(&Files{}); err != nil {
return nil, err
}
// create the first row if it does not exist yet
if err := db.FirstOrCreate(&AppState{}, AppState{
ID: 1,
Mode: "unspecified",
Running: false,
}).Error; err != nil {
return nil, err
}
return db, nil
}
+19
View File
@@ -0,0 +1,19 @@
package database
type AppState struct {
ID int `gorm:"primaryKey"`
// Mode =
// 0: unspecified
// 1: video
// 2: presentation
// 3: internet URL
Mode string
Running bool
}
type Files struct {
ID int `gorm:"primaryKey"`
Mode string
Filename string
Filepath string
}
+29
View File
@@ -0,0 +1,29 @@
package database
import (
"path/filepath"
"gorm.io/gorm"
)
func GetAppState(db *gorm.DB) (AppState, error) {
var state AppState
return state, db.First(&state).Error
}
func GetFiles(db *gorm.DB) ([]Files, error) {
var files []Files
return files, db.Find(&files).Error
}
func RegisterFile(db *gorm.DB, category, fullPath string) error {
file := Files{
Mode: category,
Filename: filepath.Base(fullPath),
Filepath: fullPath,
}
return db.Create(&file).Error
}
+51
View File
@@ -0,0 +1,51 @@
package runtime
import (
"log/slog"
"os"
"path/filepath"
)
type Environment struct {
Version string
Codename string
Hostname string
Port string
WorkDir string
}
func safeGrab(key, fallback string) string {
if v, ok := os.LookupEnv(key); ok {
return v
}
return fallback
}
func GrabEnvironment() Environment {
return Environment{
Version: safeGrab("VERSION", "0.0.1"),
Codename: safeGrab("CODENAME", "Magical Anomaly"),
Hostname: safeGrab("HOSTNAME", "0.0.0.0"),
Port: safeGrab("PORT", "8080"),
WorkDir: safeGrab("OPERATIONDIR", "."),
}
}
func EnsureOperation(workDir string) error {
slog.Info("starting audit on: " + workDir)
nDirs := []string{
workDir,
filepath.Join(workDir, "content"),
filepath.Join(workDir, "content", "fresh"),
filepath.Join(workDir, "web"),
}
for _, p := range nDirs {
if err := os.MkdirAll(p, 0755); err != nil {
return err
}
}
return nil
}