Skip to content

Commit 63b7600

Browse files
committed
Initial commit
Rudiments of how we are going to interact with the API, write responses, etc. A lot still to be flushed out, the API should be treated as experimental, etc.
0 parents  commit 63b7600

7 files changed

+241
-0
lines changed

LICENSE

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
Copyright 2019 Meter, Inc.
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.
20+
21+
This project is based in part off of src/crypto/tls/generate_cert.go, a file
22+
available in the Go source code. The license for that file is available here:
23+
24+
Copyright (c) 2009 The Go Authors. All rights reserved.
25+
26+
Redistribution and use in source and binary forms, with or without
27+
modification, are permitted provided that the following conditions are
28+
met:
29+
30+
* Redistributions of source code must retain the above copyright
31+
notice, this list of conditions and the following disclaimer.
32+
* Redistributions in binary form must reproduce the above
33+
copyright notice, this list of conditions and the following disclaimer
34+
in the documentation and/or other materials provided with the
35+
distribution.
36+
* Neither the name of Google Inc. nor the names of its
37+
contributors may be used to endorse or promote products derived from
38+
this software without specific prior written permission.
39+
40+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

chat.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package slack
2+
3+
import (
4+
"context"
5+
"net/url"
6+
)
7+
8+
type ChatService struct {
9+
client *Client
10+
}
11+
12+
type response struct {
13+
OK bool `json:"ok"`
14+
Channel string `json:"channel"`
15+
TS SlackTime `json:"ts"`
16+
Error string `json:"error"`
17+
Warning string `json:"warning"`
18+
}
19+
20+
// https://api.slack.com/methods/chat.postMessage
21+
func (c *ChatService) PostMessage(ctx context.Context, data url.Values) (*response, error) {
22+
resp := new(response)
23+
err := c.client.CreateResource(ctx, "/api/chat.postMessage", data, resp)
24+
return resp, err
25+
}

chat_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package slack
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/url"
7+
"os"
8+
"testing"
9+
)
10+
11+
func TestPostMessage(t *testing.T) {
12+
t.Skip("goes over the network")
13+
client := New(os.Getenv("SLACK_TOKEN"))
14+
users, err := client.Users.List(context.Background(), nil)
15+
if err != nil {
16+
t.Fatal(err)
17+
}
18+
var kevinuser string
19+
for _, u := range users.Members {
20+
if u.Name == "kevin" {
21+
kevinuser = u.ID
22+
}
23+
}
24+
resp, err := client.Chat.PostMessage(context.Background(), url.Values{
25+
"channel": []string{kevinuser},
26+
"text": []string{"Hello from meterbot"},
27+
})
28+
if err != nil {
29+
t.Fatal(err)
30+
}
31+
fmt.Printf("resp: %#v\n", resp)
32+
}

conversations.go

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package slack
2+
3+
type ConversationService struct {
4+
client *Client
5+
}

http.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package slack
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/url"
7+
"strings"
8+
9+
"github.com/kevinburke/rest"
10+
)
11+
12+
const Version = "0.1"
13+
14+
var userAgent string
15+
16+
func init() {
17+
userAgent = fmt.Sprintf("slack-go/%s", Version)
18+
}
19+
20+
func New(token string) *Client {
21+
restClient := rest.NewBearerClient(token, baseURL)
22+
restClient.UploadType = rest.FormURLEncoded
23+
c := &Client{
24+
Client: restClient,
25+
baseURL: baseURL,
26+
}
27+
c.Chat = &ChatService{client: c}
28+
c.Users = &UserService{client: c}
29+
return c
30+
}
31+
32+
const baseURL = "https://api.slack.com"
33+
34+
type Client struct {
35+
*rest.Client
36+
baseURL string
37+
38+
Chat *ChatService
39+
Users *UserService
40+
}
41+
42+
// CreateResource makes a POST request to the given resource.
43+
func (c *Client) CreateResource(ctx context.Context, pathPart string, data url.Values, v interface{}) error {
44+
return c.MakeRequest(ctx, "POST", pathPart, data, v)
45+
}
46+
47+
func (c *Client) ListResource(ctx context.Context, pathPart string, data url.Values, v interface{}) error {
48+
return c.MakeRequest(ctx, "GET", pathPart, data, v)
49+
}
50+
51+
// Make a request to the Slack API.
52+
func (c *Client) MakeRequest(ctx context.Context, method string, pathPart string, data url.Values, v interface{}) error {
53+
rb := new(strings.Reader)
54+
if data != nil && (method == "POST" || method == "PUT") {
55+
rb = strings.NewReader(data.Encode())
56+
}
57+
if method == "GET" && data != nil {
58+
pathPart = pathPart + "?" + data.Encode()
59+
}
60+
req, err := c.NewRequest(method, pathPart, rb)
61+
if err != nil {
62+
return err
63+
}
64+
req = req.WithContext(ctx)
65+
if ua := req.Header.Get("User-Agent"); ua == "" {
66+
req.Header.Set("User-Agent", userAgent)
67+
} else {
68+
req.Header.Set("User-Agent", userAgent+" "+ua)
69+
}
70+
return c.Do(req, &v)
71+
}

types.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package slack
2+
3+
import (
4+
"encoding/json"
5+
"math"
6+
"strconv"
7+
"time"
8+
)
9+
10+
type SlackTime time.Time
11+
12+
func (s *SlackTime) UnmarshalJSON(data []byte) error {
13+
var f float64
14+
var ss string
15+
err := json.Unmarshal(data, &ss)
16+
if err == nil {
17+
f, err = strconv.ParseFloat(ss, 64)
18+
if err != nil {
19+
return err
20+
}
21+
} else if err := json.Unmarshal(data, &f); err != nil {
22+
return err
23+
}
24+
intpart, divpart := math.Modf(f)
25+
*s = SlackTime(time.Unix(int64(intpart), int64(divpart*100*1000*1000)))
26+
return nil
27+
}
28+
29+
func (s SlackTime) MarshalJSON() ([]byte, error) {
30+
ts := float64(time.Time(s).Unix()) + float64(time.Time(s).UnixNano())/100*1000*1000
31+
return json.Marshal(ts)
32+
}

users.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package slack
2+
3+
import (
4+
"context"
5+
"net/url"
6+
)
7+
8+
type UserService struct {
9+
client *Client
10+
}
11+
12+
type User struct {
13+
ID string `json:"id"`
14+
Name string `json:"name"`
15+
Updated SlackTime `json:"updated"`
16+
}
17+
18+
type UsersListResponse struct {
19+
Members []*User `json:"members"`
20+
}
21+
22+
func (u *UserService) List(ctx context.Context, data url.Values) (*UsersListResponse, error) {
23+
resp := new(UsersListResponse)
24+
err := u.client.ListResource(ctx, "/api/users.list", data, resp)
25+
return resp, err
26+
}

0 commit comments

Comments
 (0)