Codebase list golang-github-nlopes-slack / 8c25eff
Merge pull request #155 from theckman/custom_status_support add support for setting and unsetting Custom Status/Emoji Florin Pățan authored 7 years ago GitHub committed 7 years ago
2 changed file(s) with 158 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
00 package slack
11
22 import (
3 "encoding/json"
34 "errors"
45 "net/url"
56 )
2829 Title string `json:"title"`
2930 BotID string `json:"bot_id,omitempty"`
3031 ApiAppID string `json:"api_app_id,omitempty"`
32 StatusText string `json:"status_text,omitempty"`
33 StatusEmoji string `json:"status_emoji,omitempty"`
3134 }
3235
3336 // User contains all the information of a user
249252 }
250253 return nil
251254 }
255
256 // SetUserCustomStatus will set a custom status and emoji for the currently
257 // authenticated user. If statusEmoji is "" and statusText is not, the Slack API
258 // will automatically set it to ":speech_balloon:". Otherwise, if both are ""
259 // the Slack API will unset the custom status/emoji.
260 func (api *Client) SetUserCustomStatus(statusText, statusEmoji string) error {
261 // XXX(theckman): this anonymous struct is for making requests to the Slack
262 // API for setting and unsetting a User's Custom Status/Emoji. To change
263 // these values we must provide a JSON document as the profile POST field.
264 //
265 // We use an anonymous struct over UserProfile because to unset the values
266 // on the User's profile we cannot use the `json:"omitempty"` tag. This is
267 // because an empty string ("") is what's used to unset the values. Check
268 // out the API docs for more details:
269 //
270 // - https://api.slack.com/docs/presence-and-status#custom_status
271 profile, err := json.Marshal(
272 &struct {
273 StatusText string `json:"status_text"`
274 StatusEmoji string `json:"status_emoji"`
275 }{
276 StatusText: statusText,
277 StatusEmoji: statusEmoji,
278 },
279 )
280
281 if err != nil {
282 return err
283 }
284
285 values := url.Values{
286 "token": {api.config.token},
287 "profile": {string(profile)},
288 }
289
290 response := &userResponseFull{}
291
292 if err = post("users.profile.set", values, response, api.debug); err != nil {
293 return err
294 }
295
296 if !response.Ok {
297 return errors.New(response.Error)
298 }
299
300 return nil
301 }
302
303 // UnsetUserCustomStatus removes the custom status message for the currently
304 // authenticated user. This is a convenience method that wraps
305 // (*Client).SetUserCustomStatus().
306 func (api *Client) UnsetUserCustomStatus() error {
307 return api.SetUserCustomStatus("", "")
308 }
00 package slack
11
22 import (
3 "encoding/json"
4 "fmt"
35 "net/http"
46 "testing"
57 )
3436 }
3537 }`)
3638 rw.Write(response)
39 }
40
41 func httpTestErrReply(w http.ResponseWriter, clientErr bool, msg string) {
42 if clientErr {
43 w.WriteHeader(http.StatusBadRequest)
44 } else {
45 w.WriteHeader(http.StatusInternalServerError)
46 }
47
48 w.Header().Set("Content-Type", "application/json")
49
50 body, _ := json.Marshal(&SlackResponse{
51 Ok: false, Error: msg,
52 })
53
54 w.Write(body)
55 }
56
57 func newProfileHandler(up *UserProfile) (setter func(http.ResponseWriter, *http.Request)) {
58 return func(w http.ResponseWriter, r *http.Request) {
59 if up == nil {
60 httpTestErrReply(w, false, "err: UserProfile is nil")
61 return
62 }
63
64 if err := r.ParseForm(); err != nil {
65 httpTestErrReply(w, true, fmt.Sprintf("err parsing form: %s", err.Error()))
66 return
67 }
68
69 values := r.Form
70
71 if len(values["profile"]) == 0 {
72 httpTestErrReply(w, true, `POST data must include a "profile" field`)
73 return
74 }
75
76 profile := []byte(values["profile"][0])
77
78 userProfile := UserProfile{}
79
80 if err := json.Unmarshal(profile, &userProfile); err != nil {
81 httpTestErrReply(w, true, fmt.Sprintf("err parsing JSON: %s\n\njson: `%s`", err.Error(), profile))
82 return
83 }
84
85 *up = userProfile
86
87 // TODO(theckman): enhance this to return a full User object
88 fmt.Fprint(w, `{"ok":true}`)
89 }
3790 }
3891
3992 func TestGetUserIdentity(t *testing.T) {
75128 t.Fatal(ErrIncorrectResponse)
76129 }
77130 }
131
132 func TestUserCustomStatus(t *testing.T) {
133 up := &UserProfile{}
134
135 setUserProfile := newProfileHandler(up)
136
137 http.HandleFunc("/users.profile.set", setUserProfile)
138
139 once.Do(startServer)
140 SLACK_API = "http://" + serverAddr + "/"
141 api := New("testing-token")
142
143 testSetUserCustomStatus(api, up, t)
144 testUnsetUserCustomStatus(api, up, t)
145 }
146
147 func testSetUserCustomStatus(api *Client, up *UserProfile, t *testing.T) {
148 const (
149 statusText = "testStatus"
150 statusEmoji = ":construction:"
151 )
152
153 if err := api.SetUserCustomStatus(statusText, statusEmoji); err != nil {
154 t.Fatalf(`SetUserCustomStatus(%q, %q) = %#v, want <nil>`, statusText, statusEmoji, err)
155 }
156
157 if up.StatusText != statusText {
158 t.Fatalf(`UserProfile.StatusText = %q, want %q`, up.StatusText, statusText)
159 }
160
161 if up.StatusEmoji != statusEmoji {
162 t.Fatalf(`UserProfile.StatusEmoji = %q, want %q`, up.StatusEmoji, statusEmoji)
163 }
164 }
165
166 func testUnsetUserCustomStatus(api *Client, up *UserProfile, t *testing.T) {
167 if err := api.UnsetUserCustomStatus(); err != nil {
168 t.Fatalf(`UnsetUserCustomStatus() = %#v, want <nil>`, err)
169 }
170
171 if up.StatusText != "" {
172 t.Fatalf(`UserProfile.StatusText = %q, want %q`, up.StatusText, "")
173 }
174
175 if up.StatusEmoji != "" {
176 t.Fatalf(`UserProfile.StatusEmoji = %q, want %q`, up.StatusEmoji, "")
177 }
178 }