-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from groupme/magnificrogue/go-twitter-bot
Add go based twitter bot example
- Loading branch information
Showing
10 changed files
with
685 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
FROM golang:1.16-alpine as base | ||
WORKDIR /app | ||
RUN apk add --no-cache make | ||
|
||
FROM base as builder | ||
COPY . ./ | ||
RUN go mod download | ||
RUN make build | ||
RUN chmod +x /app/bin/main | ||
|
||
FROM base as runtime | ||
|
||
COPY --from=builder /app/bin/main . | ||
|
||
CMD /app/main -tweet-query=${TWEET_QUERY} -groupme-bot-id=${GROUPME_BOT_ID} -twitter-app-key=${TWITTER_APP_KEY} -twitter-app-secret=${TWITTER_APP_SECRET} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
build: | ||
go build -o bin/main cmd/main.go | ||
|
||
run: | ||
go run cmd/main.go -tweet-query=${TWEET_QUERY} -groupme-bot-id=${GROUPME_BOT_ID} -twitter-app-key=${TWITTER_APP_KEY} -twitter-app-secret=${TWITTER_APP_SECRET} | ||
|
||
container: | ||
docker build -t groupme/twitterbot . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# What is it | ||
|
||
It is a simple bot that attempts to read tweets from twitter, specified by the tweet-query passed, and write it to a given group by using a bot user. | ||
|
||
|
||
# How to use it | ||
To use this bot in either a docker container or locally, you'll need the following: | ||
|
||
1) A query for tweets set in an environment variable TWEET_QUERY | ||
2) A groupMe bot ID set in GROUPME_BOT_ID | ||
3) A twitter app key and secret, set in TWITTER_APP_KEY and TWITTER_APP_SECRET respectively | ||
|
||
## Locally | ||
1. Have go/make installed. | ||
2. $ make run # Run in your terminal | ||
|
||
## In a container | ||
1. Ensure the environment variables above are set | ||
2. Run /app/main -tweet-query=${TWEET_QUERY} -groupme-bot-id=${GROUPME_BOT_ID} -twitter-app-key=${TWITTER_APP_KEY} -twitter-app-secret=${TWITTER_APP_SECRET} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package twitterbot | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"net/http" | ||
|
||
"github.com/Azure/go-autorest/autorest" | ||
) | ||
|
||
// BotClient is a simple wrapper for writing messages on GroupMe | ||
type BotClient struct { | ||
botID string | ||
} | ||
|
||
// NewBotClient returns a configured BotClient suitable for use | ||
func NewBotClient(botID string) (*BotClient, error) { | ||
if botID == "" { | ||
return nil, errors.New("Can't instantiate a bot client with no botID") | ||
} else { | ||
return &BotClient{ | ||
botID: botID, | ||
}, nil | ||
} | ||
} | ||
|
||
// botMessage is a simplified message body for some text sent on behalf of a bot. | ||
type botMessage struct { | ||
BotID string `json:"bot_id"` | ||
Text string `json:"text"` | ||
} | ||
|
||
// SendMessage posts a message on behalf of a bot. If the message is empty, an error will be returned | ||
func (bc *BotClient) SendMessage(message string) error { | ||
req, err := autorest.Prepare(&http.Request{}, | ||
autorest.WithBaseURL("https://api.groupme.com/v3/bots/post"), | ||
autorest.WithMethod("POST"), | ||
autorest.WithHeader("Content-Type", "application/json"), | ||
autorest.WithJSON(botMessage{ | ||
BotID: bc.botID, | ||
Text: message, | ||
}), | ||
) | ||
if err != nil { | ||
return fmt.Errorf("Unable to construct request to send message on behalf of bot: %w", err) | ||
} | ||
|
||
resp, err := autorest.Send(req) | ||
if err != nil { | ||
return fmt.Errorf("Error sending request to create a message: %w", err) | ||
} | ||
|
||
if resp.StatusCode != http.StatusAccepted { | ||
bytes, _ := ioutil.ReadAll(resp.Body) | ||
log.Fatal("Bad response code from GroupMe:", string(bytes)) | ||
err := fmt.Errorf("Unexpected HTTP status code when creating message: %d", resp.StatusCode) | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"os" | ||
"os/signal" | ||
"strings" | ||
"time" | ||
|
||
twitterbot "github.com/groupme/BotExamples/go/twitter-bot" | ||
) | ||
|
||
var ( | ||
flagTweetQuery = flag.String("tweet-query", "groupme,cats,burrito", "What tags to filter on. Passed as a single comma seperated string") | ||
flagGroupMeBotID = flag.String("groupme-bot-id", "", "Identifier for your bot on GroupMe") | ||
flagTwitterAppKey = flag.String("twitter-app-key", "", "Developer Key associated with your twitter project") | ||
flagTwitterAppSecret = flag.String("twitter-app-secret", "", "Developer secret associated with your twitter project") | ||
) | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
// setup signal aware context. | ||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) | ||
defer cancel() | ||
|
||
twitterClient, _ := twitterbot.NewTwitterClient(*flagTwitterAppKey, *flagTwitterAppSecret) | ||
botClient, _ := twitterbot.NewBotClient(*flagGroupMeBotID) | ||
|
||
poster, err := twitterbot.NewTwitterPoster(twitterClient, botClient, strings.Split(*flagTweetQuery, ",")...) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Default rate limit is 450 requests in an hour, so fetch new tweets every 10 seconds | ||
go poster.StartListening(time.Second * 10) | ||
|
||
<-ctx.Done() | ||
|
||
poster.StopListening() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module github.com/groupme/BotExamples/go/twitter-bot | ||
|
||
go 1.16 | ||
|
||
require ( | ||
github.com/Azure/go-autorest/autorest v0.11.19 // indirect | ||
github.com/dghubble/go-twitter v0.0.0-20210609183100-2fdbf421508e // indirect | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect | ||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 // indirect | ||
) |
Oops, something went wrong.