177
package main
import (
"crypto/md5"
"encoding/base64"
"net/http"
"sophuwu.site/myweb/template"
"strings"
"time"
)
// AnimInfo is a struct that holds information about an animation.
type AnimInfo struct {
ID string `storm:"id"`
Title string
Date string `storm:"index"`
Desc string
Imgs []string
Vids []string
}
// HasReqFields checks if all required fields have a non-empty value.
func (a *AnimInfo) HasReqFields() bool {
return a.Title != "" && a.Desc != "" && (len(a.Imgs)+len(a.Vids) > 0) && a.Date != "" && a.ID != ""
}
// GenAnimID generates an ID for an animation. It will generate a different ID
// each time it is called, even if the input is the same. This allows for
// multiple animations with the same title to be stored without conflict.
func GenAnimID(a AnimInfo) AnimInfo {
md := md5.New()
md.Write([]byte(time.Now().String() + a.Title))
a.ID = base64.URLEncoding.EncodeToString(md.Sum(nil))
if a.Date == "" {
a.Date = time.Now().Format("2006-01-02")
}
return a
}
// GetAnim retrieves AnimInfo from the database with the given ID.
// If the ID is not found, an error is returned.
func GetAnim(id string) (AnimInfo, error) {
var a AnimInfo
err := DB.One("ID", id, &a)
return a, err
}
// AnimDelete deletes an animation from the database with the given ID.
func AnimDelete(id string) error {
return DB.DeleteStruct(&AnimInfo{ID: id})
}
// GetAnims retrieves all animations from the database. The animations are
// sorted by date, with the most recent first in []AnimInfo.
func GetAnims() ([]AnimInfo, error) {
var anims []AnimInfo
err := DB.All(&anims)
if err != nil {
return nil, err
}
for i := 0; i < len(anims); i++ {
for j := i + 1; j < len(anims); j++ {
if anims[i].Date < anims[j].Date {
anims[i], anims[j] = anims[j], anims[i]
}
}
}
return anims, nil
}
// AnimHandler is a http.HandlerFunc that serves the animations page.
// It retrieves all animations from the database and displays them.
func AnimHandler(w http.ResponseWriter, r *http.Request) {
anims, err := GetAnims()
CheckHttpErr(err, w, r, 500)
d, err := GetPageData("anims")
if CheckHttpErr(err, w, r, 500) {
return
}
d.Set("Anims", anims)
d.Set("NoAnims", len(anims))
err = template.Use(w, r, "anims", d)
CheckHttpErr(err, w, r, 500)
}
// AnimManageList is a http.HandlerFunc that serves the animation manager list.
// It retrieves all animations from the database and displays them as a list.
// With each animation, there is a link to edit the details of that animation.
func AnimManageList(w http.ResponseWriter, r *http.Request) {
anims, err := GetAnims()
if CheckHttpErr(err, w, r, 500) {
return
}
opts := make([]UrlOpt, len(anims)+1)
opts[0] = UrlOpt{Name: "Add new animation", URL: "/manage/animation/?id=new"}
for i, a := range anims {
opts[i+1] = UrlOpt{Name: a.Title, URL: "/manage/animation/?id=" + a.ID}
}
d := template.Data("Manage animations", "List of animations")
d.Set("Options", opts)
err = template.Use(w, r, "manage", d)
CheckHttpErr(err, w, r, 500)
return
}
// AnimManager is a http.HandlerFunc that serves the animation manager. It
// allows the user to edit an existing animation or create a new one.
// If the ID is "new", a new animation is created. Otherwise, the animation
// with the given ID is retrieved from the database and displayed for editing.
func AnimManager(w http.ResponseWriter, r *http.Request) {
if "/manage/animation/" != r.URL.Path {
HttpErr(w, r, 404)
return
}
if r.Method == "GET" {
id := r.URL.Query().Get("id")
if id == "" {
AnimManageList(w, r)
return
}
var a AnimInfo
var err error
if id == "new" {
a.ID = "new"
} else {
a, err = GetAnim(id)
}
if CheckHttpErr(err, w, r, 404) {
return
}
data := template.Data("Edit animation", id)
data.Set("AnimUrl", "/manage/animation/")
data.Set("Anim", a)
err = template.Use(w, r, "edit", data)
CheckHttpErr(err, w, r, 500)
return
}
if r.Method == "POST" {
err := r.ParseForm()
if CheckHttpErr(err, w, r, 500) {
return
}
g := func(s string) string {
s = r.Form.Get(s)
return strings.TrimSpace(s)
}
gg := func(s string) []string {
var ss []string
for _, s = range strings.Split(g(s), "\n") {
s = strings.TrimSpace(s)
if s != "" {
ss = append(ss, s)
}
}
return ss
}
var a AnimInfo
a.ID = g("id")
a.Title = g("title")
a.Date = g("date")
a.Desc = g("desc")
a.Imgs = gg("imgs")
a.Vids = gg("vids")
if a.ID == "new" {
a = GenAnimID(a)
}
if !a.HasReqFields() {
HttpErr(w, r, 400)
return
}
err = DB.Save(&a)
if CheckHttpErr(err, w, r, 400) {
return
}
}
http.Redirect(w, r, "/animations/", http.StatusFound)
}