/
message.go
113 lines (99 loc) · 3.27 KB
/
message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package twilio
import (
"fmt"
"github.com/target/goalert/notification"
)
// MessageStatus indicates the state of a message.
//
// https://www.twilio.com/docs/api/messaging/message#message-status-values
type MessageStatus string
// Defined status values for messages.
const (
MessageStatusUnknown = MessageStatus("")
MessageStatusAccepted = MessageStatus("accepted")
MessageStatusQueued = MessageStatus("queued")
MessageStatusSending = MessageStatus("sending")
MessageStatusSent = MessageStatus("sent")
MessageStatusReceiving = MessageStatus("receiving")
MessageStatusReceived = MessageStatus("received")
MessageStatusDelivered = MessageStatus("delivered")
MessageStatusUndelivered = MessageStatus("undelivered")
MessageStatusFailed = MessageStatus("failed")
)
// Scan implements the sql.Scanner interface.
func (s *MessageStatus) Scan(value interface{}) error {
switch t := value.(type) {
case []byte:
*s = MessageStatus(t)
case string:
*s = MessageStatus(t)
case nil:
*s = MessageStatusUnknown
default:
return fmt.Errorf("could not process unknown type for Status(%T)", t)
}
return nil
}
// A MessageErrorCode is a defined error code for Twilio messages.
//
// https://www.twilio.com/docs/api/messaging/message#delivery-related-errors
type MessageErrorCode int
// Defined error codes for messages.
const (
MessageErrorCodeQueueOverflow = MessageErrorCode(30001)
MessageErrorCodeAccountSuspended = MessageErrorCode(30002)
MessageErrorCodeHandsetUnreachable = MessageErrorCode(30003)
MessageErrorCodeMessageBlocked = MessageErrorCode(30004)
MessageErrorCodeHandsetUnknown = MessageErrorCode(30005)
MessageErrorCodeLandlineUnreachable = MessageErrorCode(30006)
MessageErrorCodeCarrierViolation = MessageErrorCode(30007)
MessageErrorCodeUnknown = MessageErrorCode(30008)
MessageErrorCodeMissingSegment = MessageErrorCode(30009)
MessageErrorCodeExceedsMaxPrice = MessageErrorCode(30010)
)
// Message represents a Twilio message.
type Message struct {
SID string
To string
From string
Status MessageStatus
ErrorCode *MessageErrorCode
ErrorMessage *string
MessagingServiceSID string `json:"messaging_service_sid"`
}
func (msg *Message) sentMessage() *notification.SentMessage {
stat := msg.messageStatus()
return ¬ification.SentMessage{
ExternalID: msg.SID,
State: stat.State,
StateDetails: stat.Details,
SrcValue: msg.From,
}
}
func (msg *Message) messageStatus() *notification.Status {
if msg == nil {
return nil
}
var status notification.Status
if msg.ErrorMessage != nil && msg.ErrorCode != nil {
status.Details = fmt.Sprintf("%s: [%d] %s", msg.Status, *msg.ErrorCode, *msg.ErrorMessage)
} else {
status.Details = string(msg.Status)
}
switch msg.Status {
case MessageStatusFailed:
if msg.ErrorCode != nil &&
(*msg.ErrorCode == 30008 || *msg.ErrorCode == 30001) {
status.State = notification.StateFailedTemp
}
status.State = notification.StateFailedPerm
case MessageStatusDelivered:
status.State = notification.StateDelivered
case MessageStatusSent, MessageStatusUndelivered:
status.State = notification.StateSent
default:
status.State = notification.StateSending
}
status.SrcValue = msg.From
return &status
}