implement both AddReaction and GetReactions
Ryan Carver
8 years ago
4 | 4 | "net/url" |
5 | 5 | ) |
6 | 6 | |
7 | // Reaction describes the reaction and the item reacted to. One of file, | |
8 | // file_comment, or the combination of channel and timestamp must be specified. | |
7 | // Reaction is the act of reacting to an item. | |
9 | 8 | type Reaction struct { |
10 | Name string `json:"name"` | |
11 | File string `json:"file"` | |
12 | FileComment string `json:"file_comment"` | |
13 | Channel string `json:"channel"` | |
14 | Timestamp string `json:"timestamp"` | |
9 | Name string `json:"name"` | |
10 | ItemRef | |
15 | 11 | } |
16 | 12 | |
17 | // NewMessageReaction initializes a reaction to a message. | |
18 | func NewMessageReaction(name, channel, timestamp string) Reaction { | |
19 | return Reaction{Channel: channel, Timestamp: timestamp} | |
13 | // ItemReaction is the reactions that have happened on an item. | |
14 | type ItemReaction struct { | |
15 | Name string `json:"name"` | |
16 | Count int `json:"count"` | |
17 | Users []string `json:"users"` | |
20 | 18 | } |
21 | 19 | |
22 | // NewFileReaction initializes a reaction to a file. | |
23 | func NewFileReaction(name, file string) Reaction { | |
24 | return Reaction{Name: name, File: file} | |
25 | } | |
26 | ||
27 | // NewFileCommentReaction initializes a reaction to a file comment. | |
28 | func NewFileCommentReaction(name, fileComment string) Reaction { | |
29 | return Reaction{Name: name, FileComment: fileComment} | |
20 | type getReactionsResponseFull struct { | |
21 | Message struct { | |
22 | Message struct { | |
23 | Reactions []ItemReaction | |
24 | } | |
25 | } | |
26 | SlackResponse | |
30 | 27 | } |
31 | 28 | |
32 | 29 | func addReactionRequest(path string, values url.Values, debug bool) (*SlackResponse, error) { |
41 | 38 | return response, nil |
42 | 39 | } |
43 | 40 | |
41 | func getReactionRequest(path string, values url.Values, debug bool) (*getReactionsResponseFull, error) { | |
42 | response := &getReactionsResponseFull{} | |
43 | err := parseResponse(path, values, response, debug) | |
44 | if err != nil { | |
45 | return nil, err | |
46 | } | |
47 | if !response.Ok { | |
48 | return nil, errors.New(response.Error) | |
49 | } | |
50 | return response, nil | |
51 | } | |
52 | ||
53 | func setupReactionItemRef(values url.Values, item ItemRef) { | |
54 | if item.FileId != "" { | |
55 | values.Set("file", string(item.FileId)) | |
56 | } | |
57 | if item.FileCommentId != "" { | |
58 | values.Set("file_comment", string(item.FileCommentId)) | |
59 | } | |
60 | if item.ChannelId != "" { | |
61 | values.Set("channel", string(item.ChannelId)) | |
62 | } | |
63 | if item.Timestamp != "" { | |
64 | values.Set("timestamp", string(item.Timestamp)) | |
65 | } | |
66 | } | |
67 | ||
44 | 68 | // AddReaction adds a reaction emoji to a message, file or file comment. |
45 | func (api *Slack) AddReaction(reaction Reaction) error { | |
69 | func (api *Slack) AddReaction(name string, item ItemRef) error { | |
46 | 70 | values := url.Values{ |
47 | 71 | "token": {api.config.token}, |
48 | 72 | } |
49 | if reaction.Name != "" { | |
50 | values.Set("name", reaction.Name) | |
73 | if name != "" { | |
74 | values.Set("name", name) | |
51 | 75 | } |
52 | if reaction.File != "" { | |
53 | values.Set("file", string(reaction.File)) | |
54 | } | |
55 | if reaction.FileComment != "" { | |
56 | values.Set("file_comment", string(reaction.FileComment)) | |
57 | } | |
58 | if reaction.Channel != "" { | |
59 | values.Set("channel", string(reaction.Channel)) | |
60 | } | |
61 | if reaction.Timestamp != "" { | |
62 | values.Set("timestamp", string(reaction.Timestamp)) | |
63 | } | |
76 | setupReactionItemRef(values, item) | |
64 | 77 | _, err := addReactionRequest("reactions.add", values, api.debug) |
65 | 78 | if err != nil { |
66 | 79 | return err |
67 | 80 | } |
68 | 81 | return nil |
69 | 82 | } |
83 | ||
84 | // GetReactions returns details about the reactions on an item. | |
85 | func (api *Slack) GetReactions(item ItemRef) ([]ItemReaction, error) { | |
86 | values := url.Values{ | |
87 | "token": {api.config.token}, | |
88 | } | |
89 | setupReactionItemRef(values, item) | |
90 | response, err := getReactionRequest("reactions.get", values, api.debug) | |
91 | if err != nil { | |
92 | return nil, err | |
93 | } | |
94 | return response.Message.Message.Reactions, nil | |
95 | } |
6 | 6 | ) |
7 | 7 | |
8 | 8 | var ( |
9 | addedReaction Reaction | |
9 | addedReaction Reaction | |
10 | gottenReactionRef ItemRef | |
10 | 11 | ) |
11 | 12 | |
12 | 13 | func addReactionHandler(w http.ResponseWriter, r *http.Request) { |
13 | 14 | addedReaction.Name = r.FormValue("name") |
14 | addedReaction.File = r.FormValue("file") | |
15 | addedReaction.FileComment = r.FormValue("file_comment") | |
16 | addedReaction.Channel = r.FormValue("channel") | |
15 | addedReaction.FileId = r.FormValue("file") | |
16 | addedReaction.FileCommentId = r.FormValue("file_comment") | |
17 | addedReaction.ChannelId = r.FormValue("channel") | |
17 | 18 | addedReaction.Timestamp = r.FormValue("timestamp") |
18 | 19 | w.Header().Set("Content-Type", "application/json") |
19 | 20 | w.Write([]byte(`{ "ok": true }`)) |
21 | } | |
22 | ||
23 | func getReactionHandler(w http.ResponseWriter, r *http.Request) { | |
24 | gottenReactionRef.FileId = r.FormValue("file") | |
25 | gottenReactionRef.FileCommentId = r.FormValue("file_comment") | |
26 | gottenReactionRef.ChannelId = r.FormValue("channel") | |
27 | gottenReactionRef.Timestamp = r.FormValue("timestamp") | |
28 | w.Header().Set("Content-Type", "application/json") | |
29 | w.Write([]byte(`{"ok": true, | |
30 | "message": { | |
31 | "type": "message", | |
32 | "channel": "C2147483705", | |
33 | "message": { | |
34 | "type": "message", | |
35 | "ts": "111", | |
36 | "reactions": [ | |
37 | { | |
38 | "name": "astonished", | |
39 | "count": 3, | |
40 | "users": [ "U1", "U2", "U3" ] | |
41 | }, | |
42 | { | |
43 | "name": "clock1", | |
44 | "count": 3, | |
45 | "users": [ "U1", "U2" ] | |
46 | } | |
47 | ] | |
48 | } | |
49 | }}`)) | |
20 | 50 | } |
21 | 51 | |
22 | 52 | func TestSlack_AddReaction(t *testing.T) { |
24 | 54 | once.Do(startServer) |
25 | 55 | SLACK_API = "http://" + serverAddr + "/" |
26 | 56 | api := New("testing-token") |
27 | r := Reaction{} | |
28 | r.File = "FileID" | |
29 | r.FileComment = "FileCommentID" | |
30 | r.Channel = "ChannelID" | |
31 | r.Timestamp = "123" | |
57 | want := Reaction{} | |
58 | want.Name = "thumbsup" | |
59 | want.FileId = "FileID" | |
60 | want.FileCommentId = "FileCommentID" | |
61 | want.ChannelId = "ChannelID" | |
62 | want.Timestamp = "123" | |
32 | 63 | addedReaction = Reaction{} |
33 | err := api.AddReaction(r) | |
64 | err := api.AddReaction("thumbsup", want.ItemRef) | |
34 | 65 | if err != nil { |
35 | 66 | t.Fatalf("Unexpected error: %s", err) |
36 | 67 | } |
37 | if got := addedReaction; !reflect.DeepEqual(got, r) { | |
38 | t.Errorf("Got reaction %#v, want %#v", got, r) | |
68 | if got := addedReaction; !reflect.DeepEqual(got, want) { | |
69 | t.Errorf("Got reaction %#v, want %#v", got, want) | |
39 | 70 | } |
40 | 71 | } |
72 | ||
73 | func TestSlack_GetReaction(t *testing.T) { | |
74 | http.HandleFunc("/reactions.get", getReactionHandler) | |
75 | once.Do(startServer) | |
76 | SLACK_API = "http://" + serverAddr + "/" | |
77 | api := New("testing-token") | |
78 | ref := ItemRef{} | |
79 | ref.FileId = "FileID" | |
80 | ref.FileCommentId = "FileCommentID" | |
81 | ref.ChannelId = "ChannelID" | |
82 | ref.Timestamp = "123" | |
83 | gottenReactionRef = ItemRef{} | |
84 | got, err := api.GetReactions(ref) | |
85 | if err != nil { | |
86 | t.Fatalf("Unexpected error: %s", err) | |
87 | } | |
88 | if got, want := gottenReactionRef, ref; !reflect.DeepEqual(got, want) { | |
89 | t.Errorf("Got reaction ref %#v, want %#v", got, want) | |
90 | } | |
91 | want := []ItemReaction{ | |
92 | ItemReaction{Name: "astonished", Count: 3, Users: []string{"U1", "U2", "U3"}}, | |
93 | ItemReaction{Name: "clock1", Count: 3, Users: []string{"U1", "U2"}}, | |
94 | } | |
95 | if !reflect.DeepEqual(got, want) { | |
96 | t.Errorf("Got reaction %#v, want %#v", got, want) | |
97 | } | |
98 | } |