package main
import (
"bytes"
"fmt"
"go.etcd.io/bbolt"
"io"
"mime"
"net/http"
"os/exec"
"path/filepath"
"sophuwu.site/myweb/template"
"strings"
)
type DBFile struct {
Name string
Size int
}
func (f *DBFile) Valid() bool {
if f.Name == "" || strings.HasPrefix(f.Name, ".") || strings.HasPrefix(f.Name, "_") || f.Size == 0 {
return false
}
return true
}
func (f *DBFile) Set(name string, size int) {
f.Name = name
f.Size = size
}
func ListMedia() ([]DBFile, error) {
var list []DBFile
var t DBFile
err := DB.Bolt.View(func(tx *bbolt.Tx) error {
b := tx.Bucket([]byte("media"))
return b.ForEach(func(k, v []byte) error {
t.Set(string(k), len(v))
if t.Valid() {
list = append(list, t)
}
return nil
})
})
return list, err
}
func MediaHandler(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.Path, "/media/")
var err error
if path == "" {
var list []DBFile
list, err = ListMedia()
if CheckHttpErr(err, w, r, 500) {
return
}
d := template.Data("/media/", "Directory listing for /media/")
d.Set("Files", list)
d.Set("NoFiles", len(list))
err = template.Use(w, r, "filelist", d)
CheckHttpErr(err, w, r, 500)
return
}
var data []byte
data, err = DB.GetBytes("media", path)
if CheckHttpErr(err, w, r, 404) {
return
}
w.WriteHeader(200)
w.Header().Set("content-type", mime.TypeByExtension(filepath.Ext(path)))
w.Write(data)
}
func AddMedia(path string, data []byte) error {
return DB.SetBytes("media", path, data)
}
func ConvWebp(f io.Reader) (bytes.Buffer, error) {
cmd := exec.Command("convert", "-", "webp:-")
var data bytes.Buffer
cmd.Stdin = f
cmd.Stdout = &data
err := cmd.Run()
return data, err
}
func ManageMedia(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/manage/media/" {
HttpErr(w, r, 404)
return
}
if r.Method == "GET" {
d := template.Data("Manage media", "Upload media files")
d.Set("Media", "true")
err := template.Use(w, r, "edit", d)
CheckHttpErr(err, w, r, 500)
return
}
if r.Method == "POST" {
err := r.ParseMultipartForm(10 << 20)
if CheckHttpErr(err, w, r, 500) {
return
}
fh, h, err := r.FormFile("file1")
if CheckHttpErr(err, w, r, 500) {
return
}
defer fh.Close()
f := io.Reader(fh)
ext := filepath.Ext(h.Filename)
ext = strings.TrimPrefix(ext, ".")
name := filepath.Base(h.Filename)
var data bytes.Buffer
if ext == "jpg" || ext == "jpeg" || ext == "png" || ext == "gif" {
// convert to webp
name = strings.TrimSuffix(name, ext)
if !strings.HasSuffix(name, ".webp") {
name += ".webp"
}
name = strings.ReplaceAll(name, " ", "-")
name = strings.ReplaceAll(name, "..", ".")
data, err = ConvWebp(f)
} else {
_, err = data.ReadFrom(f)
}
if CheckHttpErr(err, w, r, 500) {
return
}
// add to db
err = AddMedia(name, data.Bytes())
if CheckHttpErr(err, w, r, 500) {
return
}
http.Redirect(w, r, "/media/", 302)
}
}
func DeleteMedia(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.Path, "/manage/delete/media/")
if path == "" {
list, err := ListMedia()
if CheckHttpErr(err, w, r, 500) {
return
}
d := template.Data("Delete media", "Delete media files")
d.Set("Files", list)
d.Set("NoFiles", len(list))
err = template.Use(w, r, "filelist", d)
CheckHttpErr(err, w, r, 500)
return
}
conf := r.URL.Query().Get("confirm")
if conf == "true" {
err := DB.Delete("media", path)
if CheckHttpErr(err, w, r, 500) {
return
}
http.Redirect(w, r, "/media/", 302)
}
w.Header().Set("content-type", "text/html")
w.WriteHeader(200)
fmt.Fprintf(w, "Are you sure you want to delete %s?
Yes
No", path, path)
}