mods: Add all the meme generation code
This commit is contained in:
parent
2152dd935e
commit
32612670a3
3 changed files with 170 additions and 3 deletions
1
Makefile
1
Makefile
|
@ -3,6 +3,7 @@ all: clessy-broker clessy-mods clessy-stats
|
|||
deps:
|
||||
go get github.com/boltdb/bolt/...
|
||||
go get github.com/golang/freetype
|
||||
go get github.com/llgcode/draw2d
|
||||
|
||||
install-tg:
|
||||
go install github.com/hamcha/clessy/tg
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
func initmods() {
|
||||
initviaggi()
|
||||
initmeme()
|
||||
}
|
||||
|
||||
func dispatch(broker *tg.Broker, update tg.APIMessage) {
|
||||
|
@ -26,10 +27,12 @@ func isCommand(update tg.APIMessage, cmdname string) bool {
|
|||
}
|
||||
|
||||
var botname *string
|
||||
var impact *string
|
||||
|
||||
func main() {
|
||||
brokerAddr := flag.String("broker", "localhost:7314", "Broker address:port")
|
||||
botname = flag.String("botname", "maudbot", "Bot name for /targetet@commands")
|
||||
impact = flag.String("impact", "impact.ttf", "Path to impact.ttf (Impact font)")
|
||||
flag.Parse()
|
||||
|
||||
initmods()
|
||||
|
@ -39,3 +42,9 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func assert(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
163
mods/memegen.go
163
mods/memegen.go
|
@ -1,15 +1,51 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"bytes"
|
||||
"image"
|
||||
_ "image/gif"
|
||||
"image/jpeg"
|
||||
_ "image/png"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/freetype"
|
||||
"github.com/hamcha/clessy/tg"
|
||||
"github.com/llgcode/draw2d"
|
||||
"github.com/llgcode/draw2d/draw2dimg"
|
||||
)
|
||||
|
||||
var memeFontData draw2d.FontData
|
||||
|
||||
func initmeme() {
|
||||
fontfile, err := os.Open(*impact)
|
||||
assert(err)
|
||||
defer fontfile.Close()
|
||||
|
||||
bytes, err := ioutil.ReadAll(fontfile)
|
||||
assert(err)
|
||||
|
||||
font, err := freetype.ParseFont(bytes)
|
||||
assert(err)
|
||||
|
||||
memeFontData := draw2d.FontData{"impact", draw2d.FontFamilySans, 0}
|
||||
draw2d.RegisterFont(memeFontData, font)
|
||||
}
|
||||
|
||||
func memegen(broker *tg.Broker, update tg.APIMessage) {
|
||||
if update.Photo != nil && update.Caption != nil {
|
||||
if strings.HasPrefix(*(update.Caption), "/meme") {
|
||||
caption := *(update.Caption)
|
||||
if strings.HasPrefix(caption, "/meme ") && len(caption) > 6 {
|
||||
idx := strings.Index(caption, ";")
|
||||
if idx < 0 {
|
||||
broker.SendTextMessage(update.Chat, "<b>Formato</b>: /meme TESTO IN ALTO<b>;</b>TESTO IN BASSO", &(update.MessageID))
|
||||
return
|
||||
}
|
||||
|
||||
txtup := caption[6:idx]
|
||||
txtdw := caption[idx+1:]
|
||||
|
||||
maxsz := 0
|
||||
photo := tg.APIPhotoSize{}
|
||||
for _, curphoto := range update.Photo {
|
||||
|
@ -18,7 +54,128 @@ func memegen(broker *tg.Broker, update tg.APIMessage) {
|
|||
photo = curphoto
|
||||
}
|
||||
}
|
||||
fmt.Println(photo)
|
||||
broker.GetFile(photo.FileID, func(broker *tg.Broker, data tg.BrokerUpdate) {
|
||||
img, _, err := image.Decode(bytes.NewReader(data.Bytes))
|
||||
if err != nil {
|
||||
broker.SendTextMessage(update.Chat, "<b>ERROR</b>: Non riesco a leggere l'immagine", &(update.MessageID))
|
||||
return
|
||||
}
|
||||
|
||||
//TODO Clean up this mess
|
||||
|
||||
// Create target image
|
||||
bounds := img.Bounds()
|
||||
iwidth := float64(bounds.Size().X)
|
||||
iheight := float64(bounds.Size().Y)
|
||||
|
||||
timg := image.NewRGBA(bounds)
|
||||
gc := draw2dimg.NewGraphicContext(timg)
|
||||
gc.SetStrokeColor(image.Black)
|
||||
gc.SetFillColor(image.White)
|
||||
gc.SetFontData(memeFontData)
|
||||
gc.DrawImage(img)
|
||||
|
||||
write := func(text string, istop bool) {
|
||||
text = strings.ToUpper(strings.TrimSpace(text))
|
||||
gc.Restore()
|
||||
gc.Save()
|
||||
|
||||
// Detect appropriate font size
|
||||
scale := iwidth / iheight * 200
|
||||
gc.SetFontSize(scale)
|
||||
gc.SetLineWidth(scale / 15)
|
||||
|
||||
// Get NEW bounds
|
||||
left, top, right, bottom := gc.GetStringBounds(text)
|
||||
|
||||
width := right - left
|
||||
texts := []string{text}
|
||||
if width > iwidth {
|
||||
// Split text
|
||||
texts = splitCenter(text)
|
||||
|
||||
// Get longest line
|
||||
longer := float64(0)
|
||||
longid := 0
|
||||
widths := make([]float64, len(texts))
|
||||
for id := range texts {
|
||||
tleft, _, tright, _ := gc.GetStringBounds(texts[id])
|
||||
widths[id] = tright - tleft
|
||||
if width > longer {
|
||||
longer = widths[id]
|
||||
longid = id
|
||||
}
|
||||
}
|
||||
|
||||
// Still too big? Decrease font size again
|
||||
iter := 0
|
||||
for width > iwidth && iter < 10 {
|
||||
left, _, right, _ = gc.GetStringBounds(texts[longid])
|
||||
gc.SetFontSize(scale * 0.8)
|
||||
width = right - left
|
||||
iter++
|
||||
}
|
||||
}
|
||||
|
||||
height := bottom - top
|
||||
margin := float64(10)
|
||||
lines := float64(len(texts) - 1)
|
||||
|
||||
gc.Save()
|
||||
for id, txt := range texts {
|
||||
gc.Save()
|
||||
left, _, right, _ = gc.GetStringBounds(txt)
|
||||
width = right - left
|
||||
|
||||
y := float64(0)
|
||||
if istop {
|
||||
y = (height-margin)*float64(id+1) + margin*5
|
||||
} else {
|
||||
y = iheight - (height * lines) + (height * float64(id)) - margin*5
|
||||
}
|
||||
|
||||
gc.Translate((iwidth-width)/2, y)
|
||||
gc.StrokeString(txt)
|
||||
gc.FillString(txt)
|
||||
gc.Restore()
|
||||
}
|
||||
}
|
||||
write(txtup, true)
|
||||
write(txtdw, false)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = jpeg.Encode(buf, timg, &(jpeg.Options{Quality: 80}))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func splitCenter(text string) []string {
|
||||
cindx := int(len(text) / 2)
|
||||
bs := 0
|
||||
md := 9999
|
||||
id := -1
|
||||
for i := 0; ; i++ {
|
||||
idx := strings.Index(text[bs:], " ")
|
||||
if idx < 0 {
|
||||
break
|
||||
}
|
||||
bs += idx + 1
|
||||
diff := abs(cindx - bs)
|
||||
if diff < md {
|
||||
md = diff
|
||||
id = bs - 1
|
||||
}
|
||||
}
|
||||
if id >= 0 {
|
||||
return []string{text[0:id], text[id+1:]}
|
||||
}
|
||||
return []string{text}
|
||||
}
|
||||
|
||||
func abs(i int) int {
|
||||
if i < 0 {
|
||||
return -i
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
|
Reference in a new issue