uploader/upload.go

197 lines
4.0 KiB
Go

package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"sync"
"time"
"github.com/google/uuid"
)
type Admin struct {
name string
}
type UploadState int
const (
inactive UploadState = iota
active
completed
)
type UploadContext struct {
maxSize int64
created time.Time
state UploadState
finalName string
}
type UploadDatabase struct {
data map[uuid.UUID]UploadContext
mtx sync.Mutex
}
var db UploadDatabase
func (d *UploadDatabase) commit(size int64, finalName string, lifefile time.Duration) uuid.UUID {
id := uuid.New()
d.mtx.Lock()
defer d.mtx.Unlock()
_, found := d.data[id]
if found {
return uuid.Max
}
d.data[id] = UploadContext{
created: time.Now(),
finalName: finalName,
maxSize: size,
state: inactive,
}
return id
}
func (d *UploadDatabase) exists(id uuid.UUID) bool {
d.mtx.Lock()
defer d.mtx.Unlock()
_, found := d.data[id]
return found
}
func (d *UploadDatabase) activate(id uuid.UUID) *UploadContext {
d.mtx.Lock()
defer d.mtx.Unlock()
// i, found := d.data[id]
return nil
}
func (d *UploadDatabase) deactivate(id uuid.UUID) {
}
func (d *UploadDatabase) getSize(id uuid.UUID) int64 {
d.mtx.Lock()
defer d.mtx.Unlock()
return d.data[id].maxSize
}
func initialize() {
db.data = make(map[uuid.UUID]UploadContext)
}
func adminHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./html/admin.html")
}
func generateHandler(w http.ResponseWriter, r *http.Request) {
var maxSizeBytes int64
var linkLifetime int64
var id uuid.UUID
var uploadLink string
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
}
var linkSettings struct {
Lifetime string `json:"lifetime"`
MaxSize string `json:"maxSize"`
SizeUnit string `json:"sizeUnit"`
}
err := json.NewDecoder(r.Body).Decode(&linkSettings)
if err != nil {
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
return
}
linkLifetime, err = strconv.ParseInt(linkSettings.Lifetime, 10, 64)
if err != nil {
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
return
}
maxSizeBytes, err = strconv.ParseInt(linkSettings.MaxSize, 10, 64)
if err != nil {
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
return
}
if linkSettings.SizeUnit == "GB" {
maxSizeBytes *= 1024 * 1024 * 1024
} else if linkSettings.SizeUnit == "MB" {
maxSizeBytes *= 1024 * 1024
} else {
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
return
}
id = db.commit(int64(maxSizeBytes), "untitled"+time.Now().String(), time.Duration(linkLifetime))
if id == uuid.Max {
http.Error(w, "Commit failed", http.StatusBadRequest)
return
}
uploadLink = fmt.Sprintf("http://localhost:8080/upload?key=%s", id)
response := map[string]string{"uploadLink": uploadLink}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(response); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
}
id, err := uuid.Parse(r.URL.Query().Get("key"))
if err != nil || !db.exists(id) {
http.ServeFile(w, r, "./html/user_bad.html")
return
}
if !r.URL.Query().Has("limit") {
q := r.URL.Query()
q.Set("limit", strconv.FormatInt(db.getSize(id), 10))
r.URL.RawQuery = q.Encode()
http.Redirect(w, r, r.URL.String(), http.StatusSeeOther)
return
}
http.ServeFile(w, r, "./html/user.html")
}
func fileHandler(w http.ResponseWriter, r *http.Request) {
}
func main() {
initialize()
os.MkdirAll("uploads", os.ModePerm)
http.HandleFunc("/admin", adminHandler)
http.HandleFunc("/generate", generateHandler)
http.HandleFunc("/upload", uploadHandler)
http.HandleFunc("/file", fileHandler)
// http.Handle("/", http.FileServer(http.Dir(".")))
// Start the server
fmt.Println("Starting server on :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Printf("Error starting server: %v", err)
}
}