Codebase list golang-github-nlopes-slack / 6aeef4e
:shirt: Fix Lint and Vet Errors Joe Fitzgerald 8 years ago
13 changed file(s) with 116 addition(s) and 116 deletion(s). Raw diff Collapse all Expand all
1818 fmt.Printf("%s\n", err)
1919 return
2020 }
21 fmt.Printf("Name: %s, Url: %s\n", file.Name, file.URL)
21 fmt.Printf("Name: %s, URL: %s\n", file.Name, file.URL)
2222
2323 err = api.DeleteFile(file.ID)
2424 if err != nil {
3838
3939 // Post as the authenticated user.
4040 postAsUserName = authTest.User
41 postAsUserID = authTest.UserId
41 postAsUserID = authTest.UserID
4242
4343 // Posting to DM with self causes a conversation with slackbot.
4444 postToUserName = authTest.User
45 postToUserID = authTest.UserId
45 postToUserID = authTest.UserID
4646
4747 // Find the channel.
4848 _, _, chanID, err := api.OpenIMChannel(postToUserID)
1818 }
1919 go wsAPI.HandleIncomingEvents(chReceiver)
2020 go wsAPI.Keepalive(20 * time.Second)
21 go func(wsAPI *slack.SlackWS, chSender chan slack.OutgoingMessage) {
21 go func(wsAPI *slack.WS, chSender chan slack.OutgoingMessage) {
2222 for {
2323 select {
2424 case msg := <-chSender:
4242 case slack.LatencyReport:
4343 a := msg.Data.(slack.LatencyReport)
4444 fmt.Printf("Current latency: %v\n", a.Value)
45 case *slack.SlackWSError:
46 error := msg.Data.(*slack.SlackWSError)
45 case *slack.WSError:
46 error := msg.Data.(*slack.WSError)
4747 fmt.Printf("Error: %d - %s\n", error.Code, error.Msg)
4848 default:
4949 fmt.Printf("Unexpected: %v\n", msg.Data)
44 "time"
55 )
66
7 // XXX: Need to implement
7 // UserPrefs needs to be implemented
88 type UserPrefs struct {
99 // "highlight_words":"",
1010 // "user_colors":"",
144144 // Info contains various details about Users, Channels, Bots and the authenticated user
145145 // It is returned by StartRTM
146146 type Info struct {
147 Url string `json:"url,omitempty"`
147 URL string `json:"url,omitempty"`
148148 User *UserDetails `json:"self,omitempty"`
149149 Team *Team `json:"team,omitempty"`
150150 Users []User `json:"users,omitempty"`
156156
157157 type infoResponseFull struct {
158158 Info
159 SlackWSResponse
159 WSResponse
160160 }
161161
162162 // GetBotByID returns a bot given a bot id
189189 return nil
190190 }
191191
192 // GetGroupById returns a group given a group id
193 func (info Info) GetGroupById(groupId string) *Group {
192 // GetGroupByID returns a group given a group id
193 func (info Info) GetGroupByID(groupID string) *Group {
194194 for _, group := range info.Groups {
195 if group.Id == groupId {
195 if group.ID == groupID {
196196 return &group
197197 }
198198 }
5151 // CommentId, or the combination of ChannelId and Timestamp must be
5252 // specified.
5353 type ItemRef struct {
54 ChannelId string `json:"channel"`
54 Channel string `json:"channel"`
5555 Timestamp string `json:"timestamp"`
56 FileId string `json:"file"`
57 CommentId string `json:"file_comment"`
56 File string `json:"file"`
57 Comment string `json:"file_comment"`
5858 }
5959
6060 // NewRefToMessage initializes a reference to to a message.
61 func NewRefToMessage(channelID, timestamp string) ItemRef {
62 return ItemRef{ChannelId: channelID, Timestamp: timestamp}
61 func NewRefToMessage(channel, timestamp string) ItemRef {
62 return ItemRef{Channel: channel, Timestamp: timestamp}
6363 }
6464
6565 // NewRefToFile initializes a reference to a file.
66 func NewRefToFile(fileID string) ItemRef {
67 return ItemRef{FileId: fileID}
66 func NewRefToFile(file string) ItemRef {
67 return ItemRef{File: file}
6868 }
6969
7070 // NewRefToComment initializes a reference to a file comment.
71 func NewRefToComment(commentID string) ItemRef {
72 return ItemRef{CommentId: commentID}
71 func NewRefToComment(comment string) ItemRef {
72 return ItemRef{Comment: comment}
7373 }
7777
7878 func TestNewRefToMessage(t *testing.T) {
7979 ref := NewRefToMessage("chan", "ts")
80 if got, want := ref.ChannelId, "chan"; got != want {
81 t.Errorf("ChannelId got %s, want %s", got, want)
80 if got, want := ref.Channel, "chan"; got != want {
81 t.Errorf("Channel got %s, want %s", got, want)
8282 }
8383 if got, want := ref.Timestamp, "ts"; got != want {
8484 t.Errorf("Timestamp got %s, want %s", got, want)
8585 }
86 if got, want := ref.FileId, ""; got != want {
87 t.Errorf("FileId got %s, want %s", got, want)
86 if got, want := ref.File, ""; got != want {
87 t.Errorf("File got %s, want %s", got, want)
8888 }
89 if got, want := ref.CommentId, ""; got != want {
90 t.Errorf("CommentId got %s, want %s", got, want)
89 if got, want := ref.Comment, ""; got != want {
90 t.Errorf("Comment got %s, want %s", got, want)
9191 }
9292 }
9393
9494 func TestNewRefToFile(t *testing.T) {
9595 ref := NewRefToFile("file")
96 if got, want := ref.ChannelId, ""; got != want {
97 t.Errorf("ChannelId got %s, want %s", got, want)
96 if got, want := ref.Channel, ""; got != want {
97 t.Errorf("Channel got %s, want %s", got, want)
9898 }
9999 if got, want := ref.Timestamp, ""; got != want {
100100 t.Errorf("Timestamp got %s, want %s", got, want)
101101 }
102 if got, want := ref.FileId, "file"; got != want {
103 t.Errorf("FileId got %s, want %s", got, want)
102 if got, want := ref.File, "file"; got != want {
103 t.Errorf("File got %s, want %s", got, want)
104104 }
105 if got, want := ref.CommentId, ""; got != want {
106 t.Errorf("CommentId got %s, want %s", got, want)
105 if got, want := ref.Comment, ""; got != want {
106 t.Errorf("Comment got %s, want %s", got, want)
107107 }
108108 }
109109
110110 func TestNewRefToComment(t *testing.T) {
111111 ref := NewRefToComment("file_comment")
112 if got, want := ref.ChannelId, ""; got != want {
113 t.Errorf("ChannelId got %s, want %s", got, want)
112 if got, want := ref.Channel, ""; got != want {
113 t.Errorf("Channel got %s, want %s", got, want)
114114 }
115115 if got, want := ref.Timestamp, ""; got != want {
116116 t.Errorf("Timestamp got %s, want %s", got, want)
117117 }
118 if got, want := ref.FileId, ""; got != want {
119 t.Errorf("FileId got %s, want %s", got, want)
118 if got, want := ref.File, ""; got != want {
119 t.Errorf("File got %s, want %s", got, want)
120120 }
121 if got, want := ref.CommentId, "file_comment"; got != want {
122 t.Errorf("CommentId got %s, want %s", got, want)
121 if got, want := ref.Comment, "file_comment"; got != want {
122 t.Errorf("Comment got %s, want %s", got, want)
123123 }
124124 }
101101 }
102102
103103 // NewOutgoingMessage prepares an OutgoingMessage that the user can use to send a message
104 func (api *SlackWS) NewOutgoingMessage(text string, channel string) *OutgoingMessage {
104 func (api *WS) NewOutgoingMessage(text string, channel string) *OutgoingMessage {
105105 api.mutex.Lock()
106106 defer api.mutex.Unlock()
107 api.messageId++
107 api.messageID++
108108 return &OutgoingMessage{
109 ID: api.messageId,
109 ID: api.messageID,
110110 Type: "message",
111111 Channel: channel,
112112 Text: text,
5858 }
5959
6060 const (
61 DEFAULT_REACTIONS_USERID = ""
62 DEFAULT_REACTIONS_COUNT = 100
63 DEFAULT_REACTIONS_PAGE = 1
64 DEFAULT_REACTIONS_FULL = false
61 DEFAULT_REACTIONS_USER = ""
62 DEFAULT_REACTIONS_COUNT = 100
63 DEFAULT_REACTIONS_PAGE = 1
64 DEFAULT_REACTIONS_FULL = false
6565 )
6666
6767 // ListReactionsParameters is the inputs to find all reactions by a user.
6868 type ListReactionsParameters struct {
69 UserId string
70 Count int
71 Page int
72 Full bool
69 User string
70 Count int
71 Page int
72 Full bool
7373 }
7474
7575 // NewListReactionsParameters initializes the inputs to find all reactions
7676 // performed by a user.
7777 func NewListReactionsParameters() ListReactionsParameters {
7878 return ListReactionsParameters{
79 UserId: DEFAULT_REACTIONS_USERID,
80 Count: DEFAULT_REACTIONS_COUNT,
81 Page: DEFAULT_REACTIONS_PAGE,
82 Full: DEFAULT_REACTIONS_FULL,
79 User: DEFAULT_REACTIONS_USER,
80 Count: DEFAULT_REACTIONS_COUNT,
81 Page: DEFAULT_REACTIONS_PAGE,
82 Full: DEFAULT_REACTIONS_FULL,
8383 }
8484 }
8585
135135 if name != "" {
136136 values.Set("name", name)
137137 }
138 if item.ChannelId != "" {
139 values.Set("channel", string(item.ChannelId))
138 if item.Channel != "" {
139 values.Set("channel", string(item.Channel))
140140 }
141141 if item.Timestamp != "" {
142142 values.Set("timestamp", string(item.Timestamp))
143143 }
144 if item.FileId != "" {
145 values.Set("file", string(item.FileId))
146 }
147 if item.CommentId != "" {
148 values.Set("file_comment", string(item.CommentId))
144 if item.File != "" {
145 values.Set("file", string(item.File))
146 }
147 if item.Comment != "" {
148 values.Set("file_comment", string(item.Comment))
149149 }
150150 response := &SlackResponse{}
151151 if err := parseResponse("reactions.add", values, response, api.debug); err != nil {
165165 if name != "" {
166166 values.Set("name", name)
167167 }
168 if item.ChannelId != "" {
169 values.Set("channel", string(item.ChannelId))
168 if item.Channel != "" {
169 values.Set("channel", string(item.Channel))
170170 }
171171 if item.Timestamp != "" {
172172 values.Set("timestamp", string(item.Timestamp))
173173 }
174 if item.FileId != "" {
175 values.Set("file", string(item.FileId))
176 }
177 if item.CommentId != "" {
178 values.Set("file_comment", string(item.CommentId))
174 if item.File != "" {
175 values.Set("file", string(item.File))
176 }
177 if item.Comment != "" {
178 values.Set("file_comment", string(item.Comment))
179179 }
180180 response := &SlackResponse{}
181181 if err := parseResponse("reactions.remove", values, response, api.debug); err != nil {
192192 values := url.Values{
193193 "token": {api.config.token},
194194 }
195 if item.ChannelId != "" {
196 values.Set("channel", string(item.ChannelId))
195 if item.Channel != "" {
196 values.Set("channel", string(item.Channel))
197197 }
198198 if item.Timestamp != "" {
199199 values.Set("timestamp", string(item.Timestamp))
200200 }
201 if item.FileId != "" {
202 values.Set("file", string(item.FileId))
203 }
204 if item.CommentId != "" {
205 values.Set("file_comment", string(item.CommentId))
201 if item.File != "" {
202 values.Set("file", string(item.File))
203 }
204 if item.Comment != "" {
205 values.Set("file_comment", string(item.Comment))
206206 }
207207 if params.Full != DEFAULT_REACTIONS_FULL {
208208 values.Set("full", strconv.FormatBool(params.Full))
222222 values := url.Values{
223223 "token": {api.config.token},
224224 }
225 if params.UserId != DEFAULT_REACTIONS_USERID {
226 values.Add("user", params.UserId)
225 if params.User != DEFAULT_REACTIONS_USER {
226 values.Add("user", params.User)
227227 }
228228 if params.Count != DEFAULT_REACTIONS_COUNT {
229229 values.Add("count", strconv.Itoa(params.Count))
336336 },
337337 }
338338 wantParams := map[string]string{
339 "user": "UserID",
339 "user": "User",
340340 "count": "200",
341341 "page": "2",
342342 "full": "true",
343343 }
344344 params := NewListReactionsParameters()
345 params.UserId = "UserID"
345 params.User = "User"
346346 params.Count = 200
347347 params.Page = 2
348348 params.Full = true
1616 }
1717
1818 type AuthTestResponse struct {
19 Url string `json:"url"`
19 URL string `json:"url"`
2020 Team string `json:"team"`
2121 User string `json:"user"`
2222 TeamID string `json:"team_id"`
117117 for i, test := range tests {
118118 sh = newStarsHandler()
119119 sh.response = test.json
120 response_items, response_paging, err := api.GetStarred(test.params)
120 responseItems, responsePaging, err := api.GetStarred(test.params)
121121 if err != nil {
122122 t.Fatalf("%d Unexpected error: %s", i, err)
123123 }
124124 if !reflect.DeepEqual(sh.gotParams, test.wantParams) {
125125 t.Errorf("%d got %v; want %v", i, sh.gotParams, test.wantParams)
126126 }
127 if !reflect.DeepEqual(response_items, test.starredItems) {
128 t.Errorf("%d got %v; want %v", i, response_items, test.starredItems)
127 if !reflect.DeepEqual(responseItems, test.starredItems) {
128 t.Errorf("%d got %v; want %v", i, responseItems, test.starredItems)
129129 }
130 if !reflect.DeepEqual(response_paging, test.paging) {
131 t.Errorf("%d got %v; want %v", i, response_paging, test.paging)
130 if !reflect.DeepEqual(responsePaging, test.paging) {
131 t.Errorf("%d got %v; want %v", i, responsePaging, test.paging)
132132 }
133133 }
134134 }
1515
1616 type MessageEvent Message
1717
18 type SlackWS struct {
18 type WS struct {
1919 conn *websocket.Conn
20 messageId int
20 messageID int
2121 mutex sync.Mutex
2222 pings map[int]time.Time
2323 Slack
2828 ReplyTo int `json:"reply_to"`
2929 Timestamp string `json:"ts"`
3030 Text string `json:"text"`
31 SlackWSResponse
32 }
33
34 type SlackWSResponse struct {
35 Ok bool `json:"ok"`
36 Error *SlackWSError `json:"error"`
37 }
38
39 type SlackWSError struct {
31 WSResponse
32 }
33
34 type WSResponse struct {
35 Ok bool `json:"ok"`
36 Error *WSError `json:"error"`
37 }
38
39 type WSError struct {
4040 Code int
4141 Msg string
4242 }
6363 return fmt.Sprintf("\"%s\"", tm.Format("Mon Jan _2"))
6464 }
6565
66 func (s SlackWSError) Error() string {
66 func (s WSError) Error() string {
6767 return s.Msg
6868 }
6969
7070 var portMapping = map[string]string{"ws": "80", "wss": "443"}
7171
72 func fixUrlPort(orig string) (string, error) {
72 func fixURLPort(orig string) (string, error) {
7373 urlObj, err := url.ParseRequestURI(orig)
7474 if err != nil {
7575 return "", err
8181 return orig, nil
8282 }
8383
84 func (api *Slack) StartRTM(protocol, origin string) (*SlackWS, error) {
84 func (api *Slack) StartRTM(protocol, origin string) (*WS, error) {
8585 response := &infoResponseFull{}
8686 err := parseResponse("rtm.start", url.Values{"token": {api.config.token}}, response, api.debug)
8787 if err != nil {
9494 // websocket.Dial does not accept url without the port (yet)
9595 // Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3
9696 // but slack returns the address with no port, so we have to fix it
97 api.info.Url, err = fixUrlPort(api.info.Url)
97 api.info.URL, err = fixURLPort(api.info.URL)
9898 if err != nil {
9999 return nil, err
100100 }
101101 api.config.protocol, api.config.origin = protocol, origin
102 wsApi := &SlackWS{Slack: *api}
103 wsApi.conn, err = websocket.Dial(api.info.Url, api.config.protocol, api.config.origin)
102 wsAPI := &WS{Slack: *api}
103 wsAPI.conn, err = websocket.Dial(api.info.URL, api.config.protocol, api.config.origin)
104104 if err != nil {
105105 return nil, err
106106 }
107 wsApi.pings = make(map[int]time.Time)
108 return wsApi, nil
109 }
110
111 func (api *SlackWS) Ping() error {
107 wsAPI.pings = make(map[int]time.Time)
108 return wsAPI, nil
109 }
110
111 func (api *WS) Ping() error {
112112 api.mutex.Lock()
113113 defer api.mutex.Unlock()
114 api.messageId++
115 msg := &Ping{ID: api.messageId, Type: "ping"}
114 api.messageID++
115 msg := &Ping{ID: api.messageID, Type: "ping"}
116116 if err := websocket.JSON.Send(api.conn, msg); err != nil {
117117 return err
118118 }
119119 // TODO: What happens if we already have this id?
120 api.pings[api.messageId] = time.Now()
120 api.pings[api.messageID] = time.Now()
121121 return nil
122122 }
123123
124 func (api *SlackWS) Keepalive(interval time.Duration) {
124 func (api *WS) Keepalive(interval time.Duration) {
125125 ticker := time.NewTicker(interval)
126126 defer ticker.Stop()
127127
135135 }
136136 }
137137
138 func (api *SlackWS) SendMessage(msg *OutgoingMessage) error {
138 func (api *WS) SendMessage(msg *OutgoingMessage) error {
139139 if msg == nil {
140140 return fmt.Errorf("Can't send a nil message")
141141 }
146146 return nil
147147 }
148148
149 func (api *SlackWS) HandleIncomingEvents(ch chan SlackEvent) {
149 func (api *WS) HandleIncomingEvents(ch chan SlackEvent) {
150150 for {
151151 event := json.RawMessage{}
152152 if err := websocket.JSON.Receive(api.conn, &event); err == io.EOF {
156156 //}
157157 // should we reconnect here?
158158 if !api.conn.IsClientConn() {
159 api.conn, err = websocket.Dial(api.info.Url, api.config.protocol, api.config.origin)
159 api.conn, err = websocket.Dial(api.info.URL, api.config.protocol, api.config.origin)
160160 if err != nil {
161161 log.Panic(err)
162162 }
179179 }
180180 }
181181
182 func (api *SlackWS) handleEvent(ch chan SlackEvent, event json.RawMessage) {
182 func (api *WS) handleEvent(ch chan SlackEvent, event json.RawMessage) {
183183 em := Event{}
184184 err := json.Unmarshal(event, &em)
185185 if err != nil {
1818
1919 type TeamDomainChangeEvent struct {
2020 Type string `json:"type"`
21 Url string `json:"url"`
21 URL string `json:"url"`
2222 Domain string `json:"domain"`
2323 }
2424