Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ Examples
If you already have the access token (and secret) for your user (Twitter provides this for your own account on the developer portal), creating the client is simple:

````go
anaconda.SetConsumerKey("your-consumer-key")
anaconda.SetConsumerSecret("your-consumer-secret")
api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret")
api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret", "your-consumer-key", "your-consumer-secret")
````

### Queries
Expand Down
11 changes: 3 additions & 8 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,12 @@ import (
// Initialize an client library for a given user.
// This only needs to be done *once* per user
func ExampleTwitterApi_InitializeClient() {
anaconda.SetConsumerKey("your-consumer-key")
anaconda.SetConsumerSecret("your-consumer-secret")
api := anaconda.NewTwitterApi(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api := anaconda.NewTwitterApi(ACCESS_TOKEN, ACCESS_TOKEN_SECRET, "your-consumer-key", "your-consumer-secret")
fmt.Println(*api.Credentials)
}

func ExampleTwitterApi_GetSearch() {

anaconda.SetConsumerKey("your-consumer-key")
anaconda.SetConsumerSecret("your-consumer-secret")
api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret")
api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret", "your-consumer-key", "your-consumer-secret")
search_result, err := api.GetSearch("golang", nil)
if err != nil {
panic(err)
Expand All @@ -32,7 +27,7 @@ func ExampleTwitterApi_GetSearch() {

// Throttling queries can easily be handled in the background, automatically
func ExampleTwitterApi_Throttling() {
api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret")
api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret", "your-consumer-key", "your-consumer-secret")
api.EnableThrottling(10*time.Second, 5)

// These queries will execute in order
Expand Down
2 changes: 1 addition & 1 deletion oembed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func TestOEmbed(t *testing.T) {
// It is the only one that can be tested without auth
// However, it is still rate-limited
api := anaconda.NewTwitterApi("", "")
api := anaconda.NewTwitterApi("", "", "", "")
api.SetBaseUrl(testBase)
o, err := api.GetOEmbed(url.Values{"id": []string{"99530515043983360"}})
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions streaming.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ func jsonToKnownType(j []byte) interface{} {
func (s *Stream) requestStream(urlStr string, v url.Values, method int) (resp *http.Response, err error) {
switch method {
case _GET:
return oauthClient.Get(s.api.HttpClient, s.api.Credentials, urlStr, v)
return s.api.oauthClient.Get(s.api.HttpClient, s.api.Credentials, urlStr, v)
case _POST:
return oauthClient.Post(s.api.HttpClient, s.api.Credentials, urlStr, v)
return s.api.oauthClient.Post(s.api.HttpClient, s.api.Credentials, urlStr, v)
default:
}
return nil, fmt.Errorf("HTTP method not yet supported")
Expand Down
50 changes: 19 additions & 31 deletions twitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@
//
//If you already have the access token (and secret) for your user (Twitter provides this for your own account on the developer portal), creating the client is simple:
//
// anaconda.SetConsumerKey("your-consumer-key")
// anaconda.SetConsumerSecret("your-consumer-secret")
// api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret")
//
// api := anaconda.NewTwitterApi("your-access-token", "your-access-token-secret", "your-consumer-key", "your-consumer-secret")
//
//Queries
//
Expand Down Expand Up @@ -60,13 +57,8 @@ const (
UploadBaseUrl = "https://upload.twitter.com/1.1"
)

var oauthClient = oauth.Client{
TemporaryCredentialRequestURI: "https://api.twitter.com/oauth/request_token",
ResourceOwnerAuthorizationURI: "https://api.twitter.com/oauth/authenticate",
TokenRequestURI: "https://api.twitter.com/oauth/access_token",
}

type TwitterApi struct {
oauthClient oauth.Client
Credentials *oauth.Credentials
queryQueue chan query
bucket *tokenbucket.Bucket
Expand Down Expand Up @@ -101,11 +93,20 @@ const DEFAULT_CAPACITY = 5

//NewTwitterApi takes an user-specific access token and secret and returns a TwitterApi struct for that user.
//The TwitterApi struct can be used for accessing any of the endpoints available.
func NewTwitterApi(access_token string, access_token_secret string) *TwitterApi {
func NewTwitterApi(access_token, access_token_secret, consumer_key, consumer_secret string) *TwitterApi {
//TODO figure out how much to buffer this channel
//A non-buffered channel will cause blocking when multiple queries are made at the same time
queue := make(chan query)
c := &TwitterApi{
oauthClient: oauth.Client{
TemporaryCredentialRequestURI: "https://api.twitter.com/oauth/request_token",
ResourceOwnerAuthorizationURI: "https://api.twitter.com/oauth/authenticate",
TokenRequestURI: "https://api.twitter.com/oauth/access_token",
Credentials: oauth.Credentials{
Token: consumer_key,
Secret: consumer_secret,
},
},
Credentials: &oauth.Credentials{
Token: access_token,
Secret: access_token_secret,
Expand All @@ -121,18 +122,6 @@ func NewTwitterApi(access_token string, access_token_secret string) *TwitterApi
return c
}

//SetConsumerKey will set the application-specific consumer_key used in the initial OAuth process
//This key is listed on https://dev.twitter.com/apps/YOUR_APP_ID/show
func SetConsumerKey(consumer_key string) {
oauthClient.Credentials.Token = consumer_key
}

//SetConsumerSecret will set the application-specific secret used in the initial OAuth process
//This secret is listed on https://dev.twitter.com/apps/YOUR_APP_ID/show
func SetConsumerSecret(consumer_secret string) {
oauthClient.Credentials.Secret = consumer_secret
}

// ReturnRateLimitError specifies behavior when the Twitter API returns a rate-limit error.
// If set to true, the query will fail and return the error instead of automatically queuing and
// retrying the query when the rate limit expires
Expand Down Expand Up @@ -167,17 +156,16 @@ func (c *TwitterApi) SetBaseUrl(baseUrl string) {

//AuthorizationURL generates the authorization URL for the first part of the OAuth handshake.
//Redirect the user to this URL.
//This assumes that the consumer key has already been set (using SetConsumerKey).
func AuthorizationURL(callback string) (string, *oauth.Credentials, error) {
tempCred, err := oauthClient.RequestTemporaryCredentials(http.DefaultClient, callback, nil)
func (c *TwitterApi) AuthorizationURL(callback string) (string, *oauth.Credentials, error) {
tempCred, err := c.oauthClient.RequestTemporaryCredentials(http.DefaultClient, callback, nil)
if err != nil {
return "", nil, err
}
return oauthClient.AuthorizationURL(tempCred, nil), tempCred, nil
return c.oauthClient.AuthorizationURL(tempCred, nil), tempCred, nil
}

func GetCredentials(tempCred *oauth.Credentials, verifier string) (*oauth.Credentials, url.Values, error) {
return oauthClient.RequestToken(http.DefaultClient, tempCred, verifier)
func (c *TwitterApi) GetCredentials(tempCred *oauth.Credentials, verifier string) (*oauth.Credentials, url.Values, error) {
return c.oauthClient.RequestToken(http.DefaultClient, tempCred, verifier)
}

func cleanValues(v url.Values) url.Values {
Expand All @@ -189,7 +177,7 @@ func cleanValues(v url.Values) url.Values {

// apiGet issues a GET request to the Twitter API and decodes the response JSON to data.
func (c TwitterApi) apiGet(urlStr string, form url.Values, data interface{}) error {
resp, err := oauthClient.Get(c.HttpClient, c.Credentials, urlStr, form)
resp, err := c.oauthClient.Get(c.HttpClient, c.Credentials, urlStr, form)
if err != nil {
return err
}
Expand All @@ -199,7 +187,7 @@ func (c TwitterApi) apiGet(urlStr string, form url.Values, data interface{}) err

// apiPost issues a POST request to the Twitter API and decodes the response JSON to data.
func (c TwitterApi) apiPost(urlStr string, form url.Values, data interface{}) error {
resp, err := oauthClient.Post(c.HttpClient, c.Credentials, urlStr, form)
resp, err := c.oauthClient.Post(c.HttpClient, c.Credentials, urlStr, form)
if err != nil {
return err
}
Expand Down
8 changes: 2 additions & 6 deletions twitter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ var testBase string

func init() {
// Initialize api so it can be used even when invidual tests are run in isolation
anaconda.SetConsumerKey(CONSUMER_KEY)
anaconda.SetConsumerSecret(CONSUMER_SECRET)
api = anaconda.NewTwitterApi(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = anaconda.NewTwitterApi(ACCESS_TOKEN, ACCESS_TOKEN_SECRET, CONSUMER_KEY, CONSUMER_SECRET)

if CONSUMER_KEY != "" && CONSUMER_SECRET != "" && ACCESS_TOKEN != "" && ACCESS_TOKEN_SECRET != "" {
return
Expand Down Expand Up @@ -115,9 +113,7 @@ func Test_TwitterCredentials(t *testing.T) {

// Test that creating a TwitterApi client creates a client with non-empty OAuth credentials
func Test_TwitterApi_NewTwitterApi(t *testing.T) {
anaconda.SetConsumerKey(CONSUMER_KEY)
anaconda.SetConsumerSecret(CONSUMER_SECRET)
apiLocal := anaconda.NewTwitterApi(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
apiLocal := anaconda.NewTwitterApi(ACCESS_TOKEN, ACCESS_TOKEN_SECRET, CONSUMER_KEY, CONSUMER_SECRET)

if apiLocal.Credentials == nil {
t.Fatalf("Twitter Api client has empty (nil) credentials")
Expand Down