diff --git a/main.go b/main.go index 4ccde0c..b3b3e35 100644 --- a/main.go +++ b/main.go @@ -4,12 +4,14 @@ package main import ( "flag" - "github.com/velour/catbase/plugins/emojy" "io" "math/rand" "os" "time" + "github.com/velour/catbase/plugins/cowboy" + "github.com/velour/catbase/plugins/emojy" + "github.com/velour/catbase/bot/msg" "github.com/velour/catbase/connectors/discord" "github.com/velour/catbase/plugins/giphy" @@ -170,6 +172,7 @@ func main() { b.AddPlugin(rest.New(b)) b.AddPlugin(quotegame.New(b)) b.AddPlugin(emojy.New(b)) + b.AddPlugin(cowboy.New(b)) // catches anything left, will always return true b.AddPlugin(fact.New(b)) diff --git a/plugins/cowboy/cowboy.go b/plugins/cowboy/cowboy.go new file mode 100644 index 0000000..fbb83f7 --- /dev/null +++ b/plugins/cowboy/cowboy.go @@ -0,0 +1,50 @@ +package cowboy + +import ( + "regexp" + + "github.com/rs/zerolog/log" + "github.com/velour/catbase/bot" + "github.com/velour/catbase/config" +) + +type Cowboy struct { + b bot.Bot + c *config.Config +} + +func New(b bot.Bot) *Cowboy { + c := Cowboy{ + b: b, + c: b.Config(), + } + c.register() + c.registerWeb() + return &c +} + +func (p *Cowboy) register() { + tbl := bot.HandlerTable{ + { + Kind: bot.Message, IsCmd: false, + Regex: regexp.MustCompile(`(?i)^:cowboy_(?P.+):$`), + Handler: func(r bot.Request) bool { + p.makeCowboy(r) + return true + }, + }, + } + p.b.RegisterTable(p, tbl) +} + +func (p *Cowboy) makeCowboy(r bot.Request) { + log.Debug().Msgf("makeCowboy: %s", r.Values["what"]) + base := p.c.Get("baseURL", "http://127.0.0.1:1337") + u := base + "/cowboy/img/" + r.Values["what"] + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "", bot.ImageAttachment{ + URL: u, + AltTxt: r.Msg.Body, + Width: 64, + Height: 64, + }) +} diff --git a/plugins/cowboy/cowboy_image.go b/plugins/cowboy/cowboy_image.go new file mode 100644 index 0000000..4e15293 --- /dev/null +++ b/plugins/cowboy/cowboy_image.go @@ -0,0 +1,82 @@ +package cowboy + +import ( + "bytes" + "fmt" + "image" + "image/draw" + "image/png" + "os" + "path" + + "github.com/nfnt/resize" + "github.com/velour/catbase/config" + "github.com/velour/catbase/plugins/emojy" +) + +func getEmojy(c *config.Config, name string) (image.Image, error) { + files, _, err := emojy.AllFiles(c) + if err != nil { + return nil, err + } + fname, ok := files[name] + if !ok { + return nil, fmt.Errorf("could not find emojy: %s", name) + } + f, err := os.Open(fname) + if err != nil { + return nil, err + } + img, _, err := image.Decode(f) + if err != nil { + return nil, err + } + return img, nil +} + +func getCowboyHat(c *config.Config) (image.Image, error) { + emojyPath := c.Get("emojy.path", "emojy") + p := path.Join(emojyPath, c.Get("cowboy.hatname", "hat.png")) + f, err := os.Open(p) + if err != nil { + return nil, err + } + img, _, err := image.Decode(f) + if err != nil { + return nil, err + } + return img, nil +} + +func cowboyifyImage(c *config.Config, input image.Image) (image.Image, error) { + hat, err := getCowboyHat(c) + if err != nil { + return nil, err + } + targetW := uint(c.GetInt("cowboy.targetw", 64)) + hatW, hatH := float64(hat.Bounds().Max.X), float64(hat.Bounds().Max.Y) + newH := uint(float64(targetW) / hatW * hatH) + hat = resize.Resize(targetW, newH, hat, resize.MitchellNetravali) + input = resize.Resize(targetW, targetW, input, resize.MitchellNetravali) + dst := image.NewRGBA(image.Rect(0, 0, 64, 64)) + draw.Draw(dst, input.Bounds(), input, image.Point{}, draw.Src) + draw.Draw(dst, hat.Bounds(), hat, image.Point{}, draw.Over) + return dst, nil +} + +func cowboy(c *config.Config, name string) ([]byte, error) { + emojy, err := getEmojy(c, name) + if err != nil { + return nil, err + } + img, err := cowboyifyImage(c, emojy) + if err != nil { + return nil, err + } + w := bytes.NewBuffer([]byte{}) + err = png.Encode(w, img) + if err != nil { + return nil, err + } + return w.Bytes(), nil +} diff --git a/plugins/cowboy/web.go b/plugins/cowboy/web.go new file mode 100644 index 0000000..39ec95b --- /dev/null +++ b/plugins/cowboy/web.go @@ -0,0 +1,26 @@ +package cowboy + +import ( + "fmt" + "net/http" + + "github.com/go-chi/chi/v5" +) + +func (p *Cowboy) registerWeb() { + r := chi.NewRouter() + r.HandleFunc("/img/{what}", p.handleImage) + p.b.RegisterWeb(r, "/cowboy") +} + +func (p *Cowboy) handleImage(w http.ResponseWriter, r *http.Request) { + what := chi.URLParam(r, "what") + img, err := cowboy(p.c, what) + if err != nil { + w.WriteHeader(500) + fmt.Fprintf(w, "Error: %s", err) + return + } + w.Header().Add("Content-Type", "image/png") + w.Write(img) +} diff --git a/plugins/emojy/emojy.go b/plugins/emojy/emojy.go index d28211a..33f51cc 100644 --- a/plugins/emojy/emojy.go +++ b/plugins/emojy/emojy.go @@ -4,8 +4,6 @@ import ( "bytes" "encoding/base64" "fmt" - "github.com/fogleman/gg" - "github.com/gabriel-vasile/mimetype" "math" "os" "path" @@ -14,6 +12,9 @@ import ( "strings" "time" + "github.com/fogleman/gg" + "github.com/gabriel-vasile/mimetype" + "github.com/forPelevin/gomoji" "github.com/jmoiron/sqlx" "github.com/rs/zerolog/log" @@ -192,11 +193,11 @@ func (p *EmojyPlugin) allCounts() (map[string][]EmojyCount, error) { return out, nil } -func (p *EmojyPlugin) allFiles() (map[string]string, map[string]string, error) { +func AllFiles(c *config.Config) (map[string]string, map[string]string, error) { files := map[string]string{} urls := map[string]string{} - emojyPath := p.c.Get("emojy.path", "emojy") - baseURL := p.c.Get("emojy.baseURL", "/emojy/file") + emojyPath := c.Get("emojy.path", "emojy") + baseURL := c.Get("emojy.baseURL", "/emojy/file") entries, err := os.ReadDir(emojyPath) if err != nil { return nil, nil, err @@ -213,7 +214,7 @@ func (p *EmojyPlugin) allFiles() (map[string]string, map[string]string, error) { } func (p *EmojyPlugin) isKnownEmojy(name string) (bool, string, string, error) { - allFiles, allURLs, err := p.allFiles() + allFiles, allURLs, err := AllFiles(p.c) if err != nil { return false, "", "", err } diff --git a/plugins/emojy/web.go b/plugins/emojy/web.go index 9275269..e50b6bd 100644 --- a/plugins/emojy/web.go +++ b/plugins/emojy/web.go @@ -4,8 +4,6 @@ import ( "embed" "encoding/json" "fmt" - "github.com/go-chi/chi/v5" - "github.com/rs/zerolog/log" "io" "io/ioutil" "net/http" @@ -13,6 +11,9 @@ import ( "path" "path/filepath" "strings" + + "github.com/go-chi/chi/v5" + "github.com/rs/zerolog/log" ) //go:embed *.html @@ -46,7 +47,7 @@ func (p *EmojyPlugin) handleAll(w http.ResponseWriter, r *http.Request) { } func (p *EmojyPlugin) handleAllFiles(w http.ResponseWriter, r *http.Request) { - _, urlMap, err := p.allFiles() + _, urlMap, err := AllFiles(p.c) if err != nil { w.WriteHeader(500) out, _ := json.Marshal(struct{ err error }{err})