From 76e448f5a318d141b1f06134bf620cbbaf219168 Mon Sep 17 00:00:00 2001 From: Dustin Pianalto Date: Tue, 29 Sep 2020 19:36:45 -0800 Subject: [PATCH] Build out structure --- channel.go | 15 +++++++++++ cmd/overpass/main.go | 39 ++++++++++++++++++++++++---- go.mod | 3 +++ go.sum | 10 +++++++ guild.go | 14 ++++++++++ internal/exts/tweets/tweet_events.go | 20 ++++++++++++++ internal/oauth1/oauth1.go | 21 +++++++++++++++ internal/oauth2/oauth.go | 2 +- internal/postgres/database.go | 21 +++++++++++++++ internal/twitter/twitter.go | 17 +++++++----- tweet.go | 15 +++++++++++ 11 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 channel.go create mode 100644 guild.go create mode 100644 internal/exts/tweets/tweet_events.go create mode 100644 internal/oauth1/oauth1.go create mode 100644 internal/postgres/database.go create mode 100644 tweet.go diff --git a/channel.go b/channel.go new file mode 100644 index 0000000..ffd15ce --- /dev/null +++ b/channel.go @@ -0,0 +1,15 @@ +package overpass + +type Channel struct { + ID string + embed bool + retweets bool + guild *Guild +} + +type ChannelService interface { + Channel(id string) (*Channel, error) + AddChannel(c *Channel) error + UpdateChannel(c *Channel) error + DeleteChannel(c *Channel) error +} diff --git a/cmd/overpass/main.go b/cmd/overpass/main.go index ee46cdd..900e52a 100644 --- a/cmd/overpass/main.go +++ b/cmd/overpass/main.go @@ -7,19 +7,48 @@ import ( "os/signal" "syscall" + "github.com/bwmarrin/discordgo" + "github.com/dustinpianalto/overpass/internal/exts/tweets" + "github.com/dustinpianalto/overpass/internal/postgres" "github.com/dustinpianalto/overpass/internal/twitter" ) func main() { - tClient := twitter.Connect() - tweetChan, stream := twitter.StartUserScanner(tClient, "3347145623") - for tweet := range tweetChan { - log.Printf("%s\n%s - %s\n%s", tweet.IDStr, tweet.User.Name, tweet.User.IDStr, tweet.FullText) + token := os.Getenv("DISCORD_TOKEN") + if token == "" { + log.Fatal("Discord token not found in env") + } + dbString := os.Getenv("DATABASE_URL") + if dbString == "" { + log.Fatal("DB connection string not found in env") + } + session, err := discordgo.New("Bot " + token) + if err != nil { + log.Fatal("There was an error creating the Discord session") } + session.StateEnabled = true + + _ = postgres.ConnectDatabase(dbString) + + err = session.Open() + if err != nil { + log.Fatal("There was an error opening the connection to Discord, ", err) + } + log.Println("Bot is running") + + tClient := twitter.Connect() + tweetChan := make(chan *twitter.Tweet, 100) + stream := twitter.StartUserScanner(tClient, "34743251", tweetChan) + stream1 := twitter.StartUserScanner(tClient, "25073877", tweetChan) + stream2 := twitter.StartUserScanner(tClient, "3347145623", tweetChan) + go tweets.TweetHandler(session, tweetChan) + ch := make(chan os.Signal) - signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, os.Kill, os.Interrupt) log.Println(<-ch) fmt.Println("Stopping Stream...") stream.Stop() + stream1.Stop() + stream2.Stop() } diff --git a/go.mod b/go.mod index 31ee76f..193c709 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,9 @@ module github.com/dustinpianalto/overpass go 1.14 require ( + github.com/bwmarrin/discordgo v0.22.0 github.com/dghubble/go-twitter v0.0.0-20200725221434-4bc8ad7ad1b4 + github.com/dghubble/oauth1 v0.6.0 + github.com/lib/pq v1.8.0 golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 ) diff --git a/go.sum b/go.sum index 1b9efae..e385090 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM= +github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -44,6 +46,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dghubble/go-twitter v0.0.0-20200725221434-4bc8ad7ad1b4 h1:I60CX3+rWlBGPXR13jwxxBWB2GhlhZkEEh5o1eDLzJg= github.com/dghubble/go-twitter v0.0.0-20200725221434-4bc8ad7ad1b4/go.mod h1:xfg4uS5LEzOj8PgZV7SQYRHbG7jPUnelEiaAVJxmhJE= +github.com/dghubble/oauth1 v0.6.0 h1:m1yC01Ohc/eF38jwZ8JUjL1a+XHHXtGQgK+MxQbmSx0= +github.com/dghubble/oauth1 v0.6.0/go.mod h1:8pFdfPkv/jr8mkChVbNVuJ0suiHe278BtWI4Tk1ujxk= github.com/dghubble/sling v1.3.0 h1:pZHjCJq4zJvc6qVQ5wN1jo5oNZlNE0+8T/h0XeXBUKU= github.com/dghubble/sling v1.3.0/go.mod h1:XXShWaBWKzNLhu2OxikSNFrlsvowtz4kyRuXUG7oQKY= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -100,6 +104,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +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/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -109,6 +115,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -123,10 +131,12 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/guild.go b/guild.go new file mode 100644 index 0000000..0322bb9 --- /dev/null +++ b/guild.go @@ -0,0 +1,14 @@ +package overpass + +type Guild struct { + ID string + prefix string +} + +type GuildService interface { + Guild(id string) (*Guild, error) + AddGuild(g *Guild) error + DeleteGuild(g *Guild) error + UpdateGuild(g *Guild) error + GuildChannels(g *Guild) ([]*Channel, error) +} diff --git a/internal/exts/tweets/tweet_events.go b/internal/exts/tweets/tweet_events.go new file mode 100644 index 0000000..6896dd6 --- /dev/null +++ b/internal/exts/tweets/tweet_events.go @@ -0,0 +1,20 @@ +package tweets + +import ( + "fmt" + "log" + + "github.com/bwmarrin/discordgo" + "github.com/dustinpianalto/overpass/internal/twitter" +) + +func TweetHandler(session *discordgo.Session, tweetChan <-chan *twitter.Tweet) { + + for tweet := range tweetChan { + _, err := session.ChannelMessageSend("404569276012560386", fmt.Sprintf("%s\n%s - %s\n%s\n", tweet.IDStr, tweet.User.Name, tweet.User.IDStr, tweet.Text)) + if err != nil { + log.Println(err) + } + log.Printf("%s\n%s - %s\n%s\n", tweet.IDStr, tweet.User.Name, tweet.User.IDStr, tweet.Text) + } +} diff --git a/internal/oauth1/oauth1.go b/internal/oauth1/oauth1.go new file mode 100644 index 0000000..4767627 --- /dev/null +++ b/internal/oauth1/oauth1.go @@ -0,0 +1,21 @@ +package oauth1 + +import ( + "net/http" + "os" + + "github.com/dghubble/oauth1" +) + +func GetClient() *http.Client { + apiKey := os.Getenv("TWITTER_API_KEY") + apiSecret := os.Getenv("TWITTER_API_SECRET") + accessKey := os.Getenv("TWITTER_ACCESS_KEY") + accessSecret := os.Getenv("TWITTER_ACCESS_SECRET") + config := oauth1.NewConfig(apiKey, apiSecret) + token := oauth1.NewToken(accessKey, accessSecret) + // OAuth1 http.Client will automatically authorize Requests + httpClient := config.Client(oauth1.NoContext, token) + + return httpClient +} diff --git a/internal/oauth2/oauth.go b/internal/oauth2/oauth.go index 210bca1..07ca65e 100644 --- a/internal/oauth2/oauth.go +++ b/internal/oauth2/oauth.go @@ -1,4 +1,4 @@ -package oauth +package oauth2 import ( "net/http" diff --git a/internal/postgres/database.go b/internal/postgres/database.go new file mode 100644 index 0000000..e7c1a58 --- /dev/null +++ b/internal/postgres/database.go @@ -0,0 +1,21 @@ +package postgres + +import ( + "database/sql" + "fmt" + + _ "github.com/lib/pq" +) + +func ConnectDatabase(dbConnString string) *sql.DB { + db, err := sql.Open("postgres", dbConnString) + if err != nil { + panic(fmt.Sprintf("Can't connect to the database. %v", err)) + } else { + fmt.Println("Database Connected.") + } + db.SetMaxOpenConns(75) // The RDS instance has a max of 75 open connections + db.SetMaxIdleConns(5) + db.SetConnMaxLifetime(300) + return db +} diff --git a/internal/twitter/twitter.go b/internal/twitter/twitter.go index ede89cf..6f0fa82 100644 --- a/internal/twitter/twitter.go +++ b/internal/twitter/twitter.go @@ -4,19 +4,24 @@ import ( "log" "github.com/dghubble/go-twitter/twitter" - oauth "github.com/dustinpianalto/overpass/internal/oauth2" + "github.com/dustinpianalto/overpass/internal/oauth1" ) +type Tweet struct { + twitter.Tweet +} + func Connect() *twitter.Client { - httpClient := oauth.GetClient() + httpClient := oauth1.GetClient() return twitter.NewClient(httpClient) } -func StartUserScanner(client *twitter.Client, userID string) (chan *twitter.Tweet, *twitter.Stream) { +func StartUserScanner(client *twitter.Client, userID string, tweetChan chan *Tweet) *twitter.Stream { demux := twitter.NewSwitchDemux() - tweetChan := make(chan *twitter.Tweet, 10) demux.Tweet = func(tweet *twitter.Tweet) { - tweetChan <- tweet + if tweet.User.IDStr == userID { + tweetChan <- &Tweet{*tweet} + } } demux.StatusDeletion = func(deletion *twitter.StatusDeletion) { log.Printf("%#v\n", deletion) @@ -40,5 +45,5 @@ func StartUserScanner(client *twitter.Client, userID string) (chan *twitter.Twee log.Println(err) } go demux.HandleChan(stream.Messages) - return tweetChan, stream + return stream } diff --git a/tweet.go b/tweet.go new file mode 100644 index 0000000..7c1b653 --- /dev/null +++ b/tweet.go @@ -0,0 +1,15 @@ +package overpass + +type Tweet struct { + ID string + MessageID string + ChannelID string + GuildID string + AuthorID string +} + +type TweetService interface { + Tweet(id string) (*Tweet, error) + AddTweet(t *Tweet) error + DeleteTweet(t *Tweet) error +}