first: change to per channel

And be sure not to pay attention to private/direct messages
This commit is contained in:
Chris Sexton 2019-06-06 10:33:50 -04:00
parent ae57dcb703
commit fe8763f78a
3 changed files with 85 additions and 74 deletions

View File

@ -14,6 +14,7 @@ type Messages []Message
type Message struct { type Message struct {
User *user.User User *user.User
Channel, Body string Channel, Body string
IsIM bool
Raw string Raw string
Command bool Command bool
Action bool Action bool

View File

@ -87,6 +87,11 @@ func (s *SlackApp) Serve() error {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.ReadFrom(r.Body) buf.ReadFrom(r.Body)
body := buf.String() body := buf.String()
var raw interface{}
json.Unmarshal(json.RawMessage(body), &raw)
log.Debug().
Interface("raw", raw).
Msg("Slack event")
eventsAPIEvent, e := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionVerifyToken(&slackevents.TokenComparator{VerificationToken: s.verification})) eventsAPIEvent, e := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionVerifyToken(&slackevents.TokenComparator{VerificationToken: s.verification}))
if e != nil { if e != nil {
log.Error().Err(e) log.Error().Err(e)
@ -148,6 +153,7 @@ func (s *SlackApp) msgReceivd(msg *slackevents.MessageEvent) {
} }
log.Debug(). log.Debug().
Interface("event", msg).
Str("type", msg.SubType). Str("type", msg.SubType).
Msg("accepting a message") Msg("accepting a message")
@ -389,6 +395,7 @@ func (s *SlackApp) buildMessage(m *slackevents.MessageEvent) msg.Message {
Body: text, Body: text,
Raw: m.Text, Raw: m.Text,
Channel: m.Channel, Channel: m.Channel,
IsIM: m.ChannelType == "im",
Command: isCmd, Command: isCmd,
Action: isAction, Action: isAction,
Time: tstamp, Time: tstamp,

View File

@ -18,26 +18,27 @@ import (
// This is a first plugin to serve as an example and quick copy/paste for new plugins. // This is a first plugin to serve as an example and quick copy/paste for new plugins.
type FirstPlugin struct { type FirstPlugin struct {
First *FirstEntry Bot bot.Bot
Bot bot.Bot db *sqlx.DB
db *sqlx.DB
} }
type FirstEntry struct { type FirstEntry struct {
id int64 id int64
day time.Time day time.Time
time time.Time time time.Time
body string channel string
nick string body string
saved bool nick string
saved bool
} }
// Insert or update the first entry // Insert or update the first entry
func (fe *FirstEntry) save(db *sqlx.DB) error { func (fe *FirstEntry) save(db *sqlx.DB) error {
if _, err := db.Exec(`insert into first (day, time, body, nick) if _, err := db.Exec(`insert into first (day, time, channel, body, nick)
values (?, ?, ?, ?)`, values (?, ?, ?, ?, ?)`,
fe.day.Unix(), fe.day.Unix(),
fe.time.Unix(), fe.time.Unix(),
fe.channel,
fe.body, fe.body,
fe.nick, fe.nick,
); err != nil { ); err != nil {
@ -52,6 +53,7 @@ func New(b bot.Bot) *FirstPlugin {
id integer primary key, id integer primary key,
day integer, day integer,
time integer, time integer,
channel string,
body string, body string,
nick string nick string
);`) );`)
@ -64,24 +66,16 @@ func New(b bot.Bot) *FirstPlugin {
log.Info().Msgf("First plugin initialized with day: %s", log.Info().Msgf("First plugin initialized with day: %s",
midnight(time.Now())) midnight(time.Now()))
first, err := getLastFirst(b.DB())
if err != nil {
log.Fatal().
Err(err).
Msg("Could not initialize first plugin")
}
fp := &FirstPlugin{ fp := &FirstPlugin{
Bot: b, Bot: b,
db: b.DB(), db: b.DB(),
First: first,
} }
b.Register(fp, bot.Message, fp.message) b.Register(fp, bot.Message, fp.message)
b.Register(fp, bot.Help, fp.help) b.Register(fp, bot.Help, fp.help)
return fp return fp
} }
func getLastFirst(db *sqlx.DB) (*FirstEntry, error) { func getLastFirst(db *sqlx.DB, channel string) (*FirstEntry, error) {
// Get last first entry // Get last first entry
var id sql.NullInt64 var id sql.NullInt64
var day sql.NullInt64 var day sql.NullInt64
@ -91,8 +85,9 @@ func getLastFirst(db *sqlx.DB) (*FirstEntry, error) {
err := db.QueryRow(`select err := db.QueryRow(`select
id, max(day), time, body, nick from first id, max(day), time, body, nick from first
where channel = ?
limit 1; limit 1;
`).Scan( `, channel).Scan(
&id, &id,
&day, &day,
&timeEntered, &timeEntered,
@ -110,12 +105,13 @@ func getLastFirst(db *sqlx.DB) (*FirstEntry, error) {
log.Debug().Msgf("id: %v day %v time %v body %v nick %v", log.Debug().Msgf("id: %v day %v time %v body %v nick %v",
id, day, timeEntered, body, nick) id, day, timeEntered, body, nick)
return &FirstEntry{ return &FirstEntry{
id: id.Int64, id: id.Int64,
day: time.Unix(day.Int64, 0), day: time.Unix(day.Int64, 0),
time: time.Unix(timeEntered.Int64, 0), time: time.Unix(timeEntered.Int64, 0),
body: body.String, channel: channel,
nick: nick.String, body: body.String,
saved: true, nick: nick.String,
saved: true,
}, nil }, nil
} }
@ -124,7 +120,11 @@ func midnight(t time.Time) time.Time {
return time.Date(y, m, d, 0, 0, 0, 0, time.UTC) return time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
} }
func isToday(t time.Time) bool { func isNotToday(f *FirstEntry) bool {
if f == nil {
return true
}
t := f.time
t0 := midnight(t) t0 := midnight(t)
return t0.Before(midnight(time.Now())) return t0.Before(midnight(time.Now()))
} }
@ -133,31 +133,41 @@ func isToday(t time.Time) bool {
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *FirstPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool { func (p *FirstPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
// This bot does not reply to anything log.Debug().
Interface("msg", message).
Msg("First is looking at a message")
if p.First == nil && p.allowed(message) { if message.IsIM {
log.Debug(). log.Debug().Msg("Skipping IM")
Str("body", message.Body).
Msg("No previous first. Recording new first")
p.recordFirst(c, message)
return false return false
} else if p.First != nil {
if isToday(p.First.time) && p.allowed(message) {
log.Debug().
Str("body", message.Body).
Time("t0", p.First.time).
Time("t1", time.Now()).
Msg("Recording first")
p.recordFirst(c, message)
return false
}
} }
r := strings.NewReplacer("'", "", "\"", "", ",", "", ".", "", ":", "", first, err := getLastFirst(p.db, message.Channel)
if err != nil {
log.Error().
Err(err).
Msg("Error getting last first")
}
log.Debug().Bool("first == nil", first == nil).Msg("Is first nil?")
log.Debug().Bool("first == nil || isNotToday()", isNotToday(first)).Msg("Is it today?")
log.Debug().Bool("p.allowed", p.allowed(message)).Msg("Allowed?")
if (first == nil || isNotToday(first)) && p.allowed(message) {
log.Debug().
Str("body", message.Body).
Interface("t0", first).
Time("t1", time.Now()).
Msg("Recording first")
p.recordFirst(c, message)
return false
}
r := strings.NewReplacer("", "", "'", "", "\"", "", ",", "", ".", "", ":", "",
"?", "", "!", "") "?", "", "!", "")
msg := strings.ToLower(message.Body) m := strings.ToLower(message.Body)
if r.Replace(msg) == "whos on first" { if r.Replace(m) == "whos on first" && first != nil {
p.announceFirst(c, message) p.announceFirst(c, first)
return true return true
} }
@ -165,8 +175,8 @@ func (p *FirstPlugin) message(c bot.Connector, kind bot.Kind, message msg.Messag
} }
func (p *FirstPlugin) allowed(message msg.Message) bool { func (p *FirstPlugin) allowed(message msg.Message) bool {
for _, msg := range p.Bot.Config().GetArray("Bad.Msgs", []string{}) { for _, m := range p.Bot.Config().GetArray("Bad.Msgs", []string{}) {
match, err := regexp.MatchString(msg, strings.ToLower(message.Body)) match, err := regexp.MatchString(m, strings.ToLower(message.Body))
if err != nil { if err != nil {
log.Error().Err(err).Msg("Bad regexp") log.Error().Err(err).Msg("Bad regexp")
} }
@ -201,41 +211,34 @@ func (p *FirstPlugin) allowed(message msg.Message) bool {
func (p *FirstPlugin) recordFirst(c bot.Connector, message msg.Message) { func (p *FirstPlugin) recordFirst(c bot.Connector, message msg.Message) {
log.Info(). log.Info().
Str("channel", message.Channel).
Str("user", message.User.Name). Str("user", message.User.Name).
Str("body", message.Body). Str("body", message.Body).
Msg("Recording first") Msg("Recording first")
p.First = &FirstEntry{ first := &FirstEntry{
day: midnight(time.Now()), day: midnight(time.Now()),
time: message.Time, time: message.Time,
body: message.Body, channel: message.Channel,
nick: message.User.Name, body: message.Body,
nick: message.User.Name,
} }
log.Info().Msgf("recordFirst: %+v", p.First.day) log.Info().Msgf("recordFirst: %+v", first.day)
err := p.First.save(p.db) err := first.save(p.db)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Error saving first entry") log.Error().Err(err).Msg("Error saving first entry")
return return
} }
p.announceFirst(c, message) p.announceFirst(c, first)
} }
func (p *FirstPlugin) announceFirst(c bot.Connector, message msg.Message) { func (p *FirstPlugin) announceFirst(c bot.Connector, first *FirstEntry) {
ch := message.Channel ch := first.channel
if p.First != nil { p.Bot.Send(c, bot.Message, ch, fmt.Sprintf("%s had first at %s with the message: \"%s\"",
p.Bot.Send(c, bot.Message, ch, fmt.Sprintf("%s had first at %s with the message: \"%s\"", first.nick, first.time.Format("15:04"), first.body))
p.First.nick, p.First.time.Format("15:04"), p.First.body))
}
}
// LoadData imports any configuration data into the plugin. This is not strictly necessary other
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
// date.
func (p *FirstPlugin) LoadData() {
// This bot has no data to load
} }
// Help responds to help requests. Every plugin must implement a help function. // Help responds to help requests. Every plugin must implement a help function.
func (p *FirstPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool { func (p *FirstPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
p.Bot.Send(c, bot.Message, message.Channel, "Sorry, First does not do a goddamn thing.") p.Bot.Send(c, bot.Message, message.Channel, "You can ask 'who's on first?' to find out.")
return true return true
} }