Skip to content

Commit 96b0a5e

Browse files
committed
feat: improve interfaces, fail unmarshellling earlier and return errors
1 parent 6fc5d31 commit 96b0a5e

12 files changed

+104
-76
lines changed

changes.go

+17-20
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ package gometawebhooks
33
import (
44
"context"
55
"encoding/json"
6+
"errors"
67
"fmt"
78

89
"golang.org/x/sync/errgroup"
910
)
1011

1112
var (
12-
ErrParsingChanges = fmt.Errorf("parsing changes payload: %w", ErrWebhooks)
13-
ErrChangesTypeNotImplemented = fmt.Errorf("changes type not implemented: %w", ErrWebhooks)
14-
ErrInstagramMentionHandlerNotDefined = fmt.Errorf("instagram mentions handler not defined: %w", ErrWebhooks)
15-
ErrInstagramStoryInsightsHandlerNotDefined = fmt.Errorf("instagram story insights handler not defined: %w", ErrWebhooks)
13+
ErrChangesFieldNotImplemented = errors.New("changes field not implemented")
14+
ErrInstagramMentionHandlerNotDefined = errors.New("instagram mentions handler not defined")
15+
ErrInstagramStoryInsightsHandlerNotDefined = errors.New("instagram story insights handler not defined")
1616
)
1717

1818
type Change struct {
@@ -36,18 +36,18 @@ type StoryInsightsFieldValue struct {
3636
}
3737

3838
type ChangesHandler interface {
39-
Changes(ctx context.Context, object Object, entry Entry, change Change) error
39+
Changes(context.Context, Object, Entry, Change) error
4040
}
4141

4242
func (c *Change) UnmarshalJSON(data []byte) error {
4343
var raw map[string]json.RawMessage
4444
if err := json.Unmarshal(data, &raw); err != nil {
45-
return wrapErr(err, ErrParsingChanges)
45+
return err
4646
}
4747

4848
if fieldRaw, ok := raw["field"]; ok {
4949
if err := json.Unmarshal(fieldRaw, &c.Field); err != nil {
50-
return wrapErr(err, ErrParsingChanges)
50+
return err
5151
}
5252
}
5353

@@ -56,15 +56,17 @@ func (c *Change) UnmarshalJSON(data []byte) error {
5656
case "mentions":
5757
var value MentionsFieldValue
5858
if err := json.Unmarshal(valueRaw, &value); err != nil {
59-
return wrapErr(err, ErrParsingChanges)
59+
return err
6060
}
6161
c.Value = value
6262
case "story_insights":
6363
var value StoryInsightsFieldValue
6464
if err := json.Unmarshal(valueRaw, &value); err != nil {
65-
return wrapErr(err, ErrParsingChanges)
65+
return err
6666
}
6767
c.Value = value
68+
default:
69+
return fmt.Errorf("'%s': %w", c.Field, ErrChangesFieldNotImplemented)
6870
}
6971
}
7072

@@ -88,32 +90,27 @@ func (hooks Webhooks) changes(ctx context.Context, object Object, entry Entry) e
8890
}
8991

9092
func (h Webhooks) Changes(ctx context.Context, object Object, entry Entry, change Change) error {
91-
if object != Instagram {
92-
return fmt.Errorf("'%s': %w", object, ErrObjectNotSupported)
93-
}
94-
9593
select {
9694
case <-ctx.Done():
9795
return context.Cause(ctx)
9896
default:
99-
return h.change(ctx, entry, change)
97+
return h.change(ctx, object, entry, change)
10098
}
10199
}
102-
func (h Webhooks) change(ctx context.Context, entry Entry, change Change) error {
103-
sent := unixTime(entry.Time)
104-
100+
func (h Webhooks) change(ctx context.Context, object Object, entry Entry, change Change) error {
105101
switch value := change.Value.(type) {
106102
case MentionsFieldValue:
107103
if h.instagramMentionHandler == nil {
108104
return ErrInstagramMentionHandlerNotDefined
109105
}
110-
return h.instagramMentionHandler.InstagramMention(ctx, entry.Id, sent, value)
106+
return h.instagramMentionHandler.InstagramMention(ctx, object, entry, value)
111107
case StoryInsightsFieldValue:
112108
if h.instagramStoryInsightsHandler == nil {
113109
return ErrInstagramStoryInsightsHandlerNotDefined
114110
}
115-
return h.instagramStoryInsightsHandler.InstagramStoryInsights(ctx, entry.Id, sent, value)
111+
return h.instagramStoryInsightsHandler.InstagramStoryInsights(ctx, object, entry, value)
116112
default:
117-
return fmt.Errorf("'%s': %w", change.Field, ErrChangesTypeNotImplemented)
113+
// @note should not be hit cause Unmarshall ensures field is supported
114+
return fmt.Errorf("'%s': %w", change.Field, ErrChangesFieldNotImplemented)
118115
}
119116
}

entry.go

+27-1
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,45 @@ package gometawebhooks
22

33
import (
44
"context"
5+
"encoding/json"
6+
"errors"
7+
"fmt"
58

69
"golang.org/x/sync/errgroup"
710
)
811

12+
var (
13+
ErrParsingEntry = errors.New("parsing entry")
14+
)
15+
916
type Entry struct {
1017
Id string `json:"id"`
1118
Time int64 `json:"time"`
1219
Messaging []Messaging `json:"messaging,omitempty"`
1320
Changes []Change `json:"changes,omitempty"`
1421
}
1522

23+
func (t *Entry) UnmarshalJSON(b []byte) error {
24+
type Alias Entry
25+
var entry Alias
26+
if err := json.Unmarshal(b, &entry); err != nil {
27+
return err
28+
}
29+
30+
if entry.Id == "" {
31+
return fmt.Errorf("missing 'id' field: %w", ErrParsingEntry)
32+
}
33+
34+
if entry.Time == 0 {
35+
return fmt.Errorf("missing 'time' field: %w", ErrParsingEntry)
36+
}
37+
38+
*t = Entry(entry)
39+
return nil
40+
}
41+
1642
type EntryHandler interface {
17-
Entry(ctx context.Context, object Object, entry Entry) error
43+
Entry(context.Context, Object, Entry) error
1844
}
1945

2046
func (h Webhooks) Entry(ctx context.Context, object Object, entry Entry) error {

handler/changes_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestHandleChange(t *testing.T) {
3030
}]
3131
}]
3232
}`),
33-
expectErr: gometawebhooks.ErrChangesTypeNotImplemented,
33+
expectErr: gometawebhooks.ErrChangesFieldNotImplemented,
3434
options: func(scenario *hookScenario) []handler.Option {
3535
return []handler.Option{
3636
handler.Options.CompileSchema(),

handler/handler.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package handler
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"io"
78
"net/http"
@@ -10,8 +11,8 @@ import (
1011
)
1112

1213
var (
13-
ErrReadBodyPayload = fmt.Errorf("error reading body payload: %w", gometawebhooks.ErrWebhooks)
14-
ErrInvalidHTTPMethod = fmt.Errorf("invalid HTTP Method: %w", gometawebhooks.ErrWebhooks)
14+
ErrReadBodyPayload = errors.New("error reading body payload")
15+
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
1516
)
1617

1718
type DefaultHandler interface {

handler/handler_test.go

+8-12
Original file line numberDiff line numberDiff line change
@@ -35,32 +35,32 @@ func (h testHandler) Changes(ctx context.Context, object handler.Object, entry h
3535
}
3636

3737
// Messaging implements handler.MessagingHandler.
38-
func (h testHandler) Messaging(ctx context.Context, object handler.Object, entryId string, entryTime time.Time, messaging handler.Messaging) error {
38+
func (h testHandler) Messaging(ctx context.Context, object handler.Object, entry handler.Entry, messaging handler.Messaging) error {
3939
return h.run(ctx)
4040
}
4141

4242
// InstagramMention implements handler.InstagramMentionHandler.
43-
func (h testHandler) InstagramMention(ctx context.Context, entryId string, entryTime time.Time, mention handler.MentionsFieldValue) error {
43+
func (h testHandler) InstagramMention(ctx context.Context, object handler.Object, entry handler.Entry, mention handler.MentionsFieldValue) error {
4444
return h.run(ctx)
4545
}
4646

4747
// InstagramStoryInsights implements handler.InstagramStoryInsightsHandler.
48-
func (h testHandler) InstagramStoryInsights(ctx context.Context, entryId string, entryTime time.Time, storyInsights handler.StoryInsightsFieldValue) error {
48+
func (h testHandler) InstagramStoryInsights(ctx context.Context, object handler.Object, entry handler.Entry, storyInsights handler.StoryInsightsFieldValue) error {
4949
return h.run(ctx)
5050
}
5151

5252
// InstagramMessage implements handler.InstagramMessageHandler.
53-
func (h testHandler) InstagramMessage(ctx context.Context, sender string, recipient string, sent time.Time, message handler.Message) error {
53+
func (h testHandler) InstagramMessage(ctx context.Context, object handler.Object, entry handler.Entry, sender string, recipient string, sent time.Time, message handler.Message) error {
5454
return h.run(ctx)
5555
}
5656

5757
// InstagramPostback implements handler.InstagramPostbackHandler.
58-
func (h testHandler) InstagramPostback(ctx context.Context, sender string, recipient string, sent time.Time, postback handler.Postback) error {
58+
func (h testHandler) InstagramPostback(ctx context.Context, object handler.Object, entry handler.Entry, sender string, recipient string, sent time.Time, postback handler.Postback) error {
5959
return h.run(ctx)
6060
}
6161

6262
// InstagramReferral implements handler.InstagramReferralHandler.
63-
func (h testHandler) InstagramReferral(ctx context.Context, sender string, recipient string, sent time.Time, referral handler.Referral) error {
63+
func (h testHandler) InstagramReferral(ctx context.Context, object handler.Object, entry handler.Entry, sender string, recipient string, sent time.Time, referral handler.Referral) error {
6464
return h.run(ctx)
6565
}
6666

@@ -145,15 +145,11 @@ func (scenario *hookScenario) assert(t *testing.T, result interface{}, payload [
145145
if scenario.expectErr != nil {
146146
if err == nil {
147147
t.Errorf("Expected an error, but got none.")
148-
}
149-
150-
if !errors.Is(err, scenario.expectErr) {
148+
} else if !errors.Is(err, scenario.expectErr) {
151149
t.Errorf("Expected error %v, but got %v.", scenario.expectErr, err)
152150
}
153151
return
154-
}
155-
156-
if err != nil {
152+
} else if err != nil {
157153
t.Errorf("Expected no error, but got: %v", err)
158154
}
159155

instagram.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@ import (
66
)
77

88
type InstagramMessageHandler interface {
9-
InstagramMessage(ctx context.Context, sender, recipient string, sent time.Time, message Message) error
9+
InstagramMessage(ctx context.Context, object Object, entry Entry, sender, recipient string, sent time.Time, message Message) error
1010
}
1111

1212
type InstagramPostbackHandler interface {
13-
InstagramPostback(ctx context.Context, sender, recipient string, sent time.Time, postback Postback) error
13+
InstagramPostback(ctx context.Context, object Object, entry Entry, sender, recipient string, sent time.Time, postback Postback) error
1414
}
1515

1616
type InstagramReferralHandler interface {
17-
InstagramReferral(ctx context.Context, sender, recipient string, sent time.Time, referral Referral) error
17+
InstagramReferral(ctx context.Context, object Object, entry Entry, sender, recipient string, sent time.Time, referral Referral) error
1818
}
1919

2020
type InstagramMentionHandler interface {
21-
InstagramMention(ctx context.Context, entryId string, entryTime time.Time, mention MentionsFieldValue) error
21+
InstagramMention(ctx context.Context, object Object, entry Entry, mention MentionsFieldValue) error
2222
}
2323

2424
type InstagramStoryInsightsHandler interface {
25-
InstagramStoryInsights(ctx context.Context, entryId string, entryTime time.Time, storyInsights StoryInsightsFieldValue) error
25+
InstagramStoryInsights(ctx context.Context, object Object, entry Entry, storyInsights StoryInsightsFieldValue) error
2626
}
2727

2828
type InstagramChangesHandler interface {

messaging.go

+13-18
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@ package gometawebhooks
22

33
import (
44
"context"
5-
"fmt"
6-
"time"
5+
"errors"
76

87
"golang.org/x/sync/errgroup"
98
)
109

1110
var (
12-
ErrMessagingTypeNotImplemented = fmt.Errorf("messaging type not implemented: %w", ErrWebhooks)
13-
ErrInstagramMessageHandlerNotDefined = fmt.Errorf("instagram message handler not defined: %w", ErrWebhooks)
14-
ErrInstagramPostbackHandlerNotDefined = fmt.Errorf("instagram postback handler not defined: %w", ErrWebhooks)
15-
ErrInstagramReferralHandlerNotDefined = fmt.Errorf("instagram referral handler not defined: %w", ErrWebhooks)
11+
ErrMessagingTypeNotImplemented = errors.New("messaging type not implemented")
12+
ErrInstagramMessageHandlerNotDefined = errors.New("instagram message handler not defined")
13+
ErrInstagramPostbackHandlerNotDefined = errors.New("instagram postback handler not defined")
14+
ErrInstagramReferralHandlerNotDefined = errors.New("instagram referral handler not defined")
1615
)
1716

1817
type Message struct {
@@ -77,7 +76,7 @@ type Messaging struct {
7776
}
7877

7978
type MessagingHandler interface {
80-
Messaging(ctx context.Context, object Object, entryId string, entryTime time.Time, messaging Messaging) error
79+
Messaging(context.Context, Object, Entry, Messaging) error
8180
}
8281

8382
func (hooks Webhooks) messaging(ctx context.Context, object Object, entry Entry) error {
@@ -90,26 +89,22 @@ func (hooks Webhooks) messaging(ctx context.Context, object Object, entry Entry)
9089
g.SetLimit(len(entry.Messaging))
9190
for _, messaging := range entry.Messaging {
9291
g.Go(func() error {
93-
return hooks.messagingHandler.Messaging(ctx, object, entry.Id, unixTime(entry.Time), messaging)
92+
return hooks.messagingHandler.Messaging(ctx, object, entry, messaging)
9493
})
9594
}
9695
return g.Wait()
9796
}
9897

99-
func (h Webhooks) Messaging(ctx context.Context, object Object, entryId string, entryTime time.Time, messaging Messaging) error {
100-
if object != Instagram {
101-
return fmt.Errorf("'%s': %w", object, ErrObjectNotSupported)
102-
}
103-
98+
func (h Webhooks) Messaging(ctx context.Context, object Object, entry Entry, messaging Messaging) error {
10499
select {
105100
case <-ctx.Done():
106101
return context.Cause(ctx)
107102
default:
108-
return h.message(ctx, messaging)
103+
return h.message(ctx, object, entry, messaging)
109104
}
110105
}
111106

112-
func (h Webhooks) message(ctx context.Context, messaging Messaging) error {
107+
func (h Webhooks) message(ctx context.Context, object Object, entry Entry, messaging Messaging) error {
113108
if h.messagingIgnoreEchos && messaging.Message.IsEcho {
114109
return nil
115110
}
@@ -120,23 +115,23 @@ func (h Webhooks) message(ctx context.Context, messaging Messaging) error {
120115
return ErrInstagramMessageHandlerNotDefined
121116
}
122117

123-
return h.instagramMessageHandler.InstagramMessage(ctx, messaging.Sender.Id, messaging.Recipient.Id, sent, messaging.Message)
118+
return h.instagramMessageHandler.InstagramMessage(ctx, object, entry, messaging.Sender.Id, messaging.Recipient.Id, sent, messaging.Message)
124119
}
125120

126121
if messaging.Postback.Id != "" {
127122
if h.instagramPostbackHandler == nil {
128123
return ErrInstagramPostbackHandlerNotDefined
129124
}
130125

131-
return h.instagramPostbackHandler.InstagramPostback(ctx, messaging.Sender.Id, messaging.Recipient.Id, sent, messaging.Postback)
126+
return h.instagramPostbackHandler.InstagramPostback(ctx, object, entry, messaging.Sender.Id, messaging.Recipient.Id, sent, messaging.Postback)
132127
}
133128

134129
if messaging.Referral.Type != "" {
135130
if h.instagramReferralHandler == nil {
136131
return ErrInstagramReferralHandlerNotDefined
137132
}
138133

139-
return h.instagramReferralHandler.InstagramReferral(ctx, messaging.Sender.Id, messaging.Recipient.Id, sent, messaging.Referral)
134+
return h.instagramReferralHandler.InstagramReferral(ctx, object, entry, messaging.Sender.Id, messaging.Recipient.Id, sent, messaging.Referral)
140135
}
141136

142137
return ErrMessagingTypeNotImplemented

0 commit comments

Comments
 (0)