01a692ab5b
Added tests for the word filter store. Added qgen.NewAcc() to reduce the amount of boilerplate needed for creating an accumulator. Exposed the RecordError method on the accumulator. Added an Add method to PluginList and removed AddPlugin() in favour of that. More panel buttons on Nox should be styled now. Added the panel_update_button_text phrase for future use. More errors might be caught in the thumbnailer now. Removed ls from .travis.yml, it was there for debugging Code Climate.
146 lines
3.7 KiB
Go
146 lines
3.7 KiB
Go
package common
|
|
|
|
import (
|
|
"image"
|
|
"image/gif"
|
|
"image/jpeg"
|
|
_ "image/png"
|
|
"os"
|
|
"strconv"
|
|
|
|
"../query_gen/lib"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func ThumbTask(thumbChan chan bool) {
|
|
for {
|
|
// Put this goroutine to sleep until we have work to do
|
|
<-thumbChan
|
|
|
|
// TODO: Use a real queue
|
|
acc := qgen.NewAcc()
|
|
err := acc.Select("users_avatar_queue").Columns("uid").Limit("0,5").EachInt(func(uid int) error {
|
|
// TODO: Do a bulk user fetch instead?
|
|
user, err := Users.Get(uid)
|
|
if err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
// Has the avatar been removed or already been processed by the thumbnailer?
|
|
if len(user.RawAvatar) < 2 || user.RawAvatar[1] == '.' {
|
|
_, _ = acc.Delete("users_avatar_queue").Where("uid = ?").Run(uid)
|
|
return nil
|
|
}
|
|
// This means it's an external image, they aren't currently implemented, but this is here for when they are
|
|
if user.RawAvatar[0] != '.' {
|
|
return nil
|
|
}
|
|
/*if user.RawAvatar == ".gif" {
|
|
return nil
|
|
}*/
|
|
if user.RawAvatar != ".png" && user.RawAvatar != ".jpg" && user.RawAvatar != ".jpeg" && user.RawAvatar != ".gif" {
|
|
return nil
|
|
}
|
|
|
|
err = Thumbnailer.Resize(user.RawAvatar[1:], "./uploads/avatar_"+strconv.Itoa(user.ID)+user.RawAvatar, "./uploads/avatar_"+strconv.Itoa(user.ID)+"_tmp"+user.RawAvatar, "./uploads/avatar_"+strconv.Itoa(user.ID)+"_w48"+user.RawAvatar, 48)
|
|
if err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
err = user.ChangeAvatar("." + user.RawAvatar)
|
|
if err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
_, err = acc.Delete("users_avatar_queue").Where("uid = ?").Run(uid)
|
|
return errors.WithStack(err)
|
|
})
|
|
if err != nil {
|
|
LogError(err)
|
|
}
|
|
if err = acc.FirstError(); err != nil {
|
|
LogError(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
var Thumbnailer ThumbnailerInt
|
|
|
|
type ThumbnailerInt interface {
|
|
Resize(format string, inPath string, tmpPath string, outPath string, width int) error
|
|
}
|
|
|
|
type RezThumbnailer struct {
|
|
}
|
|
|
|
func (thumb *RezThumbnailer) Resize(format string, inPath string, tmpPath string, outPath string, width int) error {
|
|
// TODO: Sniff the aspect ratio of the image and calculate the dest height accordingly, bug make sure it isn't excessively high
|
|
return nil
|
|
}
|
|
|
|
func (thumb *RezThumbnailer) resize(format string, inPath string, outPath string, width int, height int) error {
|
|
return nil
|
|
}
|
|
|
|
// ! Note: CaireThumbnailer can't handle gifs, so we'll have to either cap their sizes or have another resizer deal with them
|
|
type CaireThumbnailer struct {
|
|
}
|
|
|
|
func NewCaireThumbnailer() *CaireThumbnailer {
|
|
return &CaireThumbnailer{}
|
|
}
|
|
|
|
func precodeImage(format string, inPath string, tmpPath string) error {
|
|
imageFile, err := os.Open(inPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer imageFile.Close()
|
|
|
|
img, _, err := image.Decode(imageFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
outFile, err := os.Create(tmpPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer outFile.Close()
|
|
|
|
// TODO: Make sure animated gifs work after being encoded
|
|
if format == "gif" {
|
|
return gif.Encode(outFile, img, nil)
|
|
}
|
|
return jpeg.Encode(outFile, img, nil)
|
|
}
|
|
|
|
func (thumb *CaireThumbnailer) Resize(format string, inPath string, tmpPath string, outPath string, width int) error {
|
|
err := precodeImage(format, inPath, tmpPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
|
|
// TODO: Caire doesn't work. Try something else. Or get them to fix the index out of range. We get enough wins from re-encoding as jpeg anyway
|
|
/*imageFile, err := os.Open(tmpPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer imageFile.Close()
|
|
|
|
outFile, err := os.Create(outPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer outFile.Close()
|
|
|
|
p := &caire.Processor{NewWidth: width, Scale: true}
|
|
return p.Process(imageFile, outFile)*/
|
|
}
|
|
|
|
/*
|
|
type LilliputThumbnailer struct {
|
|
|
|
}
|
|
*/
|