This repository has been archived on 2023-07-05. You can view files and clone it, but cannot push or open issues or pull requests.
clessy/mods/unsplash.go

228 lines
5.5 KiB
Go

package main
import (
"bytes"
"image"
_ "image/gif"
"image/jpeg"
_ "image/png"
"io/ioutil"
"log"
"math/rand"
"os"
"path/filepath"
"strings"
"git.fromouter.space/crunchy-rocks/draw2d"
"git.fromouter.space/crunchy-rocks/draw2d/draw2dimg"
"git.fromouter.space/crunchy-rocks/freetype"
"git.fromouter.space/hamcha/tg"
"github.com/disintegration/imaging"
)
var quoteFontData draw2d.FontData
var pics []string
func unsplash_init() {
fontfile, err := os.Open(*gillmt)
assert(err)
defer fontfile.Close()
bytes, err := ioutil.ReadAll(fontfile)
assert(err)
font, err := freetype.ParseFont(bytes)
assert(err)
quoteFontData = draw2d.FontData{"gillmt", draw2d.FontFamilySans, draw2d.FontStyleBold}
draw2d.RegisterFont(quoteFontData, font)
// Read all the pictures inside a folder and save them for later
files, err := ioutil.ReadDir(*unsplashpath)
assert(err)
for _, file := range files {
pics = append(pics, filepath.Join(*unsplashpath, file.Name()))
}
log.Println("[unsplash] Loaded!")
}
func stripUnreadable(r rune) rune {
if r == '\n' || r == '\t' {
return ' '
}
if r < 32 {
return -1
}
return r
}
func unsplash_message(broker *tg.Broker, update tg.APIMessage) {
if isCommand(update, "unsplash") {
text := ""
user := update.User
if update.ReplyTo != nil {
switch {
case update.ReplyTo.Text != nil:
text = *(update.ReplyTo.Text)
case update.ReplyTo.Caption != nil:
text = *(update.ReplyTo.Caption)
default:
broker.SendTextMessage(update.Chat, "Non c'e' niente di 'ispiratore' in questo..", &tg.MessageOptions{
ReplyID: &update.MessageID,
})
return
}
// For forwarded message take the original user
if update.FwdUser != nil {
user = *update.FwdUser
} else {
user = update.ReplyTo.User
}
} else {
if strings.Index(*(update.Text), " ") > 0 {
text = strings.TrimSpace(strings.SplitN(*(update.Text), " ", 2)[1])
}
}
// Cleanup chars
text = strings.Map(stripUnreadable, text)
author := user.FirstName
if user.LastName != "" {
author = user.FirstName + " " + user.LastName
}
author += " (" + user.Username + ")"
if strings.TrimSpace(text) == "" {
broker.SendTextMessage(update.Chat, "Non c'e' niente di 'ispiratore' in questo..", &tg.MessageOptions{
ReplyID: &update.MessageID,
})
return
}
file, err := os.Open(pics[rand.Intn(len(pics))])
if err != nil {
log.Printf("[unsplash] Could not open origina image file: %s\n", err.Error())
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &tg.MessageOptions{
ReplyID: &update.MessageID,
})
return
}
defer file.Close()
img, _, err := image.Decode(file)
if err != nil {
log.Printf("[unsplash] Image decode error: %s\n", err.Error())
broker.SendTextMessage(update.Chat, "<b>ERRORE</b>: Non riesco a leggere l'immagine", &tg.MessageOptions{
ReplyID: &update.MessageID,
})
return
}
broker.SendChatAction(update.Chat, tg.ActionUploadingPhoto)
// Darken image
img = imaging.AdjustBrightness(imaging.AdjustGamma(imaging.AdjustSigmoid(img, 0.5, -6.0), 0.8), -20)
// 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.Emojis = emojis
gc.SetFontData(quoteFontData)
gc.DrawImage(img)
gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White)
text = strings.ToUpper(strings.TrimSpace(text))
gc.Restore()
gc.Save()
// Detect appropriate font size
scale := iheight / iwidth * (iwidth / 10) * 0.8
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*1.2 > 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*1.2 > iwidth && iter < 10 {
scale *= (0.9 - 0.05*float64(iter))
gc.SetFontSize(scale)
left, top, right, bottom = gc.GetStringBounds(texts[longid])
width = right - left
iter++
}
}
texts = append(texts, author)
height := bottom - top + 20
margin := float64(height / 50)
txtheight := (height + margin) * float64(len(texts))
gc.Save()
for id, txt := range texts {
gc.Save()
left, _, right, _ = gc.GetStringBounds(txt)
width = right - left
x := (iwidth - width) / 2
y := (iheight-txtheight)/2 + (height+margin*2)*float64(id+1)
if id == len(texts)-1 {
gc.SetFontSize(scale * 0.7)
left, _, right, _ = gc.GetStringBounds(txt)
width = right - left
x = (iwidth - width) / 1.5
y = (iheight-txtheight)/2 + (height+margin)*float64(id+1) + margin*6
}
gc.Translate(x, y)
gc.StrokeString(txt)
gc.FillString(txt)
gc.Restore()
}
buf := new(bytes.Buffer)
err = jpeg.Encode(buf, timg, &(jpeg.Options{Quality: 80}))
if err != nil {
log.Printf("[unsplash] Image encode error: %s\n", err.Error())
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &tg.MessageOptions{
ReplyID: &update.MessageID,
})
return
}
broker.SendPhoto(update.Chat, buf.Bytes(), "quote.jpg", "", &tg.MessageOptions{
ReplyID: &update.MessageID,
})
}
}