func NewOAuth1Encoder(config OAuthConfig) HeaderEncoder { var client oauth.Client = oauth.Client{Credentials: config.Consumer} var token oauth.Credentials = config.Token return func(r *rpc.Request, v interface{}, req *http.Request) error { var signUrl url.URL = *req.URL var params = signUrl.Query() // OAuth library appends the full set of signed params to the signing url. signUrl.RawQuery = "" client.SignParam(&token, req.Method, signUrl.String(), params) req.URL.RawQuery = params.Encode() return nil } }
func post(client *oauth.Client, cred *oauth.Credentials, s string) { param := make(url.Values) param.Set("status", s) uri := "https://api.twitter.com/1.1/statuses/update.json" client.SignParam(cred, "POST", uri, param) res, err := http.PostForm(uri, url.Values(param)) if err != nil { log.Println("failed to post tweet:", err) return } defer res.Body.Close() if res.StatusCode != 200 { log.Println("failed to get timeline:", err) return } }
func show(client *oauth.Client, cred *oauth.Credentials, f func(t *tweet)) { param := make(url.Values) uri := "https://api.twitter.com/1.1/statuses/home_timeline.json" client.SignParam(cred, "GET", uri, param) uri = uri + "?" + param.Encode() res, err := http.Get(uri) if err != nil { return } defer res.Body.Close() if res.StatusCode != 200 { return } var tweets []tweet json.NewDecoder(res.Body).Decode(&tweets) for _, t := range tweets { f(&t) } }
func stream(client *oauth.Client, cred *oauth.Credentials, f func(*tweet)) { param := make(url.Values) uri := "https://userstream.twitter.com/1.1/user.json" client.SignParam(cred, "GET", uri, param) uri = uri + "?" + param.Encode() res, err := http.Get(uri) if err != nil { log.Fatal("failed to get tweets:", err) } defer res.Body.Close() if res.StatusCode != 200 { log.Fatal("failed to get tweets:", err) } var buf *bufio.Reader if res.Header.Get("Content-Encoding") == "gzip" { gr, err := gzip.NewReader(res.Body) if err != nil { log.Fatal("failed to make gzip decoder:", err) } buf = bufio.NewReader(gr) } else { buf = bufio.NewReader(res.Body) } var last []byte for alive { b, _, err := buf.ReadLine() last = append(last, b...) var t tweet err = json.Unmarshal(last, &t) if err != nil { continue } last = []byte{} if t.Text == "" { continue } f(&t) } }
// Open opens a new stream. func Open(oauthClient *oauth.Client, accessToken *oauth.Credentials, urlStr string, params url.Values) (*Stream, error) { ts := new(Stream) u, err := url.Parse(urlStr) if err != nil { return nil, err } addr := u.Host if strings.LastIndex(addr, ":") <= strings.LastIndex(addr, "]") { if u.Scheme == "http" { addr = addr + ":80" } else { addr = addr + ":443" } } if u.Scheme == "http" { ts.conn, err = net.Dial("tcp", addr) if err != nil { return nil, err } } else { ts.conn, err = tls.Dial("tcp", addr, nil) if err != nil { return nil, err } if err = ts.conn.(*tls.Conn).VerifyHostname(addr[:strings.LastIndex(addr, ":")]); err != nil { return nil, ts.fatal(err) } } // Setup request body. pcopy := url.Values{} for key, values := range params { pcopy[key] = values } oauthClient.SignParam(accessToken, "POST", urlStr, pcopy) body := pcopy.Encode() var req bytes.Buffer req.WriteString("POST ") req.WriteString(u.RequestURI()) req.WriteString(" HTTP/1.1") req.WriteString("\r\nHost: ") req.WriteString(u.Host) req.WriteString("\r\nContent-Type: application/x-www-form-urlencoded") req.WriteString("\r\nContent-Length: ") req.WriteString(strconv.Itoa(len(body))) req.WriteString("\r\n\r\n") req.WriteString(body) _, err = ts.conn.Write(req.Bytes()) if err != nil { return nil, ts.fatal(err) } // Must connect in 60 seconds. err = ts.conn.SetReadDeadline(time.Now().Add(60 * time.Second)) if err != nil { return nil, ts.fatal(err) } ts.r = bufio.NewReaderSize(ts.conn, 8192) p, err := ts.r.ReadSlice('\n') if err != nil { return nil, ts.fatal(err) } m := responseLineRegexp.FindSubmatch(p) if m == nil { return nil, ts.fatal(errors.New("twitterstream: bad http response line")) } // Skip headers for { p, err = ts.r.ReadSlice('\n') if err != nil { return nil, ts.fatal(err) } if len(p) <= 2 { break } } statusCode, _ := strconv.Atoi(string(m[1])) if statusCode != 200 { p, _ := ioutil.ReadAll(ts.r) return nil, HTTPStatusError{statusCode, string(p)} } ts.chunkState = stateStart return ts, nil }