Merge pull request #33 from rcarver/rc-stars
Refactor stars
Norberto Lopes
8 years ago
0 | package main | |
1 | ||
2 | import ( | |
3 | "flag" | |
4 | "fmt" | |
5 | ||
6 | "github.com/nlopes/slack" | |
7 | ) | |
8 | ||
9 | func main() { | |
10 | var ( | |
11 | apiToken string | |
12 | debug bool | |
13 | ) | |
14 | ||
15 | flag.StringVar(&apiToken, "token", "YOUR_TOKEN_HERE", "Your Slack API Token") | |
16 | flag.BoolVar(&debug, "debug", false, "Show JSON output") | |
17 | flag.Parse() | |
18 | ||
19 | api := slack.New(apiToken) | |
20 | if debug { | |
21 | api.SetDebug(true) | |
22 | } | |
23 | ||
24 | // Get all stars for the usr. | |
25 | params := slack.NewStarsParameters() | |
26 | starredItems, _, err := api.GetStarred(params) | |
27 | if err != nil { | |
28 | fmt.Printf("Error getting stars: %s\n", err) | |
29 | return | |
30 | } | |
31 | for _, s := range starredItems { | |
32 | var desc string | |
33 | switch s.Type { | |
34 | case slack.TYPE_MESSAGE: | |
35 | desc = s.Message.Text | |
36 | case slack.TYPE_FILE: | |
37 | desc = s.File.Name | |
38 | case slack.TYPE_FILE_COMMENT: | |
39 | desc = s.File.Name + " - " + s.Comment.Comment | |
40 | case slack.TYPE_CHANNEL, slack.TYPE_IM, slack.TYPE_GROUP: | |
41 | desc = s.Channel | |
42 | } | |
43 | fmt.Printf("Starred %s: %s\n", s.Type, desc) | |
44 | } | |
45 | } |
3 | 3 | TYPE_MESSAGE = "message" |
4 | 4 | TYPE_FILE = "file" |
5 | 5 | TYPE_FILE_COMMENT = "file_comment" |
6 | TYPE_CHANNEL = "channel" | |
7 | TYPE_IM = "im" | |
8 | TYPE_GROUP = "group" | |
6 | 9 | ) |
7 | 10 | |
8 | 11 | // Item is any type of slack message - message, file, or file comment. |
29 | 32 | return Item{Type: TYPE_FILE_COMMENT, File: f, Comment: c} |
30 | 33 | } |
31 | 34 | |
35 | // NewChannelItem turns a channel id into a typed channel struct. | |
36 | func NewChannelItem(ch string) Item { | |
37 | return Item{Type: TYPE_CHANNEL, Channel: ch} | |
38 | } | |
39 | ||
40 | // NewIMItem turns a channel id into a typed im struct. | |
41 | func NewIMItem(ch string) Item { | |
42 | return Item{Type: TYPE_IM, Channel: ch} | |
43 | } | |
44 | ||
45 | // NewGroupItem turns a channel id into a typed group struct. | |
46 | func NewGroupItem(ch string) Item { | |
47 | return Item{Type: TYPE_GROUP, Channel: ch} | |
48 | } | |
49 | ||
32 | 50 | // ItemRef is a reference to a message of any type. One of FileID, |
33 | 51 | // CommentId, or the combination of ChannelId and Timestamp must be |
34 | 52 | // specified. |
39 | 39 | } |
40 | 40 | if fci.Comment != c { |
41 | 41 | t.Errorf("got Comment %v, want %v", fci.Comment, c) |
42 | } | |
43 | } | |
44 | ||
45 | func TestNewChannelItem(t *testing.T) { | |
46 | c := "C1" | |
47 | ci := NewChannelItem(c) | |
48 | if ci.Type != TYPE_CHANNEL { | |
49 | t.Errorf("got Type %s, want %s", ci.Type, TYPE_CHANNEL) | |
50 | } | |
51 | if ci.Channel != "C1" { | |
52 | t.Errorf("got Channel %v, want %v", ci.Channel, "C1") | |
53 | } | |
54 | } | |
55 | ||
56 | func TestNewIMItem(t *testing.T) { | |
57 | c := "D1" | |
58 | ci := NewIMItem(c) | |
59 | if ci.Type != TYPE_IM { | |
60 | t.Errorf("got Type %s, want %s", ci.Type, TYPE_IM) | |
61 | } | |
62 | if ci.Channel != "D1" { | |
63 | t.Errorf("got Channel %v, want %v", ci.Channel, "D1") | |
64 | } | |
65 | } | |
66 | ||
67 | func TestNewGroupItem(t *testing.T) { | |
68 | c := "G1" | |
69 | ci := NewGroupItem(c) | |
70 | if ci.Type != TYPE_GROUP { | |
71 | t.Errorf("got Type %s, want %s", ci.Type, TYPE_GROUP) | |
72 | } | |
73 | if ci.Channel != "G1" { | |
74 | t.Errorf("got Channel %v, want %v", ci.Channel, "G1") | |
42 | 75 | } |
43 | 76 | } |
44 | 77 |
17 | 17 | Page int |
18 | 18 | } |
19 | 19 | |
20 | // TODO: Verify this. The whole thing is complicated. I don't like the way they mixed things | |
21 | // It also appears to be a bug in parsing the message | |
20 | // StarredItem is an item that has been starred. | |
22 | 21 | type StarredItem struct { |
23 | Type string `json:"type"` | |
24 | ChannelId string `json:"channel"` | |
25 | Message `json:"message,omitempty"` | |
26 | File `json:"file,omitempty"` | |
27 | Comment `json:"comment,omitempty"` | |
22 | Item | |
28 | 23 | } |
29 | 24 | |
30 | 25 | type starsResponseFull struct { |
52 | 47 | // } |
53 | 48 | // } |
54 | 49 | func (api *Slack) GetStarred(params StarsParameters) ([]StarredItem, *Paging, error) { |
55 | response := &starsResponseFull{} | |
56 | 50 | values := url.Values{ |
57 | 51 | "token": {api.config.token}, |
58 | 52 | } |
65 | 59 | if params.Page != DEFAULT_STARS_PAGE { |
66 | 60 | values.Add("page", strconv.Itoa(params.Page)) |
67 | 61 | } |
62 | response := &starsResponseFull{} | |
68 | 63 | err := parseResponse("stars.list", values, response, api.debug) |
69 | 64 | if err != nil { |
70 | 65 | return nil, nil, err |
5 | 5 | "testing" |
6 | 6 | ) |
7 | 7 | |
8 | var starsTests = struct { | |
9 | in []byte | |
10 | outItems []StarredItem | |
11 | outPaging *Paging | |
12 | }{ | |
13 | []byte(`{"ok": true, | |
8 | type starsHandler struct { | |
9 | gotParams map[string]string | |
10 | response string | |
11 | } | |
12 | ||
13 | func newStarsHandler() *starsHandler { | |
14 | return &starsHandler{ | |
15 | gotParams: make(map[string]string), | |
16 | response: `{ "ok": true }`, | |
17 | } | |
18 | } | |
19 | ||
20 | func (sh *starsHandler) accumulateFormValue(k string, r *http.Request) { | |
21 | if v := r.FormValue(k); v != "" { | |
22 | sh.gotParams[k] = v | |
23 | } | |
24 | } | |
25 | ||
26 | func (sh *starsHandler) handler(w http.ResponseWriter, r *http.Request) { | |
27 | sh.accumulateFormValue("user", r) | |
28 | sh.accumulateFormValue("count", r) | |
29 | sh.accumulateFormValue("page", r) | |
30 | w.Header().Set("Content-Type", "application/json") | |
31 | w.Write([]byte(sh.response)) | |
32 | } | |
33 | ||
34 | func TestSlack_GetStarred(t *testing.T) { | |
35 | once.Do(startServer) | |
36 | SLACK_API = "http://" + serverAddr + "/" | |
37 | api := New("testing-token") | |
38 | tests := []struct { | |
39 | params StarsParameters | |
40 | wantParams map[string]string | |
41 | json string | |
42 | starredItems []StarredItem | |
43 | paging *Paging | |
44 | }{ | |
45 | { | |
46 | StarsParameters{ | |
47 | User: "U1", | |
48 | Count: 10, | |
49 | Page: 100, | |
50 | }, | |
51 | map[string]string{ | |
52 | "user": "U1", | |
53 | "count": "10", | |
54 | "page": "100", | |
55 | }, | |
56 | `{"ok": true, | |
14 | 57 | "items": [ |
15 | 58 | { |
16 | 59 | "type": "message", |
17 | "channel": "C2147483705" | |
60 | "channel": "C2147483705", | |
61 | "message": { | |
62 | "text": "hello" | |
63 | } | |
18 | 64 | }, |
19 | 65 | { |
20 | "type": "file" | |
66 | "type": "file", | |
67 | "file": { | |
68 | "name": "toy" | |
69 | } | |
21 | 70 | }, |
22 | 71 | { |
23 | "type": "file_comment" | |
72 | "type": "file_comment", | |
73 | "file": { | |
74 | "name": "toy" | |
75 | }, | |
76 | "comment": { | |
77 | "comment": "nice" | |
78 | } | |
24 | 79 | }, |
25 | 80 | { |
26 | 81 | "type": "channel", |
27 | 82 | "channel": "C2147483705" |
83 | }, | |
84 | { | |
85 | "type": "im", | |
86 | "channel": "D1" | |
87 | }, | |
88 | { | |
89 | "type": "group", | |
90 | "channel": "G1" | |
28 | 91 | } |
29 | ||
30 | 92 | ], |
31 | 93 | "paging": { |
32 | 94 | "count": 100, |
33 | 95 | "total": 4, |
34 | 96 | "page": 1, |
35 | 97 | "pages": 1 |
36 | }}`), | |
37 | []StarredItem{ | |
38 | { | |
39 | Type: "message", | |
40 | ChannelId: "C2147483705", | |
98 | }}`, | |
99 | []StarredItem{ | |
100 | {Item: NewMessageItem("C2147483705", &Message{Msg: Msg{Text: "hello"}})}, | |
101 | {Item: NewFileItem(&File{Name: "toy"})}, | |
102 | {Item: NewFileCommentItem(&File{Name: "toy"}, &Comment{Comment: "nice"})}, | |
103 | {Item: NewChannelItem("C2147483705")}, | |
104 | {Item: NewIMItem("D1")}, | |
105 | {Item: NewGroupItem("G1")}, | |
106 | }, | |
107 | &Paging{ | |
108 | Count: 100, | |
109 | Total: 4, | |
110 | Page: 1, | |
111 | Pages: 1, | |
112 | }, | |
41 | 113 | }, |
42 | { | |
43 | Type: "file", | |
44 | }, | |
45 | { | |
46 | Type: "file_comment", | |
47 | }, | |
48 | { | |
49 | Type: "channel", | |
50 | ChannelId: "C2147483705", | |
51 | }, | |
52 | }, | |
53 | &Paging{ | |
54 | Count: 100, | |
55 | Total: 4, | |
56 | Page: 1, | |
57 | Pages: 1, | |
58 | }, | |
59 | } | |
60 | ||
61 | func getStarredHandler(rw http.ResponseWriter, r *http.Request) { | |
62 | rw.Header().Set("Content-Type", "application/json") | |
63 | // XXX: I stripped the actual content just to test this test Oo | |
64 | // At some point I should add valid content here | |
65 | rw.Write(starsTests.in) | |
66 | } | |
67 | ||
68 | func TestGetStarred(t *testing.T) { | |
69 | http.HandleFunc("/stars.list", getStarredHandler) | |
70 | once.Do(startServer) | |
71 | SLACK_API = "http://" + serverAddr + "/" | |
72 | api := New("testing-token") | |
73 | response_items, response_paging, err := api.GetStarred(NewStarsParameters()) | |
74 | if err != nil { | |
75 | t.Errorf("Unexpected error: %s", err) | |
76 | return | |
77 | 114 | } |
78 | eq := reflect.DeepEqual(response_items, starsTests.outItems) | |
79 | if !eq { | |
80 | t.Errorf("got %v; want %v", response_items, starsTests.outItems) | |
81 | } | |
82 | eq = reflect.DeepEqual(response_paging, starsTests.outPaging) | |
83 | if !eq { | |
84 | t.Errorf("got %v; want %v", response_paging, starsTests.outPaging) | |
115 | var sh *starsHandler | |
116 | http.HandleFunc("/stars.list", func(w http.ResponseWriter, r *http.Request) { sh.handler(w, r) }) | |
117 | for i, test := range tests { | |
118 | sh = newStarsHandler() | |
119 | sh.response = test.json | |
120 | response_items, response_paging, err := api.GetStarred(test.params) | |
121 | if err != nil { | |
122 | t.Fatalf("%d Unexpected error: %s", i, err) | |
123 | } | |
124 | if !reflect.DeepEqual(sh.gotParams, test.wantParams) { | |
125 | t.Errorf("%d got %v; want %v", i, sh.gotParams, test.wantParams) | |
126 | } | |
127 | if !reflect.DeepEqual(response_items, test.starredItems) { | |
128 | t.Errorf("%d got %v; want %v", i, response_items, test.starredItems) | |
129 | } | |
130 | if !reflect.DeepEqual(response_paging, test.paging) { | |
131 | t.Errorf("%d got %v; want %v", i, response_paging, test.paging) | |
132 | } | |
85 | 133 | } |
86 | 134 | } |