Awesome
go-twitter
DEPRECATED As of Nov 2022, the go-twitter API library is no longer being developed. If you fork this repo, please remove the logo since it is not covered by the license.
<img align="right" src="https://storage.googleapis.com/dghubble/gopher-on-bird.png">go-twitter is a Go client library for the Twitter API. Check the usage section or try the examples to see how to access the Twitter API.
Features
- Twitter REST API:
- Accounts
- Blocks
- DirectMessageEvents
- Favorites
- Friends
- Friendships
- Followers
- Lists
- PremiumSearch
- RateLimits
- Search
- Statuses
- Timelines
- Users
- Twitter Streaming API
- Public Streams
- User Streams
- Site Streams
- Firehose Streams
Install
go get github.com/dghubble/go-twitter/twitter
Documentation
Read GoDoc
Usage
REST API
The twitter
package provides a Client
for accessing the Twitter API. Here are some example requests.
config := oauth1.NewConfig("consumerKey", "consumerSecret")
token := oauth1.NewToken("accessToken", "accessSecret")
httpClient := config.Client(oauth1.NoContext, token)
// Twitter client
client := twitter.NewClient(httpClient)
// Home Timeline
tweets, resp, err := client.Timelines.HomeTimeline(&twitter.HomeTimelineParams{
Count: 20,
})
// Send a Tweet
tweet, resp, err := client.Statuses.Update("just setting up my twttr", nil)
// Status Show
tweet, resp, err := client.Statuses.Show(585613041028431872, nil)
// Search Tweets
search, resp, err := client.Search.Tweets(&twitter.SearchTweetParams{
Query: "gopher",
})
// User Show
user, resp, err := client.Users.Show(&twitter.UserShowParams{
ScreenName: "dghubble",
})
// Followers
followers, resp, err := client.Followers.List(&twitter.FollowerListParams{})
Authentication is handled by the http.Client
passed to NewClient
to handle user auth (OAuth1) or application auth (OAuth2). See the Authentication section.
Required parameters are passed as positional arguments. Optional parameters are passed typed params structs (or nil).
Streaming API
The Twitter Public, User, Site, and Firehose Streaming APIs can be accessed through the Client
StreamService
which provides methods Filter
, Sample
, User
, Site
, and Firehose
.
Create a Client
with an authenticated http.Client
. All stream endpoints require a user auth context so choose an OAuth1 http.Client
.
client := twitter.NewClient(httpClient)
Next, request a managed Stream
be started.
Filter
Filter Streams return Tweets that match one or more filtering predicates such as Track
, Follow
, and Locations
.
params := &twitter.StreamFilterParams{
Track: []string{"kitten"},
StallWarnings: twitter.Bool(true),
}
stream, err := client.Streams.Filter(params)
User
User Streams provide messages specific to the authenticate User and possibly those they follow.
params := &twitter.StreamUserParams{
With: "followings",
StallWarnings: twitter.Bool(true),
}
stream, err := client.Streams.User(params)
Note To see Direct Message events, your consumer application must ask Users for read/write/DM access to their account.
Sample
Sample Streams return a small sample of public Tweets.
params := &twitter.StreamSampleParams{
StallWarnings: twitter.Bool(true),
}
stream, err := client.Streams.Sample(params)
Site, Firehose
Site and Firehose Streams require your application to have special permissions, but their API works the same way.
Receiving Messages
Each Stream
maintains the connection to the Twitter Streaming API endpoint, receives messages, and sends them on the Stream.Messages
channel.
Go channels support range iterations which allow you to read the messages which are of type interface{}
.
for message := range stream.Messages {
fmt.Println(message)
}
If you run this in your main goroutine, it will receive messages forever unless the stream stops. To continue execution, receive messages using a separate goroutine.
Demux
Receiving messages of type interface{}
isn't very nice, it means you'll have to type switch and probably filter out message types you don't care about.
For this, try a Demux
, like SwitchDemux
, which receives messages and type switches them to call functions with typed messages.
For example, say you're only interested in Tweets and Direct Messages.
demux := twitter.NewSwitchDemux()
demux.Tweet = func(tweet *twitter.Tweet) {
fmt.Println(tweet.Text)
}
demux.DM = func(dm *twitter.DirectMessage) {
fmt.Println(dm.SenderID)
}
Pass the Demux
each message or give it the entire Stream.Message
channel.
for message := range stream.Messages {
demux.Handle(message)
}
// or pass the channel
demux.HandleChan(stream.Messages)
Stopping
The Stream
will stop itself if the stream disconnects and retrying produces unrecoverable errors. When this occurs, Stream
will close the stream.Messages
channel, so execution will break out of any message for range loops.
When you are finished receiving from a Stream
, call Stop()
which closes the connection, channels, and stops the goroutine before returning. This ensures resources are properly cleaned up.
Pitfalls
Bad: In this example, Stop()
is unlikely to be reached. Control stays in the message loop unless the Stream
becomes disconnected and cannot retry.
// program does not terminate :(
stream, _ := client.Streams.Sample(params)
for message := range stream.Messages {
demux.Handle(message)
}
stream.Stop()
Bad: Here, messages are received on a non-main goroutine, but then Stop()
is called immediately. The Stream
is stopped and the program exits.
// got no messages :(
stream, _ := client.Streams.Sample(params)
go demux.HandleChan(stream.Messages)
stream.Stop()
Good: For main package scripts, one option is to receive messages in a goroutine and wait for CTRL-C to be pressed, then explicitly stop the Stream
.
stream, err := client.Streams.Sample(params)
go demux.HandleChan(stream.Messages)
// Wait for SIGINT and SIGTERM (HIT CTRL-C)
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
log.Println(<-ch)
stream.Stop()
Authentication
The API client accepts an any http.Client
capable of making user auth (OAuth1) or application auth (OAuth2) authorized requests. See the dghubble/oauth1 and golang/oauth2 packages which can provide such agnostic clients.
Passing an http.Client
directly grants you control over the underlying transport, avoids dependencies on particular OAuth1 or OAuth2 packages, and keeps client APIs separate from authentication protocols.
See the google/go-github client which takes the same approach.
For example, make requests as a consumer application on behalf of a user who has granted access, with OAuth1.
// OAuth1
import (
"github.com/dghubble/go-twitter/twitter"
"github.com/dghubble/oauth1"
)
config := oauth1.NewConfig("consumerKey", "consumerSecret")
token := oauth1.NewToken("accessToken", "accessSecret")
// http.Client will automatically authorize Requests
httpClient := config.Client(oauth1.NoContext, token)
// Twitter client
client := twitter.NewClient(httpClient)
If no user auth context is needed, make requests as your application with application auth.
// OAuth2
import (
"github.com/dghubble/go-twitter/twitter"
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
)
// oauth2 configures a client that uses app credentials to keep a fresh token
config := &clientcredentials.Config{
ClientID: "consumerKey",
ClientSecret: "consumerSecret",
TokenURL: "https://api.twitter.com/oauth2/token",
}
// http.Client will automatically authorize Requests
httpClient := config.Client(oauth2.NoContext)
// Twitter client
client := twitter.NewClient(httpClient)
To implement Login with Twitter for web or mobile, see the gologin package and examples.
Roadmap
- Support gzipped streams
- Auto-stop streams in the event of long stalls
Contributing
See the Contributing Guide.