Skip to content

Commit 84d2040

Browse files
authored
Support Get method on Connector Client for Teams specific context (#74)
Hi, First of all, awesome library! We were missing an ability to send authenticated requests for team details. That's why I implemented such functionality in the Connector Client. This PR brings two improvements: - Support of the `Get` method for Connector Client (to get channels, team details, etc.) - Read more: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/get-teams-context?tabs=json - Remove unused `activity` for the Client `Delete` method Let me know what you think! Cheers! Resolves #71
1 parent ae31623 commit 84d2040

File tree

2 files changed

+65
-24
lines changed

2 files changed

+65
-24
lines changed

connector/client/client.go

+64-23
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ import (
4040
// Client provides interface to send requests to the connector service.
4141
type Client interface {
4242
Post(ctx context.Context, url url.URL, activity schema.Activity) error
43-
Delete(ctx context.Context, url url.URL, activity schema.Activity) error
43+
Delete(ctx context.Context, url url.URL) error
44+
Get(ctx context.Context, url url.URL) (json.RawMessage, error)
4445
Put(ctx context.Context, url url.URL, activity schema.Activity) error
4546
}
4647

@@ -81,19 +82,48 @@ func (client *ConnectorClient) Post(ctx context.Context, target url.URL, activit
8182
if err != nil {
8283
return err
8384
}
84-
return client.sendRequest(req, activity)
85+
return client.sendRequestWithRespErrCheck(req)
86+
}
87+
88+
// Get a resource from given URL using authenticated request.
89+
//
90+
// This method is helpful for obtaining Teams context for your bot.
91+
// Read more: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/get-teams-context?tabs=json
92+
func (client *ConnectorClient) Get(ctx context.Context, target url.URL) (json.RawMessage, error) {
93+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, target.String(), nil)
94+
if err != nil {
95+
return nil, err
96+
}
97+
98+
res, err := client.sendRequest(req)
99+
if err != nil {
100+
return nil, newHTTPError(err)
101+
}
102+
defer res.Body.Close()
103+
104+
if wrappedErr := client.checkRespError(res); wrappedErr != nil {
105+
return nil, wrappedErr
106+
}
107+
108+
var rawOutput json.RawMessage
109+
err = json.NewDecoder(res.Body).Decode(&rawOutput)
110+
if err != nil {
111+
return nil, err
112+
}
113+
114+
return rawOutput, nil
85115
}
86116

87117
// Delete an activity.
88118
//
89119
// Creates a HTTP DELETE request with the provided activity ID and a Bearer token in the header.
90120
// Returns any error as received from the call to connector service.
91-
func (client *ConnectorClient) Delete(ctx context.Context, target url.URL, activity schema.Activity) error {
121+
func (client *ConnectorClient) Delete(ctx context.Context, target url.URL) error {
92122
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, target.String(), nil)
93123
if err != nil {
94124
return err
95125
}
96-
return client.sendRequest(req, activity)
126+
return client.sendRequestWithRespErrCheck(req)
97127
}
98128

99129
// Put an activity.
@@ -109,40 +139,41 @@ func (client *ConnectorClient) Put(ctx context.Context, target url.URL, activity
109139
if err != nil {
110140
return err
111141
}
112-
return client.sendRequest(req, activity)
142+
return client.sendRequestWithRespErrCheck(req)
113143
}
114144

115-
func (client *ConnectorClient) sendRequest(req *http.Request, activity schema.Activity) error {
145+
func (client *ConnectorClient) sendRequestWithRespErrCheck(req *http.Request) error {
146+
res, err := client.sendRequest(req)
147+
if err != nil {
148+
return newHTTPError(err)
149+
}
150+
151+
defer res.Body.Close()
152+
return client.checkRespError(res)
153+
}
154+
155+
func (client *ConnectorClient) sendRequest(req *http.Request) (*http.Response, error) {
116156
token, err := client.getToken(req.Context())
117157
if err != nil {
118-
return err
158+
return nil, err
119159
}
120160

121161
req.Header.Set("Content-Type", "application/json")
122162
req.Header.Set("Authorization", "Bearer "+token)
123163

124-
return client.checkRespError(client.ReplyClient.Do(req))
164+
return client.ReplyClient.Do(req)
125165
}
126166

127-
func (client *ConnectorClient) checkRespError(resp *http.Response, err error) error {
167+
func (client *ConnectorClient) checkRespError(resp *http.Response) error {
128168
allowedResp := []int{http.StatusOK, http.StatusCreated, http.StatusAccepted}
129-
if err != nil {
130-
return customerror.HTTPError{
131-
HtErr: err,
132-
}
133-
}
134-
defer resp.Body.Close()
135169
// Check if resp allowed
136170
for _, code := range allowedResp {
137171
if code == resp.StatusCode {
138172
return nil
139173
}
140174
}
141175

142-
return customerror.HTTPError{
143-
HtErr: errors.New("invalid response"),
144-
StatusCode: resp.StatusCode,
145-
}
176+
return newHTTPErrorWithStatusCode(errors.New("invalid response"), resp.StatusCode)
146177
}
147178

148179
func (client *ConnectorClient) getToken(ctx context.Context) (string, error) {
@@ -174,10 +205,7 @@ func (client *ConnectorClient) getToken(ctx context.Context) (string, error) {
174205

175206
resp, err := client.AuthClient.Do(r)
176207
if err != nil {
177-
return "", customerror.HTTPError{
178-
StatusCode: resp.StatusCode,
179-
HtErr: err,
180-
}
208+
return "", newHTTPErrorWithStatusCode(err, resp.StatusCode)
181209
}
182210

183211
defer resp.Body.Close()
@@ -196,3 +224,16 @@ func (client *ConnectorClient) getToken(ctx context.Context) (string, error) {
196224

197225
return client.AuthCache.Keys.(string), nil
198226
}
227+
228+
func newHTTPError(err error) error {
229+
return customerror.HTTPError{
230+
HtErr: err,
231+
}
232+
}
233+
234+
func newHTTPErrorWithStatusCode(err error, statusCode int) error {
235+
return customerror.HTTPError{
236+
HtErr: err,
237+
StatusCode: statusCode,
238+
}
239+
}

core/activity/response.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (response *DefaultResponse) DeleteActivity(ctx context.Context, activity sc
6161

6262
// Send activity to client
6363
u.Path = path.Join(u.Path, respPath)
64-
err = response.Client.Delete(ctx, *u, activity)
64+
err = response.Client.Delete(ctx, *u)
6565
return errors.Wrap(err, "Failed to delete response.")
6666
}
6767

0 commit comments

Comments
 (0)