mirror of https://github.com/velour/catbase.git
Merge pull request #196 from velour/reaction_log
slackApp: add reaction logging
This commit is contained in:
commit
1fcb28b8d6
|
@ -1,7 +1,6 @@
|
|||
package slackapp
|
||||
|
||||
import (
|
||||
"github.com/nlopes/slack"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
|
@ -14,7 +13,7 @@ import (
|
|||
// • Strips < and > surrounding links.
|
||||
//
|
||||
// This was directly bogarted from velour/chat with emoji conversion removed.
|
||||
func fixText(findUser func(id string) (*slack.User, error), text string) string {
|
||||
func fixText(findUser func(id, defaultName string) string, text string) string {
|
||||
var output []rune
|
||||
for len(text) > 0 {
|
||||
r, i := utf8.DecodeRuneInString(text)
|
||||
|
@ -49,16 +48,15 @@ func fixText(findUser func(id string) (*slack.User, error), text string) string
|
|||
return string(output)
|
||||
}
|
||||
|
||||
func fixTag(findUser func(string) (*slack.User, error), tag []rune) ([]rune, bool) {
|
||||
func fixTag(findUser func(string, string) string, tag []rune) ([]rune, bool) {
|
||||
switch {
|
||||
case hasPrefix(tag, "@U"):
|
||||
if i := indexRune(tag, '|'); i >= 0 {
|
||||
return tag[i+1:], true
|
||||
}
|
||||
if findUser != nil {
|
||||
if u, err := findUser(string(tag[1:])); err == nil {
|
||||
return []rune(u.Name), true
|
||||
}
|
||||
u := findUser(string(tag[1:]), "unknown")
|
||||
return []rune(u), true
|
||||
}
|
||||
return tag, true
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ import (
|
|||
"github.com/velour/catbase/config"
|
||||
)
|
||||
|
||||
const DefaultRing = 5
|
||||
const DefaultIDRing = 10
|
||||
const DefaultMsgRing = 50
|
||||
const defaultLogFormat = "[{{fixDate .Time \"2006-01-02 15:04:05\"}}] {{if .TopicChange}}*** {{.User.Name}}{{else if .Action}}* {{.User.Name}}{{else}}<{{.User.Name}}>{{end}} {{.Body}}\n"
|
||||
|
||||
// 11:10AM DBG connectors/slackapp/slackApp.go:496 > Slack event dir=logs raw={"Action":false,"AdditionalData":
|
||||
|
@ -58,6 +59,7 @@ type SlackApp struct {
|
|||
event bot.Callback
|
||||
|
||||
msgIDBuffer *ring.Ring
|
||||
msgBuffer *ring.Ring
|
||||
|
||||
logFormat *template.Template
|
||||
}
|
||||
|
@ -73,17 +75,11 @@ func New(c *config.Config) *SlackApp {
|
|||
|
||||
api := slack.New(token, slack.OptionDebug(false))
|
||||
|
||||
idBuf := ring.New(c.GetInt("ringSize", DefaultRing))
|
||||
for i := 0; i < idBuf.Len(); i++ {
|
||||
idBuf.Value = ""
|
||||
idBuf = idBuf.Next()
|
||||
}
|
||||
|
||||
tplTxt := c.GetString("slackapp.log.format", defaultLogFormat)
|
||||
tplTxt := c.GetString("slackapp.logMessage.format", defaultLogFormat)
|
||||
funcs := template.FuncMap{
|
||||
"fixDate": fixDate,
|
||||
}
|
||||
tpl := template.Must(template.New("log").Funcs(funcs).Parse(tplTxt))
|
||||
tpl := template.Must(template.New("logMessage").Funcs(funcs).Parse(tplTxt))
|
||||
|
||||
return &SlackApp{
|
||||
api: api,
|
||||
|
@ -96,7 +92,8 @@ func New(c *config.Config) *SlackApp {
|
|||
users: make(map[string]*slack.User),
|
||||
emoji: make(map[string]string),
|
||||
channels: make(map[string]*slack.Channel),
|
||||
msgIDBuffer: idBuf,
|
||||
msgIDBuffer: ring.New(c.GetInt("idRingSize", DefaultIDRing)),
|
||||
msgBuffer: ring.New(c.GetInt("msgRingSize", DefaultMsgRing)),
|
||||
logFormat: tpl,
|
||||
}
|
||||
}
|
||||
|
@ -130,12 +127,22 @@ func (s *SlackApp) Serve() error {
|
|||
} else if eventsAPIEvent.Type == slackevents.CallbackEvent {
|
||||
innerEvent := eventsAPIEvent.InnerEvent
|
||||
switch ev := innerEvent.Data.(type) {
|
||||
case *slackevents.MessageAction:
|
||||
log.Debug().Interface("ev", ev).Msg("MessageAction")
|
||||
case *slackevents.MessageActionResponse:
|
||||
log.Debug().Interface("ev", ev).Msg("MessageActionResponse")
|
||||
case *slackevents.AppMentionEvent:
|
||||
// This is a bit of a problem. AppMentionEvent also needs to
|
||||
// End up in msgReceived
|
||||
//s.msgReceivd(ev)
|
||||
case *slackevents.MessageEvent:
|
||||
s.msgReceivd(ev)
|
||||
case *slack.ReactionAddedEvent:
|
||||
s.reactionReceived(ev)
|
||||
default:
|
||||
log.Debug().
|
||||
Interface("ev", ev).
|
||||
Msg("Unknown CallbackEvent")
|
||||
}
|
||||
} else {
|
||||
log.Debug().
|
||||
|
@ -152,6 +159,9 @@ func (s *SlackApp) Serve() error {
|
|||
func (s *SlackApp) checkRingOrAdd(ts string) bool {
|
||||
found := false
|
||||
s.msgIDBuffer.Do(func(p interface{}) {
|
||||
if p == nil {
|
||||
return
|
||||
}
|
||||
if p.(string) == ts {
|
||||
found = true
|
||||
}
|
||||
|
@ -193,7 +203,7 @@ func (s *SlackApp) msgReceivd(msg *slackevents.MessageEvent) {
|
|||
Msg("Ignoring message")
|
||||
return
|
||||
}
|
||||
if err := s.log(m); err != nil {
|
||||
if err := s.logMessage(m); err != nil {
|
||||
log.Fatal().Err(err).Msg("Error logging message")
|
||||
}
|
||||
if !isItMe && msg.ThreadTimeStamp == "" {
|
||||
|
@ -209,6 +219,9 @@ func (s *SlackApp) msgReceivd(msg *slackevents.MessageEvent) {
|
|||
Str("text", msg.Text).
|
||||
Msg("Unknown message is hidden")
|
||||
}
|
||||
|
||||
s.msgBuffer.Value = msg
|
||||
s.msgBuffer = s.msgBuffer.Next()
|
||||
}
|
||||
|
||||
func (s *SlackApp) Send(kind bot.Kind, args ...interface{}) (string, error) {
|
||||
|
@ -407,12 +420,8 @@ func (s *SlackApp) buildMessage(m *slackevents.MessageEvent) msg.Message {
|
|||
isAction := m.SubType == "me_message"
|
||||
|
||||
// We have to try a few layers to get a valid name for the user because Slack
|
||||
name := "UNKNOWN"
|
||||
u, _ := s.getUser(m.User)
|
||||
if u != nil {
|
||||
name = u.Profile.DisplayName
|
||||
}
|
||||
if m.Username != "" && u == nil {
|
||||
name := s.getUser(m.User, "unknown")
|
||||
if m.Username != "" && name == "unknown" {
|
||||
name = m.Username
|
||||
}
|
||||
|
||||
|
@ -459,21 +468,29 @@ func (s *SlackApp) getChannel(id string) (*slack.Channel, error) {
|
|||
return s.channels[id], nil
|
||||
}
|
||||
|
||||
func stringForUser(user *slack.User) string {
|
||||
if user.Profile.DisplayName != "" {
|
||||
return user.Profile.DisplayName
|
||||
}
|
||||
return user.Name
|
||||
}
|
||||
|
||||
// Get username for Slack user ID
|
||||
func (s *SlackApp) getUser(id string) (*slack.User, error) {
|
||||
if name, ok := s.users[id]; ok {
|
||||
return name, nil
|
||||
func (s *SlackApp) getUser(id, defaultName string) string {
|
||||
if u, ok := s.users[id]; ok {
|
||||
return stringForUser(u)
|
||||
}
|
||||
|
||||
log.Debug().
|
||||
Str("id", id).
|
||||
Msg("User not already found, requesting info")
|
||||
|
||||
u, err := s.api.GetUserInfo(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return defaultName
|
||||
}
|
||||
s.users[id] = u
|
||||
return s.users[id], nil
|
||||
return stringForUser(u)
|
||||
}
|
||||
|
||||
// Who gets usernames out of a channel
|
||||
|
@ -500,8 +517,8 @@ func (s *SlackApp) Who(id string) []string {
|
|||
|
||||
ret := []string{}
|
||||
for _, m := range members {
|
||||
u, err := s.getUser(m)
|
||||
if err != nil {
|
||||
u := s.getUser(m, "unknown")
|
||||
if u != "unknown" {
|
||||
log.Error().
|
||||
Err(err).
|
||||
Str("user", m).
|
||||
|
@ -509,15 +526,14 @@ func (s *SlackApp) Who(id string) []string {
|
|||
continue
|
||||
/**/
|
||||
}
|
||||
ret = append(ret, u.Name)
|
||||
ret = append(ret, u)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// log writes to a <slackapp.log.dir>/<channel>.log
|
||||
// Uses slackapp.log.format to write entries
|
||||
func (s *SlackApp) log(raw msg.Message) error {
|
||||
|
||||
// logMessage writes to a <slackapp.logMessage.dir>/<channel>.logMessage
|
||||
// Uses slackapp.logMessage.format to write entries
|
||||
func (s *SlackApp) logMessage(raw msg.Message) error {
|
||||
// Do some filtering and fixing up front
|
||||
if raw.Body == "" {
|
||||
return nil
|
||||
|
@ -536,20 +552,29 @@ func (s *SlackApp) log(raw msg.Message) error {
|
|||
data.TopicChange = true
|
||||
}
|
||||
|
||||
dir := path.Join(s.config.Get("slackapp.log.dir", "logs"), raw.ChannelName)
|
||||
buf := bytes.Buffer{}
|
||||
if err := s.logFormat.Execute(&buf, data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.log(buf.String(), raw.ChannelName)
|
||||
}
|
||||
|
||||
func (s *SlackApp) log(msg, channel string) error {
|
||||
dir := path.Join(s.config.Get("slackapp.logMessage.dir", "logs"), channel)
|
||||
now := time.Now()
|
||||
fname := now.Format("20060102") + ".log"
|
||||
path := path.Join(dir, fname)
|
||||
|
||||
log.Debug().
|
||||
Interface("raw", raw).
|
||||
Interface("raw", msg).
|
||||
Str("dir", dir).
|
||||
Msg("Slack event")
|
||||
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
log.Error().
|
||||
Err(err).
|
||||
Msg("Could not create log directory")
|
||||
Msg("Could not create logMessage directory")
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -557,13 +582,46 @@ func (s *SlackApp) log(raw msg.Message) error {
|
|||
if err != nil {
|
||||
log.Fatal().
|
||||
Err(err).
|
||||
Msg("Error opening log file")
|
||||
Msg("Error opening logMessage file")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := s.logFormat.Execute(f, data); err != nil {
|
||||
if _, err := fmt.Fprint(f, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return f.Sync()
|
||||
}
|
||||
|
||||
func (s *SlackApp) reactionReceived(event *slack.ReactionAddedEvent) error {
|
||||
name := s.getUser(event.User, "unknown")
|
||||
|
||||
ch, err := s.getChannel(event.Item.Channel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
channel := ch.Name
|
||||
|
||||
body := "unknown message"
|
||||
|
||||
// Iterate through the ring and print its contents
|
||||
s.msgBuffer.Do(func(p interface{}) {
|
||||
switch m := p.(type) {
|
||||
case nil:
|
||||
case *slackevents.MessageEvent:
|
||||
if m.TimeStamp == event.Item.Timestamp {
|
||||
u := s.getUser(m.User, "unknown")
|
||||
body = fmt.Sprintf("%s: %s", u, m.Text)
|
||||
}
|
||||
default:
|
||||
log.Debug().Interface("msg", m).Msg("Unexpected type")
|
||||
}
|
||||
})
|
||||
|
||||
tstamp := slackTStoTime(event.EventTimestamp)
|
||||
msg := fmt.Sprintf("[%s] <%s> reacted to %s with :%s:\n",
|
||||
fixDate(tstamp, "2006-01-02 15:04:05"),
|
||||
name, body, event.Reaction)
|
||||
|
||||
return s.log(msg, channel)
|
||||
}
|
||||
|
|
12
go.mod
12
go.mod
|
@ -3,20 +3,15 @@ module github.com/velour/catbase
|
|||
require (
|
||||
github.com/PaulRosset/go-hacknews v0.0.0-20170815075127-4aad99273a3c
|
||||
github.com/PuerkitoBio/goquery v1.5.0
|
||||
github.com/ajstarks/svgo v0.0.0-20181006003313-6ce6a3bcf6cd // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
|
||||
github.com/fogleman/gg v1.3.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
||||
github.com/golang/protobuf v1.3.2 // indirect
|
||||
github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 // indirect
|
||||
github.com/gonum/internal v0.0.0-20181124074243-f884aa714029 // indirect
|
||||
github.com/gorilla/websocket v1.4.0 // indirect
|
||||
github.com/james-bowman/nlp v0.0.0-20190408090549-143ee6f41889
|
||||
github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7 // indirect
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/jung-kurt/gofpdf v1.7.0 // indirect
|
||||
github.com/lib/pq v1.2.0 // indirect
|
||||
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect
|
||||
github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018 // indirect
|
||||
|
@ -25,7 +20,6 @@ require (
|
|||
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf // indirect
|
||||
github.com/nlopes/slack v0.5.0
|
||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237 // indirect
|
||||
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d // indirect
|
||||
github.com/rs/zerolog v1.15.0
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
|
@ -33,14 +27,10 @@ require (
|
|||
github.com/stretchr/testify v1.3.0
|
||||
github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89
|
||||
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
|
||||
golang.org/x/mobile v0.0.0-20190806162312-597adff16ade // indirect
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 // indirect
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a // indirect
|
||||
golang.org/x/tools v0.0.0-20190813142322-97f12d73768f // indirect
|
||||
gonum.org/v1/gonum v0.0.0-20190808205415-ced62fe5104b // indirect
|
||||
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e // indirect
|
||||
gonum.org/v1/plot v0.0.0-20190615073203-9aa86143727f // indirect
|
||||
google.golang.org/appengine v1.6.1 // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
)
|
||||
|
|
48
go.sum
48
go.sum
|
@ -6,58 +6,44 @@ github.com/PaulRosset/go-hacknews v0.0.0-20170815075127-4aad99273a3c/go.mod h1:8
|
|||
github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk=
|
||||
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/ajstarks/svgo v0.0.0-20181006003313-6ce6a3bcf6cd/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff h1:+TEqaP0eO1unI7XHHFeMDhsxhLDIb0x8KYuZbqbAmxA=
|
||||
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff/go.mod h1:QCRjR0b4qiJiNjuP7RFM89bh4UExGJalcWmYeSvlnRc=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 h1:EvokxLQsaaQjcWVWSV38221VAK7qc2zhaO17bKys/18=
|
||||
github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg=
|
||||
github.com/gonum/internal v0.0.0-20181124074243-f884aa714029 h1:8jtTdc+Nfj9AR+0soOeia9UZSvYBvETVHZrugUowJ7M=
|
||||
github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/james-bowman/nlp v0.0.0-20190301165020-c5645f996605 h1:MjLvsJmW4uoTjleqqiL0wKRTjxUakKUhDNoSsSlS2hk=
|
||||
github.com/james-bowman/nlp v0.0.0-20190301165020-c5645f996605/go.mod h1:kixuaexEqWB+mHZNysgnb6mqgGIT25WvD1/tFRRt0J0=
|
||||
github.com/james-bowman/nlp v0.0.0-20190408090549-143ee6f41889 h1:VYwE/yKDYXpd5hno5fCCWv2wPcM37DYAX4r3Re1pLz8=
|
||||
github.com/james-bowman/nlp v0.0.0-20190408090549-143ee6f41889/go.mod h1:kixuaexEqWB+mHZNysgnb6mqgGIT25WvD1/tFRRt0J0=
|
||||
github.com/james-bowman/sparse v0.0.0-20190309194602-7d83420cfcbe h1:UFAsFuH6cu/0Lx+qBWfxiO69jrPkvdbG3qwSWI/7yF0=
|
||||
github.com/james-bowman/sparse v0.0.0-20190309194602-7d83420cfcbe/go.mod h1:G6EcQnwZKsWtItoaQHd+FHPPk6bDeYVJSeeSP9Sge+I=
|
||||
github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7 h1:ph/BDQQDL41apnHSN48I5GyNOQXXAlc79HwGqDSXCss=
|
||||
github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7/go.mod h1:G6EcQnwZKsWtItoaQHd+FHPPk6bDeYVJSeeSP9Sge+I=
|
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/jung-kurt/gofpdf v1.7.0/go.mod h1:s/VXv+TdctEOx2wCEguezYaR7f0OwUAd6H9VGfRkcSs=
|
||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 h1:AsEBgzv3DhuYHI/GiQh2HxvTP71HCCE9E/tzGUzGdtU=
|
||||
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5/go.mod h1:c2mYKRyMb1BPkO5St0c/ps62L4S0W2NAkaTXj9qEI+0=
|
||||
github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 h1:iOAVXzZyXtW408TMYejlUPo6BIn92HmOacWtIfNyYns=
|
||||
github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6/go.mod h1:sFlOUpQL1YcjhFVXhg1CG8ZASEs/Mf1oVb6H75JL/zg=
|
||||
github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018 h1:MNApn+Z+fIT4NPZopPfCc1obT6aY3SVM6DOctz1A9ZU=
|
||||
github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018/go.mod h1:sFlOUpQL1YcjhFVXhg1CG8ZASEs/Mf1oVb6H75JL/zg=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mmcdole/gofeed v1.0.0-beta2 h1:CjQ0ADhAwNSb08zknAkGOEYqr8zfZKfrzgk9BxpWP2E=
|
||||
|
@ -66,33 +52,23 @@ github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/
|
|||
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf/go.mod h1:pasqhqstspkosTneA62Nc+2p9SOBBYAPbnmRRWPQ0V8=
|
||||
github.com/nlopes/slack v0.5.0 h1:NbIae8Kd0NpqaEI3iUrsuS0KbcEDhzhc939jLW5fNm0=
|
||||
github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
|
||||
github.com/olebedev/when v0.0.0-20190131080308-164b69386514 h1:xpZutaUgtGPKT2JFaH72/yby908QS9ORlnrAkkdJ4m0=
|
||||
github.com/olebedev/when v0.0.0-20190131080308-164b69386514/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0=
|
||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254 h1:JYoQR67E1vv1WGoeW8DkdFs7vrIEe/5wP+qJItd5tUE=
|
||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0=
|
||||
github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4=
|
||||
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.12.0 h1:aqZ1XRadoS8IBknR5IDFvGzbHly1X9ApIqOroooQF/c=
|
||||
github.com/rs/zerolog v1.12.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0 h1:uPRuwkWF4J6fGsJ2R0Gn2jB1EQiav9k3S6CSdygQJXY=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89 h1:3D3M900hEBJJAqyKl70QuRHi5weX9+ptlQI1v+FNcQ8=
|
||||
|
@ -103,31 +79,21 @@ github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxt
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190321205749-f0864edee7f3 h1:Ep4L2ibjtJcW6IP73KbcJAU0cpNKsLNSSP2jE1xlCys=
|
||||
golang.org/x/exp v0.0.0-20190321205749-f0864edee7f3/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190806162312-597adff16ade/go.mod h1:AlhUtkH4DA4asiFC5RgK7ZKmauvtkAVcy9L0epCzlWo=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190606173856-1492cefac77f h1:IWHgpgFqnL5AhBUBZSgBdjl2vkQUEzcY+JNKWfcgAU0=
|
||||
golang.org/x/net v0.0.0-20190606173856-1492cefac77f/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -135,7 +101,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
|
@ -146,21 +111,16 @@ golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGm
|
|||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190813142322-97f12d73768f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.0.0-20190325211145-e42c1265cdd5 h1:tyvqqvbB9Sn6UPjokEzsK6cCE9k4Tx/AHGGaJiLIk7g=
|
||||
gonum.org/v1/gonum v0.0.0-20190325211145-e42c1265cdd5/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
||||
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
||||
gonum.org/v1/gonum v0.0.0-20190808205415-ced62fe5104b h1:wlZ2AJblZitrh7dfm5OX2WenXLBZCuWqUeNczop2lPA=
|
||||
gonum.org/v1/gonum v0.0.0-20190808205415-ced62fe5104b/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts=
|
||||
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
|
||||
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
||||
gonum.org/v1/plot v0.0.0-20190615073203-9aa86143727f/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||
|
|
Loading…
Reference in New Issue