diff --git a/go.mod b/go.mod index 5ae6707..d9089c6 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,17 @@ module github.com/velour/catbase require ( + github.com/ChimeraCoder/anaconda v2.0.0+incompatible + github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7 // indirect github.com/PaulRosset/go-hacknews v0.0.0-20170815075127-4aad99273a3c github.com/PuerkitoBio/goquery v1.5.0 github.com/armon/go-radix v1.0.0 // indirect + github.com/azr/backoff v0.0.0-20160115115103-53511d3c7330 // indirect github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff github.com/chrissexton/sentiment v0.0.0-20190927141846-d69c422ba035 + github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc // indirect + github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect + github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17 // indirect github.com/go-sql-driver/mysql v1.4.1 // indirect github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 // indirect github.com/gonum/internal v0.0.0-20181124074243-f884aa714029 // indirect @@ -35,3 +41,5 @@ require ( google.golang.org/appengine v1.6.1 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect ) + +go 1.13 diff --git a/go.sum b/go.sum index 4184663..4d334db 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ github.com/AlekSi/pointer v1.0.0 h1:KWCWzsvFxNLcmM5XmiqHsGTTsuwZMsLFwWF9Y+//bNE= github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ChimeraCoder/anaconda v2.0.0+incompatible h1:F0eD7CHXieZ+VLboCD5UAqCeAzJZxcr90zSCcuJopJs= +github.com/ChimeraCoder/anaconda v2.0.0+incompatible/go.mod h1:TCt3MijIq3Qqo9SBtuW/rrM4x7rDfWqYWHj8T7hLcLg= +github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7 h1:r+EmXjfPosKO4wfiMLe1XQictsIlhErTufbWUsjOTZs= +github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7/go.mod h1:b2EuEMLSG9q3bZ95ql1+8oVqzzrTNSiOQqSXWFBzxeI= github.com/PaulRosset/go-hacknews v0.0.0-20170815075127-4aad99273a3c h1:bJ0HbTMaInVjakxM76G+2gsmbKTdHzpTUGyLGYxdMO0= github.com/PaulRosset/go-hacknews v0.0.0-20170815075127-4aad99273a3c/go.mod h1:8+24kIp7vJsYy0GmQDDNnPwAYEWkl3OcaPxJSDAfe1U= github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk= @@ -10,6 +14,8 @@ github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRy 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/azr/backoff v0.0.0-20160115115103-53511d3c7330 h1:ekDALXAVvY/Ub1UtNta3inKQwZ/jMB/zpOtD8rAYh78= +github.com/azr/backoff v0.0.0-20160115115103-53511d3c7330/go.mod h1:nH+k0SvAt3HeiYyOlJpLLv1HG1p7KWP7qU9QPp2/pCo= github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598 h1:j2XRGH5Y5uWtBYXGwmrjKeM/kfu/jh7ZcnrGvyN5Ttk= github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598/go.mod h1:sduMkaHcXDIWurl/Bd/z0rNEUHw5tr6LUA9IO8E9o0o= github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff h1:+TEqaP0eO1unI7XHHFeMDhsxhLDIb0x8KYuZbqbAmxA= @@ -20,7 +26,13 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 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/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc h1:tP7tkU+vIsEOKiK+l/NSLN4uUtkyuxc6hgYpQeCWAeI= +github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc/go.mod h1:ORH5Qp2bskd9NzSfKqAF7tKfONsEkCarTE5ESr/RVBw= +github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= +github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad/go.mod h1:mPKfmRa823oBIgl2r20LeMSpTAteW5j7FLkc0vjmzyQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17 h1:GOfMz6cRgTJ9jWV0qAezv642OhPnKEG7gtUjJSdStHE= +github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17/go.mod h1:HfkOCN6fkKKaPSAeNq/er3xObxTW4VLeY6UUK895gLQ= 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= diff --git a/main.go b/main.go index 9e9dcb8..a26b1da 100644 --- a/main.go +++ b/main.go @@ -4,13 +4,16 @@ package main import ( "flag" - "github.com/velour/catbase/plugins/cli" - "github.com/velour/catbase/plugins/newsbid" "math/rand" "net/http" "os" "time" + "github.com/velour/catbase/plugins/twitter" + + "github.com/velour/catbase/plugins/cli" + "github.com/velour/catbase/plugins/newsbid" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -126,6 +129,7 @@ func main() { b.AddPlugin(tldr.New(b)) b.AddPlugin(stock.New(b)) b.AddPlugin(newsbid.New(b)) + b.AddPlugin(twitter.New(b)) b.AddPlugin(cli.New(b)) // catches anything left, will always return true b.AddPlugin(fact.New(b)) diff --git a/plugins/twitter/twitter.go b/plugins/twitter/twitter.go new file mode 100644 index 0000000..295a11b --- /dev/null +++ b/plugins/twitter/twitter.go @@ -0,0 +1,86 @@ +package twitter + +import ( + "fmt" + "net/url" + "time" + + "github.com/rs/zerolog/log" + + "github.com/ChimeraCoder/anaconda" + + "github.com/velour/catbase/bot" + "github.com/velour/catbase/config" +) + +type Twitter struct { + c *config.Config + b bot.Bot + api *anaconda.TwitterApi + + tweetLog map[string]int64 +} + +func New(b bot.Bot) *Twitter { + t := Twitter{ + c: b.Config(), + b: b, + tweetLog: map[string]int64{}, + } + token := t.c.GetString("twitter.accesstoken", "") + secret := t.c.GetString("twitter.accesssecret", "") + consumerKey := t.c.GetString("twitter.consumerkey", "") + consumerSecret := t.c.GetString("twitter.consumersecret", "") + //delay := t.c.GetInt("twitter.delay", 10) + + // Don't create the API or start the loop without credentials + if token == "" || secret == "" || consumerKey == "" || consumerSecret == "" { + log.Error(). + Str("token", token). + Str("secret", secret). + Str("consumerKey", consumerKey). + Str("consumerSecret", consumerSecret). + Msg("Could not start Twitter API") + return &t + } + + t.api = anaconda.NewTwitterApiWithCredentials(token, secret, consumerKey, consumerSecret) + go t.timer(b.DefaultConnector()) + + return &t +} + +func (t *Twitter) timer(c bot.Connector) { + checkTime := t.c.GetInt("twitter.checktime", 10) + ticker := time.NewTicker(time.Duration(checkTime) * time.Minute) + t.check(c) + for { + <-ticker.C + t.check(c) + } +} + +func (t *Twitter) check(c bot.Connector) { + log.Debug().Msg("checking twitter") + chs := t.c.GetArray("twitter.channels", []string{}) + users := t.c.GetArray("twitter.users", []string{}) + for _, u := range users { + vals := url.Values{"screen_name": []string{u}} + tweets, err := t.api.GetUserTimeline(vals) + if err != nil { + log.Error().Err(err).Str("user", u).Msg("error getting tweets") + continue + } + for _, tweet := range tweets { + if last, ok := t.tweetLog[u]; !ok || last < tweet.Id { + link := fmt.Sprintf("https://twitter.com/%s/status/%s", u, tweet.IdStr) + log.Debug().Str("tweet", link).Msg("Unknown tweet") + for _, ch := range chs { + log.Debug().Str("ch", ch).Msg("Sending tweet") + t.b.Send(c, bot.Message, ch, link) + } + t.tweetLog[u] = tweet.Id + } + } + } +}