Skip to content
This repository was archived by the owner on Nov 5, 2022. It is now read-only.

Commit 15e71f0

Browse files
authored
Merge pull request #36 from Fallenstedt/rc/0.4.1
0.4.1
2 parents 04b1953 + de2d3ae commit 15e71f0

16 files changed

+278
-48
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ api.SetUnmarshalHook(func(bytes []byte) (interface{}, error) {
118118

119119
##### Start Stream
120120
Start your stream. This is a long-running HTTP GET request.
121-
You can get specific data you want by adding [query params](https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream).
122-
Additionally, [view an example of query params here](https://developer.twitter.com/en/docs/twitter-api/expansions), or in the [examples](https://github.com/fallenstedt/twitter-stream/tree/master/example)
121+
You can request additional tweet data by adding [query params](https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream).
122+
Use the `twitterstream.NewStreamQueryParamsBuilder()` to start a stream with the data you want.
123123

124124
```go
125125

@@ -142,7 +142,15 @@ func fetchTweets() stream.IStream {
142142
}
143143
return data, err
144144
})
145-
err = api.StartStream("?expansions=author_id&tweet.fields=created_at")
145+
146+
// https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream
147+
streamExpansions := twitterstream.NewStreamQueryParamsBuilder().
148+
AddExpansion("author_id").
149+
AddTweetField("created_at").
150+
Build()
151+
152+
// StartStream will start the stream
153+
err = api.StartStream(streamExpansions)
146154

147155
if err != nil {
148156
panic(err)
@@ -162,7 +170,7 @@ func initiateStream() {
162170
// When the loop below ends, restart the stream
163171
defer initiateStream()
164172

165-
// Start processing data from twitter
173+
// Start processing data from twitter after starting the stream
166174
for tweet := range api.GetMessages() {
167175

168176
// Handle disconnections from twitter

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.4.0
1+
0.4.1

example/create_rules_example.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func deleteRules() {
6868
api := twitterstream.NewTwitterStream(tok.AccessToken)
6969

7070
// use api.Rules.Get to find the ID number for an existing rule
71-
res, err := api.Rules.Delete(rules.NewDeleteRulesRequest(1469776000158363653, 1469776000158363654), false)
71+
res, err := api.Rules.Delete(rules.NewDeleteRulesRequest(1469777072675450881, 74893274932), false)
7272

7373
if err != nil {
7474
panic(err)
@@ -89,4 +89,4 @@ func printRules(data []rules.DataRule) {
8989
fmt.Printf("Tag: %v\n",datum.Tag)
9090
fmt.Printf("Value: %v\n\n", datum.Value)
9191
}
92-
}
92+
}

example/main.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const SECRET = "SECRET"
55

66
func main() {
77
// Run an example function
8-
98
addRules()
109
getRules()
1110
initiateStream()

example/stream_forever.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,24 +75,37 @@ func initiateStream() {
7575
}
7676

7777
func fetchTweets() stream.IStream {
78+
// Get Bearer Token using API keys
7879
tok, err := getTwitterToken()
7980
if err != nil {
8081
panic(err)
8182
}
8283

84+
// Instantiate an instance of twitter stream using the bearer token
8385
api := getTwitterStreamApi(tok)
86+
87+
// On Each tweet, decode the bytes into a StreamDataExample struct
8488
api.SetUnmarshalHook(func(bytes []byte) (interface{}, error) {
8589
data := StreamDataExample{}
8690
if err := json.Unmarshal(bytes, &data); err != nil {
8791
fmt.Printf("failed to unmarshal bytes: %v", err)
8892
}
8993
return data, err
9094
})
91-
err = api.StartStream("?expansions=author_id&tweet.fields=created_at")
95+
96+
// Request additional data from teach tweet
97+
streamExpansions := twitterstream.NewStreamQueryParamsBuilder().
98+
AddExpansion("author_id").
99+
AddTweetField("created_at").
100+
Build()
101+
102+
// Start the Stream
103+
err = api.StartStream(streamExpansions)
92104
if err != nil {
93105
panic(err)
94106
}
95107

108+
// Return the twitter stream api instance
96109
return api
97110
}
98111

httpclient/http_client_mock.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
11
package httpclient
22

3-
import "net/http"
3+
import (
4+
"net/http"
5+
"net/url"
6+
)
47

58
type mockHttpClient struct {
69
token string
710
MockNewHttpRequest func(opts *RequestOpts) (*http.Response, error)
8-
MockGetSearchStream func(queryParams string) (*http.Response, error)
11+
MockGetSearchStream func(queryParams *url.Values) (*http.Response, error)
912
MockGetRules func() (*http.Response, error)
10-
MockAddRules func(queryParams string, body string) (*http.Response, error)
11-
MockGenerateUrl func(name string, queryParams string) (string, error)
13+
MockAddRules func(queryParams *url.Values, body string) (*http.Response, error)
14+
MockGenerateUrl func(name string, queryParams *url.Values) (string, error)
1215
}
1316

1417
func NewHttpClientMock(token string) *mockHttpClient {
1518
return &mockHttpClient{token: token}
1619
}
1720

18-
func (t *mockHttpClient) GenerateUrl(name string, queryParams string) (string, error) {
21+
func (t *mockHttpClient) GenerateUrl(name string, queryParams *url.Values) (string, error) {
1922
return t.MockGenerateUrl(name, queryParams)
2023
}
2124

2225
func (t *mockHttpClient) GetRules() (*http.Response, error) {
2326
return t.MockGetRules()
2427
}
2528

26-
func (t *mockHttpClient) AddRules(queryParams string, body string) (*http.Response, error) {
29+
func (t *mockHttpClient) AddRules(queryParams *url.Values, body string) (*http.Response, error) {
2730
return t.MockAddRules(queryParams, body)
2831
}
2932

30-
func (t *mockHttpClient) GetSearchStream(queryParams string) (*http.Response, error) {
33+
func (t *mockHttpClient) GetSearchStream(queryParams *url.Values) (*http.Response, error) {
3134
return t.MockGetSearchStream(queryParams)
3235
}
3336

httpclient/httpclient.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package httpclient
33
import (
44
"bytes"
55
"errors"
6+
"fmt"
67
"log"
78
"net/http"
9+
"net/url"
810
"strings"
911
)
1012

@@ -18,9 +20,9 @@ type (
1820
IHttpClient interface {
1921
NewHttpRequest(opts *RequestOpts) (*http.Response, error)
2022
GetRules() (*http.Response, error)
21-
GetSearchStream(queryParams string) (*http.Response, error)
22-
AddRules(queryParams string, body string) (*http.Response, error)
23-
GenerateUrl(name string, queryParams string) (string, error)
23+
GetSearchStream(queryParams *url.Values) (*http.Response, error)
24+
AddRules(queryParams *url.Values, body string) (*http.Response, error)
25+
GenerateUrl(name string, queryParams *url.Values) (string, error)
2426
}
2527

2628
httpClient struct {
@@ -48,7 +50,7 @@ func (t *httpClient) GetRules() (*http.Response, error) {
4850
}
4951

5052
// AddRules will add rules for you to stream with.
51-
func (t *httpClient) AddRules(queryParams string, body string) (*http.Response, error) {
53+
func (t *httpClient) AddRules(queryParams *url.Values, body string) (*http.Response, error) {
5254
url, err := t.GenerateUrl("rules", queryParams)
5355

5456
if err != nil {
@@ -69,7 +71,7 @@ func (t *httpClient) AddRules(queryParams string, body string) (*http.Response,
6971
}
7072

7173
// GetSearchStream will start the stream with twitter.
72-
func (t *httpClient) GetSearchStream(queryParams string) (*http.Response, error) {
74+
func (t *httpClient) GetSearchStream(queryParams *url.Values) (*http.Response, error) {
7375
// Make an HTTP GET request to GET /2/tweets/search/stream
7476
url, err := t.GenerateUrl("stream", queryParams)
7577

@@ -90,10 +92,10 @@ func (t *httpClient) GetSearchStream(queryParams string) (*http.Response, error)
9092
}
9193

9294
// GenerateUrl is a utility function for httpclient package to generate a valid url for api.twitter.
93-
func (t *httpClient) GenerateUrl(name string, queryParams string) (string, error) {
95+
func (t *httpClient) GenerateUrl(name string, queryParams *url.Values) (string, error) {
9496
var url string
95-
if len(queryParams) > 0 {
96-
url = Endpoints[name] + queryParams
97+
if queryParams != nil {
98+
url = Endpoints[name] + fmt.Sprintf("?%v", queryParams.Encode())
9799
} else {
98100
url = Endpoints[name]
99101
}

rules/rule_builder.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
package rules
22

33
type (
4+
// IRuleBuilder is an interface that describers how to implement a RuleBuilder.
45
IRuleBuilder interface {
56
AddRule(value string, tag string) *RuleBuilder
67
Build() CreateRulesRequest
78
}
89

10+
// RuleValue is a struct used to help create twitter stream rules.
11+
// It takes in a value and a tag.
912
RuleValue struct {
1013
Value *string `json:"value,omitempty"`
1114
Tag *string `json:"tag,omitempty"`
1215
}
1316

17+
// RuleBuilder is struct used to help create twitter stream rules.
1418
RuleBuilder struct {
1519
rules []*RuleValue
1620
}
1721

22+
// CreateRulesRequest is a struct used to create the payload for creating rules.
1823
CreateRulesRequest struct {
1924
Add []*RuleValue `json:"add"`
2025
}
2126

27+
// DeleteRulesRequest is a struct used to create the payload for deleting rules.
2228
DeleteRulesRequest struct {
2329
Delete struct {
2430
Ids []int `json:"ids"`
@@ -27,12 +33,14 @@ type (
2733

2834
)
2935

36+
// NewDeleteRulesRequest will create an instance of DeleteRulesRequest.
3037
func NewDeleteRulesRequest(ids ...int) DeleteRulesRequest {
3138
return DeleteRulesRequest{Delete: struct {
3239
Ids []int `json:"ids"`
3340
}(struct{ Ids []int }{Ids: ids})}
3441
}
3542

43+
// NewRuleBuilder will create an instance of `RuleBuilder`.
3644
func NewRuleBuilder() *RuleBuilder {
3745
return &RuleBuilder{
3846
rules: []*RuleValue{},
@@ -64,4 +72,3 @@ func (r *RuleValue) setValueTag(value string, tag string) *RuleValue {
6472
r.Tag = &tag
6573
return r
6674
}
67-

rules/rule_builder_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ func TestNewRuleBuilderBuildsManyRules(t *testing.T) {
4444
if string(body) != "{\"add\":[{\"value\":\"cats\",\"tag\":\"cat tweets\"},{\"value\":\"dogs\",\"tag\":\"dog tweets\"}]}" {
4545
t.Errorf("Expected %v to equal %v", string(body), "{\"add\":[{\"value\":\"cats\",\"tag\":\"cat tweets\"},{\"value\":\"dogs\",\"tag\":\"dog tweets\"}]}")
4646
}
47-
}
47+
}

rules/rules.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package rules
33
import (
44
"encoding/json"
55
"github.com/fallenstedt/twitter-stream/httpclient"
6+
"net/url"
67
)
78

89
type (
@@ -68,13 +69,7 @@ func (t *rules) Create(rules CreateRulesRequest, dryRun bool) (*TwitterRuleRespo
6869
return nil, err
6970
}
7071

71-
res, err := t.httpClient.AddRules(func() string {
72-
if dryRun {
73-
return "?dry_run=true"
74-
} else {
75-
return ""
76-
}
77-
}(), string(body))
72+
res, err := t.httpClient.AddRules(t.addDryRun(dryRun), string(body))
7873

7974
if err != nil {
8075
return nil, err
@@ -95,13 +90,7 @@ func (t *rules) Delete(req DeleteRulesRequest, dryRun bool) (*TwitterRuleRespons
9590
return nil, err
9691
}
9792

98-
res, err := t.httpClient.AddRules(func() string {
99-
if dryRun {
100-
return "?dry_run=true"
101-
} else {
102-
return ""
103-
}
104-
}(), string(body))
93+
res, err := t.httpClient.AddRules(t.addDryRun(dryRun), string(body))
10594

10695

10796
defer res.Body.Close()
@@ -127,3 +116,14 @@ func (t *rules) Get() (*TwitterRuleResponse, error) {
127116
return data, nil
128117
}
129118

119+
120+
121+
func (t *rules) addDryRun(dryRun bool) *url.Values {
122+
if dryRun {
123+
query := new(url.URL).Query()
124+
query.Add("dry_run", "true")
125+
return &query
126+
} else {
127+
return nil
128+
}
129+
}

0 commit comments

Comments
 (0)