167 lines
3.7 KiB
Go
167 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"io/ioutil"
|
|
"image"
|
|
_ "image/gif"
|
|
"image/jpeg"
|
|
_ "image/png"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/nfnt/resize"
|
|
)
|
|
|
|
type Picture struct {
|
|
path string
|
|
basename string
|
|
Name string `json:"name"`
|
|
UploadTime time.Time `json:"upload_time"`
|
|
}
|
|
|
|
type ByUploadTime []Picture
|
|
|
|
func (a ByUploadTime) Len() int { return len(a) }
|
|
func (a ByUploadTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
func (a ByUploadTime) Less(i, j int) bool { return a[i].UploadTime.Sub(a[j].UploadTime).Nanoseconds() < 0 }
|
|
|
|
func getImages(dir string) ([]Picture, error) {
|
|
if files, err := ioutil.ReadDir(dir); err != nil {
|
|
return nil, err
|
|
} else {
|
|
pictures := make([]Picture, 0)
|
|
for _, file := range files {
|
|
if !file.IsDir() {
|
|
filename := file.Name()
|
|
pictures = append(pictures, Picture{
|
|
filepath.Join(dir, filename), // Path
|
|
filename, // Basename
|
|
filename[:len(filename) - len(filepath.Ext(filename))], // Sanitized filename
|
|
file.ModTime(), // UploadTime
|
|
})
|
|
}
|
|
}
|
|
sort.Sort(ByUploadTime(pictures))
|
|
return pictures, nil
|
|
}
|
|
}
|
|
|
|
func GetNextImages() ([]Picture, error) {
|
|
return getImages(NextImgDir)
|
|
}
|
|
|
|
func GetPublishedImages() ([]Picture, error) {
|
|
return getImages(PublishedImgDir)
|
|
}
|
|
|
|
func GetLastImage() (Picture, error) {
|
|
if picts, err := GetPublishedImages(); err != nil {
|
|
return Picture{}, err
|
|
} else {
|
|
return picts[len(picts)-1], nil
|
|
}
|
|
}
|
|
|
|
func getImage(flist func() ([]Picture, error), fname string) (Picture, error) {
|
|
if picts, err := flist(); err != nil {
|
|
return Picture{}, err
|
|
} else if pid, err := strconv.Atoi(fname); err == nil {
|
|
if pid < len(picts) {
|
|
return picts[pid], nil
|
|
} else {
|
|
return Picture{}, errors.New("Invalid picture identifier")
|
|
}
|
|
} else {
|
|
for _, pict := range picts {
|
|
if pict.Name == fname || pict.basename == fname {
|
|
return pict, nil
|
|
}
|
|
}
|
|
return Picture{}, errors.New("No such picture")
|
|
}
|
|
}
|
|
|
|
func GetPublishedImage(fname string) (Picture, error) {
|
|
return getImage(GetPublishedImages, fname)
|
|
}
|
|
|
|
func GetNextImage(fname string) (Picture, error) {
|
|
return getImage(GetNextImages, fname)
|
|
}
|
|
|
|
func UniqueImage(filename string) (bool) {
|
|
if pict, _ := GetPublishedImage(filename); pict.path != "" {
|
|
return false
|
|
} else {
|
|
if pict, _ := GetNextImage(filename); pict.path != "" {
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
func AddImage(filename string, blob io.ReadCloser) (error) {
|
|
// Check the name is not already used
|
|
if ok := UniqueImage(filename); !ok {
|
|
return errors.New("This filename is already used, please choose another one.")
|
|
|
|
// Convert to JPEG
|
|
} else if img, _, err := image.Decode(blob); err != nil {
|
|
return err
|
|
|
|
// Save file
|
|
} else if fw, err := os.Create(filepath.Join(NextImgDir, filename + ".jpg")); err != nil {
|
|
return err
|
|
} else if err := jpeg.Encode(fw, img, nil); err != nil {
|
|
return err
|
|
} else {
|
|
fw.Close()
|
|
|
|
thumb := resize.Thumbnail(300, 185, img, resize.Lanczos3)
|
|
|
|
// Save thumbnail
|
|
if fw, err := os.Create(filepath.Join(ThumbsDir, filename + ".jpg")); err != nil {
|
|
return err
|
|
} else if err := jpeg.Encode(fw, thumb, nil); err != nil {
|
|
return err
|
|
} else {
|
|
fw.Close()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p Picture) Publish() (error) {
|
|
npath := filepath.Join(PublishedImgDir, p.basename)
|
|
if err := os.Rename(p.path, npath); err != nil {
|
|
return err
|
|
} else if err := os.Chtimes(npath, time.Now(), time.Now()); err != nil {
|
|
return err
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (p Picture) Unpublish() (error) {
|
|
if err := os.Rename(p.path, filepath.Join(NextImgDir, p.basename)); err != nil {
|
|
return err
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (p Picture) Remove() (error) {
|
|
if err := os.Remove(p.path); err != nil {
|
|
return err
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|