Compare commits

..

3 Commits

Author SHA1 Message Date
Chris Sexton 04fecf1987 tappd: save ID in DB 2022-10-15 10:23:57 -04:00
Chris Sexton bf54f421fe twitch: remove broken test 2022-10-15 10:23:57 -04:00
Chris Sexton c147e65497 tappd: save images and serve them 2022-10-15 10:23:57 -04:00
4 changed files with 68 additions and 38 deletions

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"github.com/disintegration/imageorient" "github.com/disintegration/imageorient"
"github.com/fogleman/gg" "github.com/fogleman/gg"
"github.com/gabriel-vasile/mimetype"
"github.com/nfnt/resize" "github.com/nfnt/resize"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/velour/catbase/plugins/meme" "github.com/velour/catbase/plugins/meme"
@ -127,14 +128,17 @@ func (p *Tappd) getAndOverlay(id, srcURL string, texts []textSpec) (imageInfo, e
return imageInfo{}, err return imageInfo{}, err
} }
bounds := img.Bounds() bounds := img.Bounds()
mime := mimetype.Detect(data)
info := imageInfo{ info := imageInfo{
ID: id, ID: id,
SrcURL: srcURL, SrcURL: srcURL,
BotURL: u.String(), BotURL: u.String(),
Img: img, Img: img,
Repr: data, Repr: data,
W: bounds.Dx(), W: bounds.Dx(),
H: bounds.Dy(), H: bounds.Dy(),
MimeType: mime.String(),
FileName: id + mime.Extension(),
} }
p.imageMap[id] = info p.imageMap[id] = info
log.Debug(). log.Debug().

View File

@ -4,12 +4,13 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"github.com/gabriel-vasile/mimetype"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/config" "github.com/velour/catbase/config"
"github.com/velour/catbase/connectors/discord" "github.com/velour/catbase/connectors/discord"
"image" "image"
"os"
"path"
"regexp" "regexp"
"time" "time"
) )
@ -21,13 +22,15 @@ type Tappd struct {
} }
type imageInfo struct { type imageInfo struct {
ID string ID string
SrcURL string SrcURL string
BotURL string BotURL string
Img image.Image Img image.Image
Repr []byte Repr []byte
W int W int
H int H int
MimeType string
FileName string
} }
func New(b bot.Bot) *Tappd { func New(b bot.Bot) *Tappd {
@ -50,7 +53,7 @@ func (p *Tappd) mkDB() error {
return err return err
} }
_, err = tx.Exec(`create table if not exists tappd ( _, err = tx.Exec(`create table if not exists tappd (
id integer primary key autoincrement, id string primary key,
who string, who string,
channel string, channel string,
message string, message string,
@ -67,15 +70,15 @@ func (p *Tappd) mkDB() error {
return nil return nil
} }
func (p *Tappd) log(who, channel, message string) error { func (p *Tappd) log(id, who, channel, message string) error {
db := p.b.DB() db := p.b.DB()
tx, err := db.Beginx() tx, err := db.Beginx()
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
_, err = tx.Exec(`insert into tappd (who, channel, message, ts) values (?, ?, ? ,?)`, _, err = tx.Exec(`insert into tappd (id, who, channel, message, ts) values (?, ?, ?, ? ,?)`,
who, channel, message, time.Now()) id, who, channel, message, time.Now())
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return err return err
@ -144,10 +147,9 @@ func (p *Tappd) tap(s *discordgo.Session, i *discordgo.InteractionCreate) {
Height: info.H, Height: info.H,
}, },
}} }}
mime := mimetype.Detect(info.Repr)
files := []*discordgo.File{{ files := []*discordgo.File{{
Name: info.ID + mime.Extension(), Name: info.FileName,
ContentType: mime.String(), ContentType: info.MimeType,
Reader: bytes.NewBuffer(info.Repr), Reader: bytes.NewBuffer(info.Repr),
}} }}
content := info.BotURL content := info.BotURL
@ -171,10 +173,20 @@ func (p *Tappd) tap(s *discordgo.Session, i *discordgo.InteractionCreate) {
log.Error().Err(err).Msgf("error with interaction") log.Error().Err(err).Msgf("error with interaction")
return return
} }
err = p.log(who, channel, shortMsg) err = p.log(info.ID, who, channel, shortMsg)
if err != nil { if err != nil {
log.Error().Err(err).Msgf("error recording tap") log.Error().Err(err).Msgf("error recording tap")
} }
imgPath := p.c.Get("tappd.imagepath", "tappdimg")
err = os.MkdirAll(imgPath, 0775)
if err != nil {
log.Error().Err(err).Msgf("error creating directory")
return
}
err = os.WriteFile(path.Join(imgPath, info.FileName), info.Repr, 0664)
if err != nil {
log.Error().Err(err).Msgf("error writing file")
}
} }
func (p *Tappd) register() { func (p *Tappd) register() {

View File

@ -2,9 +2,13 @@ package tappd
import ( import (
"encoding/json" "encoding/json"
"fmt"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"net/http" "net/http"
"os"
"path"
"strings"
) )
func (p *Tappd) registerWeb() { func (p *Tappd) registerWeb() {
@ -13,19 +17,35 @@ func (p *Tappd) registerWeb() {
p.b.RegisterWeb(r, "/tappd/{id}") p.b.RegisterWeb(r, "/tappd/{id}")
} }
func (p *Tappd) getImg(id string) ([]byte, error) {
imgData, ok := p.imageMap[id]
if ok {
return imgData.Repr, nil
}
imgPath := p.c.Get("tappd.imagepath", "tappdimg")
entries, err := os.ReadDir(imgPath)
if err != nil {
log.Error().Err(err).Msgf("can't read image path")
return nil, err
}
for _, e := range entries {
if strings.HasPrefix(e.Name(), id) {
return os.ReadFile(path.Join(imgPath, e.Name()))
}
}
log.Error().Msgf("didn't find image")
return nil, fmt.Errorf("file not found")
}
func (p *Tappd) serveImage(w http.ResponseWriter, r *http.Request) { func (p *Tappd) serveImage(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id") id := chi.URLParam(r, "id")
imgData, ok := p.imageMap[id] data, err := p.getImg(id)
log.Debug(). if err != nil {
Str("id", id). log.Error().Err(err).Msgf("error getting image")
Str("SrcURL", imgData.SrcURL).
Bool("ok", ok).
Msgf("creating request")
if !ok {
w.WriteHeader(404) w.WriteHeader(404)
out, _ := json.Marshal(struct{ err string }{"could not find ID"}) out, _ := json.Marshal(struct{ err string }{"could not find ID: " + err.Error()})
w.Write(out) w.Write(out)
return return
} }
w.Write(imgData.Repr) w.Write(data)
} }

View File

@ -53,9 +53,3 @@ func makeTwitchPlugin(t *testing.T) (*Twitch, *bot.MockBot) {
return c, mb return c, mb
} }
func TestTwitch(t *testing.T) {
b, mb := makeTwitchPlugin(t)
b.twitchStatus(makeRequest("!twitch status"))
assert.NotEmpty(t, mb.Messages)
}