forked from NdoleStudio/httpsms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmessage.go
More file actions
229 lines (184 loc) · 8.64 KB
/
message.go
File metadata and controls
229 lines (184 loc) · 8.64 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package entities
import (
"time"
"github.com/google/uuid"
)
// MessageType is the type of message if it is incoming or outgoing
type MessageType string
const (
// MessageTypeMobileTerminated means the message it sent to a mobile phone
MessageTypeMobileTerminated = "mobile-terminated"
// MessageTypeMobileOriginated means the message comes directly from a mobile phone
MessageTypeMobileOriginated = "mobile-originated"
// MessageTypeCallMissed means the message is generated when a phone call is missed by the android phone
MessageTypeCallMissed = "call/missed"
)
// MessageStatus is the status of the message
type MessageStatus string
const (
// MessageStatusPending means the message has been queued to be sent
MessageStatusPending = "pending"
// MessageStatusScheduled means the message has been scheduled to be sent
MessageStatusScheduled = "scheduled"
// MessageStatusSending means a phone has picked up the message and is currently sending it
MessageStatusSending = "sending"
// MessageStatusSent means the message has already sent by the mobile phone
MessageStatusSent = "sent"
// MessageStatusReceived means the message was received by the mobile phone (MO) or a phone call is missed by the mobile phone
MessageStatusReceived = "received"
// MessageStatusFailed means the mobile phone could not send the message
MessageStatusFailed = "failed"
// MessageStatusDelivered means the mobile phone has delivered the message
MessageStatusDelivered = "delivered"
// MessageStatusExpired means the message could not be sent by the mobile phone after 5 minutes
MessageStatusExpired = "expired"
// MessageStatusDeleted is for deleted messages and threads
MessageStatusDeleted = "deleted"
)
// MessageEventName is the type of event generated by the mobile phone for a message
type MessageEventName string
const (
// MessageEventNameSent is emitted when a message is sent by the mobile phone
MessageEventNameSent = MessageEventName("SENT")
// MessageEventNameDelivered is emitted when a message is delivered by the mobile phone
MessageEventNameDelivered = MessageEventName("DELIVERED")
// MessageEventNameFailed is emitted when a message is failed by the mobile phone
MessageEventNameFailed = MessageEventName("FAILED")
)
// SIM is the SIM card to use to send the message
type SIM string
const (
// SIM1 use the SIM card in slot 1 to send the message
SIM1 = SIM("SIM1")
// SIM2 use the SIM card in slot 2 to send the message
SIM2 = SIM("SIM2")
)
// String gets the string representation of the SIM
func (s SIM) String() string {
return string(s)
}
// Message represents a message sent between 2 phone numbers
type Message struct {
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;" example:"32343a19-da5e-4b1b-a767-3298a73703cb"`
RequestID *string `json:"request_id" example:"153554b5-ae44-44a0-8f4f-7bbac5657ad4" validate:"optional"`
Owner string `json:"owner" example:"+18005550199"`
UserID UserID `json:"user_id" gorm:"index:idx_messages__user_id" example:"WB7DRDWrJZRGbYrv2CKGkqbzvqdC"`
Contact string `json:"contact" example:"+18005550100"`
Content string `json:"content" example:"This is a sample text message"`
Encrypted bool `json:"encrypted" example:"false" gorm:"default:false"`
Type MessageType `json:"type" example:"mobile-terminated"`
Status MessageStatus `json:"status" example:"pending"`
// SIM is the SIM card to use to send the message
// * SMS1: use the SIM card in slot 1
// * SMS2: use the SIM card in slot 2
// * DEFAULT: used the default communication SIM card
SIM SIM `json:"sim" example:"DEFAULT"`
// SendDuration is the number of nanoseconds from when the request was received until when the mobile phone send the message
SendDuration *int64 `json:"send_time" example:"133414" validate:"optional"`
RequestReceivedAt time.Time `json:"request_received_at" example:"2022-06-05T14:26:01.520828+03:00"`
CreatedAt time.Time `json:"created_at" example:"2022-06-05T14:26:02.302718+03:00"`
UpdatedAt time.Time `json:"updated_at" example:"2022-06-05T14:26:10.303278+03:00"`
OrderTimestamp time.Time `json:"order_timestamp" example:"2022-06-05T14:26:09.527976+03:00"`
LastAttemptedAt *time.Time `json:"last_attempted_at" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
NotificationScheduledAt *time.Time `json:"scheduled_at" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
SentAt *time.Time `json:"sent_at" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
ScheduledSendTime *time.Time `json:"scheduled_send_time" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
DeliveredAt *time.Time `json:"delivered_at" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
ExpiredAt *time.Time `json:"expired_at" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
FailedAt *time.Time `json:"failed_at" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
CanBePolled bool `json:"-" example:"false" swaggerignore:"true"`
SendAttemptCount uint `json:"send_attempt_count" example:"0"`
MaxSendAttempts uint `json:"max_send_attempts" example:"1"`
ReceivedAt *time.Time `json:"received_at" example:"2022-06-05T14:26:09.527976+03:00" validate:"optional"`
FailureReason *string `json:"failure_reason" example:"UNKNOWN" validate:"optional"`
}
// IsSending determines if a message is being sent
func (message *Message) IsSending() bool {
return message.Status == MessageStatusSending
}
// IsDelivered checks if a message is delivered
func (message *Message) IsDelivered() bool {
return message.Status == MessageStatusDelivered
}
// IsPending checks if a message is pending
func (message *Message) IsPending() bool {
return message.Status == MessageStatusPending
}
// IsScheduled checks if a message is scheduled
func (message *Message) IsScheduled() bool {
return message.Status == MessageStatusScheduled
}
// IsExpired checks if a message is expired
func (message *Message) IsExpired() bool {
return message.Status == MessageStatusExpired
}
// CanBeRescheduled checks if a message can be rescheduled
func (message *Message) CanBeRescheduled() bool {
return message.SendAttemptCount < message.MaxSendAttempts
}
// IsSent determines if a message has been sent
func (message *Message) IsSent() bool {
return message.Status == MessageStatusSent
}
// Sent registers a message as sent
func (message *Message) Sent(timestamp time.Time) *Message {
sendDuration := timestamp.UnixNano() - message.RequestReceivedAt.UnixNano()
message.SentAt = ×tamp
message.Status = MessageStatusSent
message.updateOrderTimestamp(timestamp)
message.SendDuration = &sendDuration
return message
}
// Failed registers a message as failed
func (message *Message) Failed(timestamp time.Time, errorMessage string) *Message {
message.FailedAt = ×tamp
message.Status = MessageStatusFailed
message.FailureReason = &errorMessage
message.updateOrderTimestamp(timestamp)
return message
}
// Delivered registers a message as delivered
func (message *Message) Delivered(timestamp time.Time) *Message {
message.DeliveredAt = ×tamp
message.Status = MessageStatusDelivered
if message.SendDuration == nil {
sendDuration := timestamp.UnixNano() - message.RequestReceivedAt.UnixNano()
message.SendDuration = &sendDuration
}
message.updateOrderTimestamp(timestamp)
return message
}
// AddSendAttemptCount increments the send attempt count of a message
func (message *Message) AddSendAttemptCount() *Message {
message.SendAttemptCount++
return message
}
// Expired registers a message as expired
func (message *Message) Expired(timestamp time.Time) *Message {
message.ExpiredAt = ×tamp
message.Status = MessageStatusExpired
message.CanBePolled = true
message.updateOrderTimestamp(timestamp)
return message
}
// NotificationScheduled registers a message as scheduled
func (message *Message) NotificationScheduled(timestamp time.Time) *Message {
message.NotificationScheduledAt = ×tamp
if message.IsExpired() || message.IsPending() {
message.Status = MessageStatusScheduled
}
message.updateOrderTimestamp(timestamp)
return message
}
// AddSendAttempt configures a Message for sending
func (message *Message) AddSendAttempt(timestamp time.Time) *Message {
message.Status = MessageStatusSending
message.LastAttemptedAt = ×tamp
message.updateOrderTimestamp(timestamp)
return message
}
func (message *Message) updateOrderTimestamp(timestamp time.Time) {
if timestamp.UnixNano() > message.OrderTimestamp.UnixNano() {
message.OrderTimestamp = timestamp
}
}