Add photo modules
This commit is contained in:
parent
53caadf9d9
commit
bc2ef31a3b
9 changed files with 508 additions and 6 deletions
2
go.mod
2
go.mod
|
@ -6,7 +6,7 @@ require (
|
||||||
git.fromouter.space/crunchy-rocks/draw2d v0.0.0-20190208101535-675e82cb6412
|
git.fromouter.space/crunchy-rocks/draw2d v0.0.0-20190208101535-675e82cb6412
|
||||||
git.fromouter.space/crunchy-rocks/emoji v0.0.0-20181116142102-2188aadaf093
|
git.fromouter.space/crunchy-rocks/emoji v0.0.0-20181116142102-2188aadaf093
|
||||||
git.fromouter.space/crunchy-rocks/freetype v0.0.0-20181116104610-3115318f2577
|
git.fromouter.space/crunchy-rocks/freetype v0.0.0-20181116104610-3115318f2577
|
||||||
git.fromouter.space/hamcha/tg v0.1.0
|
git.fromouter.space/hamcha/tg v0.2.1
|
||||||
git.sr.ht/~hamcha/containers v0.0.3
|
git.sr.ht/~hamcha/containers v0.0.3
|
||||||
github.com/cockroachdb/pebble v0.0.0-20220323190648-7ad3551b2050
|
github.com/cockroachdb/pebble v0.0.0-20220323190648-7ad3551b2050
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -6,8 +6,8 @@ git.fromouter.space/crunchy-rocks/emoji v0.0.0-20181116142102-2188aadaf093 h1:pa
|
||||||
git.fromouter.space/crunchy-rocks/emoji v0.0.0-20181116142102-2188aadaf093/go.mod h1:bmXZYbLNSGivLP7yQlcQ605b1H1L8kzxAk8A7sAEWx0=
|
git.fromouter.space/crunchy-rocks/emoji v0.0.0-20181116142102-2188aadaf093/go.mod h1:bmXZYbLNSGivLP7yQlcQ605b1H1L8kzxAk8A7sAEWx0=
|
||||||
git.fromouter.space/crunchy-rocks/freetype v0.0.0-20181116104610-3115318f2577 h1:rntW5kRu8s7dN8n7WWLHzAVZrnk7NS9YCdEQwA/O9pk=
|
git.fromouter.space/crunchy-rocks/freetype v0.0.0-20181116104610-3115318f2577 h1:rntW5kRu8s7dN8n7WWLHzAVZrnk7NS9YCdEQwA/O9pk=
|
||||||
git.fromouter.space/crunchy-rocks/freetype v0.0.0-20181116104610-3115318f2577/go.mod h1:MlK0wT7XDuAuw0l/Z+Es2OHozCbBb2r9VxOy8bU58ow=
|
git.fromouter.space/crunchy-rocks/freetype v0.0.0-20181116104610-3115318f2577/go.mod h1:MlK0wT7XDuAuw0l/Z+Es2OHozCbBb2r9VxOy8bU58ow=
|
||||||
git.fromouter.space/hamcha/tg v0.1.0 h1:cJwL8pElkBtaDn7Bxa14zvlnBTTK8LdcCtcbBg7hEvk=
|
git.fromouter.space/hamcha/tg v0.2.1 h1:cN14BhgbRLwYs4LkiKCKD9lDxwzbrpuRkQ6Buk4LdFw=
|
||||||
git.fromouter.space/hamcha/tg v0.1.0/go.mod h1:aIFj7n5FP+Zr/Zv6I6Kq4ZqhRxC12gXFQcC3iOakv9M=
|
git.fromouter.space/hamcha/tg v0.2.1/go.mod h1:aIFj7n5FP+Zr/Zv6I6Kq4ZqhRxC12gXFQcC3iOakv9M=
|
||||||
git.sr.ht/~hamcha/containers v0.0.3 h1:obG9X8s5iOIahVe+EGpkBDYmUAO78oTi9Y9gRurt334=
|
git.sr.ht/~hamcha/containers v0.0.3 h1:obG9X8s5iOIahVe+EGpkBDYmUAO78oTi9Y9gRurt334=
|
||||||
git.sr.ht/~hamcha/containers v0.0.3/go.mod h1:RiZphUpy9t6EnL4Gf6uzByM9QrBoqRCEPo7kz2wzbhE=
|
git.sr.ht/~hamcha/containers v0.0.3/go.mod h1:RiZphUpy9t6EnL4Gf6uzByM9QrBoqRCEPo7kz2wzbhE=
|
||||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||||
|
|
4
main.go
4
main.go
|
@ -9,9 +9,11 @@ import (
|
||||||
|
|
||||||
"git.fromouter.space/crunchy-rocks/clessy-ng/modules"
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules"
|
||||||
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/macro"
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/macro"
|
||||||
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/meme"
|
||||||
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/metafora"
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/metafora"
|
||||||
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/proverbio"
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/proverbio"
|
||||||
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/remind"
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/remind"
|
||||||
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/snapchat"
|
||||||
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/unsplash"
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules/unsplash"
|
||||||
"git.fromouter.space/crunchy-rocks/clessy-ng/utils"
|
"git.fromouter.space/crunchy-rocks/clessy-ng/utils"
|
||||||
|
|
||||||
|
@ -26,6 +28,8 @@ var mods = map[string]modules.Module{
|
||||||
"macro": ¯o.Module{},
|
"macro": ¯o.Module{},
|
||||||
"remind": &remind.Module{},
|
"remind": &remind.Module{},
|
||||||
"unsplash": &unsplash.Module{},
|
"unsplash": &unsplash.Module{},
|
||||||
|
"snapchat": &snapchat.Module{},
|
||||||
|
"meme": &meme.Module{},
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkErr(err error, message string, args ...interface{}) {
|
func checkErr(err error, message string, args ...interface{}) {
|
||||||
|
|
233
modules/meme/mod.go
Normal file
233
modules/meme/mod.go
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
package meme
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"image"
|
||||||
|
_ "image/gif"
|
||||||
|
"image/jpeg"
|
||||||
|
_ "image/png"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules"
|
||||||
|
"git.fromouter.space/crunchy-rocks/clessy-ng/utils"
|
||||||
|
|
||||||
|
"git.fromouter.space/crunchy-rocks/draw2d"
|
||||||
|
"git.fromouter.space/crunchy-rocks/draw2d/draw2dimg"
|
||||||
|
"git.fromouter.space/crunchy-rocks/emoji"
|
||||||
|
"git.fromouter.space/crunchy-rocks/freetype"
|
||||||
|
"git.fromouter.space/hamcha/tg"
|
||||||
|
)
|
||||||
|
|
||||||
|
var memeFontData draw2d.FontData
|
||||||
|
|
||||||
|
type Module struct {
|
||||||
|
client *tg.Telegram
|
||||||
|
name string
|
||||||
|
emojis emoji.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) Initialize(options modules.ModuleOptions) error {
|
||||||
|
m.client = options.API
|
||||||
|
m.name = options.Name
|
||||||
|
m.emojis = options.Emojis
|
||||||
|
|
||||||
|
rand.Seed(time.Now().Unix())
|
||||||
|
|
||||||
|
fontfile := utils.RequireEnv("CLESSY_MEME_FONT")
|
||||||
|
bytes, err := os.ReadFile(fontfile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
font, err := freetype.ParseFont(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
memeFontData = draw2d.FontData{
|
||||||
|
Name: "impact",
|
||||||
|
Family: draw2d.FontFamilySans,
|
||||||
|
Style: 0,
|
||||||
|
}
|
||||||
|
draw2d.RegisterFont(memeFontData, font)
|
||||||
|
|
||||||
|
log.Println("[meme] Loaded!")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) OnUpdate(update tg.APIUpdate) {
|
||||||
|
// Not a message? Ignore
|
||||||
|
if update.Message == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
message := *update.Message
|
||||||
|
|
||||||
|
// Make replies work
|
||||||
|
if message.ReplyTo != nil && message.Text != nil && message.ReplyTo.Photo != nil {
|
||||||
|
message.Photo = message.ReplyTo.Photo
|
||||||
|
message.Caption = message.Text
|
||||||
|
}
|
||||||
|
|
||||||
|
if message.Photo != nil && message.Caption != nil {
|
||||||
|
caption := *(message.Caption)
|
||||||
|
if strings.HasPrefix(caption, "/meme ") && len(caption) > 6 {
|
||||||
|
idx := strings.Index(caption, ";")
|
||||||
|
if idx < 0 {
|
||||||
|
m.client.SendTextMessage(tg.ClientTextMessageData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Text: "<b>Formato</b>: /meme TESTO IN ALTO<b>;</b>TESTO IN BASSO",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
txtup := caption[6:idx]
|
||||||
|
txtdw := caption[idx+1:]
|
||||||
|
|
||||||
|
maxsz := 0
|
||||||
|
photo := tg.APIPhotoSize{}
|
||||||
|
for _, curphoto := range message.Photo {
|
||||||
|
if curphoto.Width > maxsz {
|
||||||
|
maxsz = curphoto.Width
|
||||||
|
photo = curphoto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byt, err := m.client.GetFile(tg.FileRequestData{
|
||||||
|
FileID: photo.FileID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[memegen] Received error: %s\n", err.Error())
|
||||||
|
m.client.SendTextMessage(tg.ClientTextMessageData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Text: "<b>ERRORE!</b> @hamcha controlla la console!",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
img, _, err := image.Decode(bytes.NewReader(byt))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[memegen] Image decode error: %s\n", err.Error())
|
||||||
|
m.client.SendTextMessage(tg.ClientTextMessageData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Text: "<b>ERRORE!</b> Non riesco a leggere l'immagine",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.client.SendChatAction(tg.ClientChatActionData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Action: tg.ActionUploadingPhoto,
|
||||||
|
})
|
||||||
|
|
||||||
|
//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.Emojis = m.emojis
|
||||||
|
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 := iheight / iwidth * (iwidth / 10)
|
||||||
|
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 = utils.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 {
|
||||||
|
log.Println("Warning, resizing!")
|
||||||
|
gc.SetFontSize(scale * (0.8 - 0.1*float64(iter)))
|
||||||
|
left, top, right, bottom = gc.GetStringBounds(texts[longid])
|
||||||
|
width = right - left
|
||||||
|
iter++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
height := bottom - top
|
||||||
|
margin := float64(height / 50)
|
||||||
|
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}))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[memegen] Image encode error: %s\n", err.Error())
|
||||||
|
m.client.SendTextMessage(tg.ClientTextMessageData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Text: "<b>ERRORE!</b> @hamcha controlla la console!",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.client.SendPhoto(tg.ClientPhotoData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Bytes: buf.Bytes(),
|
||||||
|
Filename: "meme.jpg",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
206
modules/snapchat/mod.go
Normal file
206
modules/snapchat/mod.go
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
package snapchat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
_ "image/gif"
|
||||||
|
"image/jpeg"
|
||||||
|
_ "image/png"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.fromouter.space/crunchy-rocks/clessy-ng/modules"
|
||||||
|
"git.fromouter.space/crunchy-rocks/clessy-ng/utils"
|
||||||
|
|
||||||
|
"git.fromouter.space/crunchy-rocks/draw2d"
|
||||||
|
"git.fromouter.space/crunchy-rocks/draw2d/draw2dimg"
|
||||||
|
"git.fromouter.space/crunchy-rocks/emoji"
|
||||||
|
"git.fromouter.space/crunchy-rocks/freetype"
|
||||||
|
"git.fromouter.space/hamcha/tg"
|
||||||
|
)
|
||||||
|
|
||||||
|
var snapFontData draw2d.FontData
|
||||||
|
|
||||||
|
type Module struct {
|
||||||
|
client *tg.Telegram
|
||||||
|
name string
|
||||||
|
emojis emoji.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) Initialize(options modules.ModuleOptions) error {
|
||||||
|
m.client = options.API
|
||||||
|
m.name = options.Name
|
||||||
|
m.emojis = options.Emojis
|
||||||
|
|
||||||
|
rand.Seed(time.Now().Unix())
|
||||||
|
|
||||||
|
fontfile := utils.RequireEnv("CLESSY_SNAPCHAT_FONT")
|
||||||
|
bytes, err := os.ReadFile(fontfile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
font, err := freetype.ParseFont(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
snapFontData = draw2d.FontData{
|
||||||
|
Name: "sourcesans",
|
||||||
|
Family: draw2d.FontFamilySans,
|
||||||
|
Style: draw2d.FontStyleBold,
|
||||||
|
}
|
||||||
|
draw2d.RegisterFont(snapFontData, font)
|
||||||
|
|
||||||
|
log.Println("[snapchat] Loaded!")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) OnUpdate(update tg.APIUpdate) {
|
||||||
|
// Not a message? Ignore
|
||||||
|
if update.Message == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
message := *update.Message
|
||||||
|
|
||||||
|
// Make replies work
|
||||||
|
if message.ReplyTo != nil && message.Text != nil && message.ReplyTo.Photo != nil {
|
||||||
|
message.Photo = message.ReplyTo.Photo
|
||||||
|
message.Caption = message.Text
|
||||||
|
}
|
||||||
|
|
||||||
|
if message.Photo != nil && message.Caption != nil {
|
||||||
|
caption := *(message.Caption)
|
||||||
|
if strings.HasPrefix(caption, "/snap ") && len(caption) > 6 {
|
||||||
|
txt := strings.TrimSpace(caption[6:])
|
||||||
|
|
||||||
|
maxsz := 0
|
||||||
|
photo := tg.APIPhotoSize{}
|
||||||
|
for _, curphoto := range message.Photo {
|
||||||
|
if curphoto.Width > maxsz {
|
||||||
|
maxsz = curphoto.Width
|
||||||
|
photo = curphoto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byt, err := m.client.GetFile(tg.FileRequestData{
|
||||||
|
FileID: photo.FileID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[snapchat] Received error: %s\n", err.Error())
|
||||||
|
m.client.SendTextMessage(tg.ClientTextMessageData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Text: "<b>ERRORE!</b> @hamcha controlla la console!",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
img, _, err := image.Decode(bytes.NewReader(byt))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[snapchat] Image decode error: %s\n", err.Error())
|
||||||
|
m.client.SendTextMessage(tg.ClientTextMessageData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Text: "<b>ERRORE!</b> Non riesco a leggere l'immagine",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.client.SendChatAction(tg.ClientChatActionData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Action: tg.ActionUploadingPhoto,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create target image
|
||||||
|
bounds := img.Bounds()
|
||||||
|
iwidth := float64(bounds.Size().Y) / 1.6
|
||||||
|
iheight := float64(bounds.Size().Y)
|
||||||
|
|
||||||
|
repos := iwidth < float64(bounds.Size().X)
|
||||||
|
if !repos {
|
||||||
|
iwidth = float64(bounds.Size().X)
|
||||||
|
}
|
||||||
|
|
||||||
|
timg := image.NewRGBA(image.Rect(0, 0, int(iwidth), int(iheight)))
|
||||||
|
gc := draw2dimg.NewGraphicContext(timg)
|
||||||
|
gc.Emojis = m.emojis
|
||||||
|
gc.SetFontData(snapFontData)
|
||||||
|
|
||||||
|
gc.Save()
|
||||||
|
if repos {
|
||||||
|
gc.Translate(-(float64(bounds.Size().X)-iwidth)/2, 0)
|
||||||
|
}
|
||||||
|
gc.DrawImage(img)
|
||||||
|
gc.Restore()
|
||||||
|
|
||||||
|
scale := iwidth / 25
|
||||||
|
gc.SetFontSize(scale)
|
||||||
|
|
||||||
|
lineMargin := scale / 3
|
||||||
|
boxMargin := lineMargin
|
||||||
|
topMargin := lineMargin / 6
|
||||||
|
write := func(text string, startHeight float64) {
|
||||||
|
texts := utils.WordWrap(gc, strings.TrimSpace(text), iwidth*0.9)
|
||||||
|
totalHeight := startHeight
|
||||||
|
firstLine := 0.
|
||||||
|
for _, txt := range texts {
|
||||||
|
_, top, _, bottom := gc.GetStringBounds(txt)
|
||||||
|
height := (bottom - top)
|
||||||
|
if firstLine == 0 {
|
||||||
|
firstLine = height
|
||||||
|
}
|
||||||
|
totalHeight += lineMargin + height
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw background
|
||||||
|
starty := startHeight - boxMargin - topMargin - firstLine
|
||||||
|
endy := totalHeight + boxMargin - firstLine
|
||||||
|
gc.Save()
|
||||||
|
gc.SetFillColor(color.RGBA{0, 0, 0, 160})
|
||||||
|
gc.BeginPath()
|
||||||
|
gc.MoveTo(0, starty)
|
||||||
|
gc.LineTo(iwidth, starty)
|
||||||
|
gc.LineTo(iwidth, endy)
|
||||||
|
gc.LineTo(0, endy)
|
||||||
|
gc.Close()
|
||||||
|
gc.Fill()
|
||||||
|
gc.Restore()
|
||||||
|
|
||||||
|
// Write lines
|
||||||
|
gc.SetFillColor(image.White)
|
||||||
|
height := startHeight
|
||||||
|
for _, txt := range texts {
|
||||||
|
left, top, right, bottom := gc.GetStringBounds(txt)
|
||||||
|
width := right - left
|
||||||
|
gc.FillStringAt(txt, (iwidth-width)/2, height)
|
||||||
|
height += lineMargin + (bottom - top)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write(txt, (rand.Float64()*0.4+0.3)*iheight)
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = jpeg.Encode(buf, timg, &(jpeg.Options{Quality: 80}))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[snapchat] Image encode error: %s\n", err.Error())
|
||||||
|
m.client.SendTextMessage(tg.ClientTextMessageData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Text: "<b>ERRORE!</b> @hamcha controlla la console!",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.client.SendPhoto(tg.ClientPhotoData{
|
||||||
|
ChatID: message.Chat.ChatID,
|
||||||
|
Bytes: buf.Bytes(),
|
||||||
|
Filename: "meme.jpg",
|
||||||
|
ReplyID: &message.MessageID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package unsplash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
|
||||||
"image"
|
"image"
|
||||||
_ "image/gif"
|
_ "image/gif"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
|
@ -255,7 +254,7 @@ func (m *Module) OnUpdate(update tg.APIUpdate) {
|
||||||
}
|
}
|
||||||
m.client.SendPhoto(tg.ClientPhotoData{
|
m.client.SendPhoto(tg.ClientPhotoData{
|
||||||
ChatID: message.Chat.ChatID,
|
ChatID: message.Chat.ChatID,
|
||||||
Bytes: base64.StdEncoding.EncodeToString(buf.Bytes()),
|
Bytes: buf.Bytes(),
|
||||||
Filename: "quote.jpg",
|
Filename: "quote.jpg",
|
||||||
ReplyID: &message.MessageID,
|
ReplyID: &message.MessageID,
|
||||||
})
|
})
|
||||||
|
|
1
run.ps1
1
run.ps1
|
@ -6,5 +6,6 @@ $env:CLESSY_EMOJI_PATH = "_data"
|
||||||
$env:CLESSY_UNSPLASH_FONT = "_data/gill.ttf"
|
$env:CLESSY_UNSPLASH_FONT = "_data/gill.ttf"
|
||||||
$env:CLESSY_UNSPLASH_BG_PATH = "_data/pics"
|
$env:CLESSY_UNSPLASH_BG_PATH = "_data/pics"
|
||||||
$env:CLESSY_MEME_FONT = "_data/impact.ttf"
|
$env:CLESSY_MEME_FONT = "_data/impact.ttf"
|
||||||
|
$env:CLESSY_SNAPCHAT_FONT = "_data/source.ttf"
|
||||||
mkdir -force _data/pics
|
mkdir -force _data/pics
|
||||||
go run .
|
go run .
|
1
run.sh
1
run.sh
|
@ -5,5 +5,6 @@ export CLESSY_DB_DIR=_data/db
|
||||||
export CLESSY_EMOJI_PATH=_data
|
export CLESSY_EMOJI_PATH=_data
|
||||||
export CLESSY_UNSPLASH_FONT=_data/gill.ttf
|
export CLESSY_UNSPLASH_FONT=_data/gill.ttf
|
||||||
export CLESSY_MEME_FONT=_data/impact.ttf
|
export CLESSY_MEME_FONT=_data/impact.ttf
|
||||||
|
export CLESSY_SNAPCHAT_FONT=_data/source.ttf
|
||||||
mkdir -p _data/pics
|
mkdir -p _data/pics
|
||||||
go run .
|
go run .
|
|
@ -1,6 +1,11 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"git.fromouter.space/crunchy-rocks/draw2d"
|
||||||
|
)
|
||||||
|
|
||||||
func abs(i int) int {
|
func abs(i int) int {
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
|
@ -30,3 +35,56 @@ func SplitCenter(text string) []string {
|
||||||
}
|
}
|
||||||
return []string{strings.TrimSpace(text[:whitespaceBackIndex]), strings.TrimSpace(text[whitespaceBackIndex:])}
|
return []string{strings.TrimSpace(text[:whitespaceBackIndex]), strings.TrimSpace(text[whitespaceBackIndex:])}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Word wrapping code from https://github.com/fogleman/gg
|
||||||
|
// Copyright (C) 2016 Michael Fogleman
|
||||||
|
// Licensed under MIT (https://github.com/fogleman/gg/blob/master/LICENSE.md)
|
||||||
|
|
||||||
|
func splitOnSpace(x string) []string {
|
||||||
|
var result []string
|
||||||
|
pi := 0
|
||||||
|
ps := false
|
||||||
|
for i, c := range x {
|
||||||
|
s := unicode.IsSpace(c)
|
||||||
|
if s != ps && i > 0 {
|
||||||
|
result = append(result, x[pi:i])
|
||||||
|
pi = i
|
||||||
|
}
|
||||||
|
ps = s
|
||||||
|
}
|
||||||
|
result = append(result, x[pi:])
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func WordWrap(gc draw2d.GraphicContext, s string, width float64) []string {
|
||||||
|
var result []string
|
||||||
|
for _, line := range strings.Split(s, "\n") {
|
||||||
|
fields := splitOnSpace(line)
|
||||||
|
if len(fields)%2 == 1 {
|
||||||
|
fields = append(fields, "")
|
||||||
|
}
|
||||||
|
x := ""
|
||||||
|
for i := 0; i < len(fields); i += 2 {
|
||||||
|
left, _, right, _ := gc.GetStringBounds(x + fields[i])
|
||||||
|
w := right - left
|
||||||
|
if w > width {
|
||||||
|
if x == "" {
|
||||||
|
result = append(result, fields[i])
|
||||||
|
x = ""
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
result = append(result, x)
|
||||||
|
x = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x += fields[i] + fields[i+1]
|
||||||
|
}
|
||||||
|
if x != "" {
|
||||||
|
result = append(result, x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, line := range result {
|
||||||
|
result[i] = strings.TrimSpace(line)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue