GithubHelp home page GithubHelp logo

chimeracoder / anaconda Goto Github PK

View Code? Open in Web Editor NEW
1.1K 23.0 247.0 580 KB

A Go client library for the Twitter 1.1 API

License: MIT License

Go 100.00%
go twitter golang go-library golang-library api-client

anaconda's Introduction

Anaconda

Build Status Build Status GoDoc

Anaconda is a simple, transparent Go package for accessing version 1.1 of the Twitter API.

Successful API queries return native Go structs that can be used immediately, with no need for type assertions.

Examples

Authentication

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:

api := anaconda.NewTwitterApiWithCredentials("your-access-token", "your-access-token-secret", "your-consumer-key", "your-consumer-secret")

Queries

Queries are conducted using a pointer to an authenticated TwitterApi struct. In v1.1 of Twitter's API, all requests should be authenticated.

searchResult, _ := api.GetSearch("golang", nil)
for _ , tweet := range searchResult.Statuses {
    fmt.Println(tweet.Text)
}

Certain endpoints allow separate optional parameter; if desired, these can be passed as the final parameter.

//Perhaps we want 30 values instead of the default 15
v := url.Values{}
v.Set("count", "30")
result, err := api.GetSearch("golang", v)

(Remember that url.Values is equivalent to a map[string][]string, if you find that more convenient notation when specifying values). Otherwise, nil suffices.

Streaming

Anaconda supports the Streaming APIs. You can use PublicStream* or UserStream API methods. A go loop is started an gives you an stream that sends interface{} objects through it's chan C Objects which you can cast into a tweet, event and more.

v := url.Values{}
s := api.UserStream(v)

for t := range s.C {
  switch v := t.(type) {
  case anaconda.Tweet:
    fmt.Printf("%-15s: %s\n", v.User.ScreenName, v.Text)
  case anaconda.EventTweet:
    switch v.Event.Event {
    case "favorite":
      sn := v.Source.ScreenName
      tw := v.TargetObject.Text
      fmt.Printf("Favorited by %-15s: %s\n", sn, tw)
    case "unfavorite":
      sn := v.Source.ScreenName
      tw := v.TargetObject.Text
      fmt.Printf("UnFavorited by %-15s: %s\n", sn, tw)
    }
  }
}

Endpoints

Anaconda implements most of the endpoints defined in the Twitter API documentation. For clarity, in most cases, the function name is simply the name of the HTTP method and the endpoint (e.g., the endpoint GET /friendships/incoming is provided by the function GetFriendshipsIncoming).

In a few cases, a shortened form has been chosen to make life easier (for example, retweeting is simply the function Retweet)

Error Handling, Rate Limiting, and Throttling

Error Handling

Twitter errors are returned as an ApiError, which satisfies the error interface and can be treated as a vanilla error. However, it also contains the additional information returned by the Twitter API that may be useful in deciding how to proceed after encountering an error.

If you make queries too quickly, you may bump against Twitter's rate limits. If this happens, anaconda automatically retries the query when the rate limit resets, using the X-Rate-Limit-Reset header that Twitter provides to determine how long to wait.

In other words, users of the anaconda library should not need to handle rate limiting errors themselves; this is handled seamlessly behind-the-scenes. If an error is returned by a function, another form of error must have occurred (which can be checked by using the fields provided by the ApiError struct).

(If desired, this feature can be turned off by calling ReturnRateLimitError(true).)

Throttling

Anaconda now supports automatic client-side throttling of queries to avoid hitting the Twitter rate-limit.

This is currently off by default; however, it may be turned on by default in future versions of the library, as the implementation is improved.

To set a delay between queries, use the SetDelay method:

api.SetDelay(10 * time.Second)

Delays are set specific to each TwitterApi struct, so queries that use different users' access credentials are completely independent.

To turn off automatic throttling, set the delay to 0:

api.SetDelay(0 * time.Second)

Query Queue Persistence

If your code creates a NewTwitterApi in a regularly called function, you'll need to call .Close() on the API struct to clear the queryQueue and allow the goroutine to exit. Otherwise you could see goroutine and therefor heap memory leaks in long-running applications.

Google App Engine

Since Google App Engine doesn't make the standard http.Transport available, it's necessary to tell Anaconda to use a different client context.

api = anaconda.NewTwitterApi("", "")
c := appengine.NewContext(r)
api.HttpClient.Transport = &urlfetch.Transport{Context: c}

License

Anaconda is free software licensed under the MIT/X11 license. Details provided in the LICENSE file.

anaconda's People

Contributors

abeestrada avatar aditya-stripe avatar ajorgensen avatar alexk111 avatar aswin avatar azr avatar benjojo avatar bharathmg avatar bobrik avatar bouk avatar cention-mujibur-rahman avatar chimeracoder avatar cocoeyes02 avatar dylangraham avatar eseglem avatar francesco149 avatar gaul avatar hamman avatar jbuberel avatar joeblubaugh avatar kamicup avatar muesli avatar nabkey avatar njern avatar penguinxr2 avatar plauche avatar pocke avatar ppone avatar shalecraig avatar thanawatp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

anaconda's Issues

Parse Tweet Coordinate

Hello,

I am relatively new to Go so please forgive me if this is a noob question.

I am trying to parse the coordinates out of a tweet. Currently I have the following code:

for _, tweet := range tweets {
    p := tweet.Coordinates.(map[string]interface {})
    c := p["coordinates"].([]interface{})
    lat := c[1].(float64)
    lng := c[0].(float64)

While this works fine I am wondering if there is a more idiomatic / type safe way too do this - perhaps with a struct like this (though I have no idea how to use this struct):

type geoJSON struct {
    Coordinates []float64 `json:"coordinates"`
    Type        string    `json:"type"`
}

Issue with Uploading Media

Hi,

I have a small proc gen bot using this api and it recently started to fail on the uploads. With no code change on my side.

I still have to do full testing but I noticed that twitter specifies you should be using multipart/form-data and should be set to application/octet-stream
https://dev.twitter.com/rest/reference/post/media/upload

The OAuth lib you are using doesn't use the normal go multipart writer and sets application/x-www-form-urlencoded. I'm wondering if Twitter got a bit more strict on this.

Is this a known issue? Is anyone else getting this?

Add a specific type to represent errors (implementing error interface, of course)

Right now error handling is pretty basic, but a dedicated error type would help applications that want to take different actions based on the specific error received (ie, to slow down when a 'Rate limit exceeded' error is encountered, versus a 'Sorry, that page does not exist" error.

(Even when we implement rate limiting as in #1, this will still be needed because we can't be sure that the same credentials aren't being used by some other application simultaneously).

Multiple applications per executable

Hello,

While making the twitter bot I realise that I should have to call two applications, e.g. use different application keys at the same time. It looks like the anaconda currently does not support it. I do not mind try to do it myself, but do you maybe have design considerations about it?

Regards,
Alex

Streaming API

It doesn't look like anaconda supports streaming API.

Dependency on net/url?

I had to add:

import (
    "net/url"
    "github.com/ChimeraCoder/anaconda"
)

Is that correct? If so, maybe nice to mention in the readme.md.

Great lib btw :-)

need help: multiple goroutines

Hi.
I am doing a Twitter bot working on several accounts (two in my case). But when I start a goroutine and initialize Twitter API, it stops the other one.

How should I handle multiple goroutines with Anaconda for my program to work ?

Thanks !

There was an error parsing the JSON document. The document may not be well-formed. unexpected non-whitespace character after JSON data at line 2 column 1

When I use the demo code I get this error in the browser. But if I was to grab a single tweet everything works fine. Does anybody have a work around or is this a bug?

searchResult, _ := api.GetSearch("golang", nil)
for _ , tweet := range searchResult.Statuses {
w.Header().Set("Content-Type", "Application/json;charset=UTF-8")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(tweet)
}

GetHomeTimeline doesn't allow you to pass custom values

Not sure why it was never implemented, but you can't pass url.Values to GetHomeTimeline. This makes it hard if you want to poll using "since_id".

Also why not expose apiGet/apiPost so people can extend missing api calls/options?

Cursors are annoying

...and also unnecessary! Thanks to the wonders of Go's channels, it should be easy to create auxiliary methods that abstract away the tedious, repeated calls to the same endpoint except with the cursor value changed.

Memory leak

anaconda.NewTwitterApi creates channel and go routine to listen for queries, but there's no way to close this channel and make object available for gc. This is kind of annoying when you create thousands of clients.

Best way to get new followers

What would be the "best way" to get new followers? Basically i have to follow everyone who follows me.

I know i could follow all the followers that is returned by GetFollowersList, but this doesn't seem to be a good way to do it.

Any recommendations will be appreciated.

Access to Rate Limit headers

Hello, I noticed the ApiError has access to the response headers. However, I was wondering if there is a way to access the headers on a success response too?

On any given successful response there is also rate-limit information passed back in the headers.
https://dev.twitter.com/rest/public/rate-limiting

X-Rate-Limit-Limit: the rate limit ceiling for that given request
X-Rate-Limit-Remaining: the number of requests left for the 15 minute window
X-Rate-Limit-Reset: the remaining window before the rate limit resets in UTC epoch seconds

If this is currently not available let me know if you have thoughts on where this could fit in the library. I'd be happy to help build it in.

"Could not authenticate you."

I can authenticate w/ mrjones/oauth and store the user token/secret, but after that when trying to use anaconda for any api requests just results in the error below.

I've verified that the consumer key/secret, and user token/secret are referenced correctly, but anaconda just does not want to work for me. Am I doing something obviously wrong here?

Get https://api.twitter.com/1.1/statuses/show.json?id=634839419317456896 returned status 401, {"errors":[{"code":32,"message":"Could not authenticate you."}]}
    anaconda.SetConsumerKey(os.Getenv("TWITTER_KEY"))
    anaconda.SetConsumerSecret(os.Getenv("TWITTER_SECRET"))
    api := anaconda.NewTwitterApi(userToken, userTokenSecret)
    res, err := api.GetTweet(634839419317456896, nil)

go get issue with dustin/gojson

go get github.com/ChimeraCoder/anaconda

github.com/dustin/gojson

../github.com/dustin/gojson/encode.go:247: undefined: sync.Pool

Unexpected property names for Tweet Entities

The returned JSON contains properties such as Display_url instead of display_url and Expanded_url instead of expanded_url.

Is there a reason for this? I see some fields do get renamed such as VideoInfo to video_info on line 47, but most don't.

RetweetedStatus contains string like "0xc2084ed700" instead of Tweet object

Hi! Getting great use out of this excellent lib. Thank you!

I need to make use of items in the RetweetedStatus (retweeted_status) object, but in all cases where there is a retweet, it looks like this RetweetedStatus:0xc2084ed700 instead of the full Twitter object which I expect to be there. (When it is not a retweet, it is RetweetedStatus:<nil> which is expected.)

Didn't find anyone else reporting this issue, but I can't see a way in which my own code would be causing it. Any ideas?

Thanks!

Support for lists

Hi!

I'm working on a small-ish project which will require support for Twitter Lists. Figured I'd add support for them to anaconda. Is this something you'd be interested in accepting a PR for once I am done?

Retweeted_status in Tweet

Why Tweet struct doesn't have a Retweeted_status struct inside such as Retweet struct? Some tweets fetched from a user timeline are truncated. It's possible to recover the full text without unmarshalling this Retweeted_struct from the response?

Cannot install on go 1.2 and 1.3

go get github.com/ChimeraCoder/anaconda
# github.com/dustin/gojson
../src/github.com/dustin/gojson/encode.go:247: undefined: sync.Pool

unable to override http client for oauth calls

Using anaconda within appengine fails as AuthorizationURL and GetCredentials use http.DefaultClient. As per the documentation, appengine fetches need to use the urlfetch package. It's possible to override the client for the API object, but this isn't used for these calls.

Either these methods should be on the API, which I think is tricky as it requires passing around the API to the callback, or the client could be passed in to the methods, which is unfortunate.

If there's another way to handle this, with the existing code or with a patch, i'd like to hear it.

Parse 'quoted_status'

Tweets may have "quoted_status" if the retweet was quoted. Having a pointer to "quoted_status" similar to "retweeted_status" would be great.

GetFriendsIdsAll Incomplete/Copy & Paste error?

The GetFriendsIdsAll function is identical to the GetFriendsIds function (and consequently doesn't match the docs).

Would be great to get that added as it looks like it would be much easier to use.

"WithheldInCountries" still string not []string

The field "withheld_in_countries" in Twitter Json structures (WithheldInCountries in User) is still string not []string (command GetUserTimeline), current version cannot unmarshal structures because of this issue.

Undo Retweets

Is it possible to undo retweets? Apparently it should be done using destroy api (noob in twitter API).

Standardize spelling of favorite/favourite

anacaonda.Tweet has a field called FavoriteCount while anaconda.User has a field called FavouritesCount.

It would be nice is the library used the same spelling for both fields. For what it's worth, the twitter API seems to prefer the non-US "favourite".

Use `go generate` to generate struct definitions automatically

With Go 1.4, the go generate command was added, which allows us to tie in gojson more cleanly. (gojson is the same tool that was being used previously, just informally).

Automatically generating the struct definitions is more robust, cleaner, less error-prone, and also makes it easier for us to update the library if the API changes at any point in the future.

PublicStreamFilter Streaming API doesn't work

Method calls that work with the standard api.GetSearch(...) fail with api.PublicStreamFilter(v), the debug output being:

2015/05/11 18:15:32 [start of for loop]
2015/05/11 18:15:32 [requesting stream]
2015/05/11 18:15:33 Twitter streaming: leaving after an irremediable error: [401 Authorization Required]
<hangs>

Simple repro below:

func main() {
    flag.Parse()

    anaconda.SetConsumerKey(*consumerKey)
    anaconda.SetConsumerSecret(*consumerSecret)
    api := anaconda.NewTwitterApi(*token, *tokenSecret)
    api.SetLogger(anaconda.BasicLogger)

    searchResult, err := api.GetSearch("twitter", nil)
    if err != nil {
        log.Fatal(err)
    }

    // works
    for _, tweet := range searchResult.Statuses {
        fmt.Println(tweet.Text)
    }

    v := url.Values{}
    v.Set("track", "tweet")
    // Fails: Twitter streaming: leaving after an irremediable error: [401 Authorization Required]
    stream := api.PublicStreamFilter(v)

    select {
    case <-stream.Quit:
        log.Println("Quitting")
    case elem := <-stream.C:
        fmt.Println(elem)
    }
}

GetFriendsListAll return only 200 friends

I tried get all friends of user but it returns only 200 of them. How can I get all of them ?

api := getNewAPI(token, tokenSecret)
v := url.Values{}
v.Set("count", "200")
v.Set("skip_status", "true")
friends := <-api.GetFriendsListAll(v)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.