diff --git a/mods/main.go b/mods/main.go index d3d4e58..ef341f4 100644 --- a/mods/main.go +++ b/mods/main.go @@ -10,12 +10,14 @@ import ( func initmods() { initviaggi() initmeme() + initunsplash() } func dispatch(broker *tg.Broker, update tg.APIMessage) { metafora(broker, update) viaggi(broker, update) memegen(broker, update) + unsplash(broker, update) } func isCommand(update tg.APIMessage, cmdname string) bool { @@ -29,11 +31,13 @@ func isCommand(update tg.APIMessage, cmdname string) bool { var botname *string var impact *string +var gillmt *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)") + gillmt = flag.String("gillmt", "gill.ttf", "Path to gill.ttf (Gill Sans MT font)") flag.Parse() initmods() diff --git a/mods/unsplash.go b/mods/unsplash.go new file mode 100644 index 0000000..a21c25f --- /dev/null +++ b/mods/unsplash.go @@ -0,0 +1,174 @@ +package main + +import ( + "bytes" + "image" + _ "image/gif" + "image/jpeg" + _ "image/png" + "io/ioutil" + "log" + "net/http" + "os" + "strings" + + "github.com/golang/freetype" + "github.com/hamcha/clessy/tg" + "github.com/llgcode/draw2d" + "github.com/llgcode/draw2d/draw2dimg" + + "github.com/disintegration/imaging" +) + +const unsplashUrl = "https://source.unsplash.com/random/1280x720" + +var quoteFontData draw2d.FontData + +func initunsplash() { + 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) +} + +func unsplash(broker *tg.Broker, update tg.APIMessage) { + if isCommand(update, "unsplash") { + text := "" + user := update.User + + if update.ReplyTo != nil { + text = *(update.ReplyTo.Text) + user = update.ReplyTo.User + } else { + text = strings.Replace(*(update.Text), "/unsplash ", "", 1) + } + + 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..", &update.MessageID) + return + } + + resp, err := http.Get(unsplashUrl) + if err != nil { + log.Println("[unsplash] HTTP request failed: %s\n", err.Error()) + broker.SendTextMessage(update.Chat, "ERRORE! @hamcha controlla la console!", &update.MessageID) + return + } + defer resp.Body.Close() + + img, _, err := image.Decode(resp.Body) + if err != nil { + log.Println("[unsplash] Image decode error: %s\n", err.Error()) + broker.SendTextMessage(update.Chat, "ERRORE: Non riesco a leggere l'immagine", &update.MessageID) + return + } + + // 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.SetFontData(memeFontData) + 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 > 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.1 > iwidth && iter < 10 { + log.Println("Warning, resizing!") + left, top, right, bottom = gc.GetStringBounds(texts[longid]) + scale *= (0.8 - 0.1*float64(iter)) + gc.SetFontSize(scale) + width = right - left + iter++ + } + } + + texts = append(texts, author) + height := bottom - top + 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)*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.Println("[unsplash] Image encode error: %s\n", err.Error()) + broker.SendTextMessage(update.Chat, "ERRORE! @hamcha controlla la console!", &update.MessageID) + return + } + broker.SendPhoto(update.Chat, buf.Bytes(), "quote.jpg", nil, &update.MessageID) + } +}