Add /api/images

This commit is contained in:
nemunaire 2016-06-26 11:23:29 +02:00
parent a12d13aa00
commit 99e09acb56
3 changed files with 197 additions and 0 deletions

1
api.go
View File

@ -13,6 +13,7 @@ import (
type DispatchFunction func(*User, []string, io.ReadCloser) (interface{}, error)
var apiRoutes = map[string]*(map[string]struct{AuthFunction;DispatchFunction}){
"images": &ApiImagesRouting,
"version": &ApiVersionRouting,
}

44
api_images.go Normal file
View File

@ -0,0 +1,44 @@
package main
import (
"errors"
"io"
)
var ApiImagesRouting = map[string]struct{AuthFunction; DispatchFunction}{
"GET": {PublicPage, listImages},
"POST": {PublicPage, addImage},
"DELETE": {PrivatePage, hideImage},
}
func listImages(u *User, args []string, body io.ReadCloser) (interface{}, error) {
if len(args) < 1 {
return GetPublishedImages()
} else if args[0] == "last" {
return GetLastImage()
} else {
return GetPublishedImage(args[0])
}
}
func addImage(u *User, args []string, body io.ReadCloser) (interface{}, error) {
if len(args) < 1 {
return nil, errors.New("Need an image identifier to create")
} else if err := AddImage(args[0], body); err != nil {
return nil, err
} else {
return true, nil
}
}
func hideImage(u *User, args []string, body io.ReadCloser) (interface{}, error) {
if len(args) < 1 {
return nil, errors.New("Need an image identifier to delete")
} else if pict, err := GetPublishedImage(args[0]); err != nil {
return nil, errors.New("No matching image")
} else if err := pict.Unpublish(); err != nil {
return nil, err
} else {
return true, nil
}
}

152
picture.go Normal file
View File

@ -0,0 +1,152 @@
package main
import (
"errors"
"io"
"io/ioutil"
"image"
_ "image/gif"
"image/jpeg"
_ "image/png"
"os"
"path/filepath"
"sort"
"strconv"
"time"
)
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()
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
}
}