-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathphada.go
163 lines (140 loc) · 3.63 KB
/
phada.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
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
package phada
import (
"encoding/json"
"errors"
"net/http"
"net/url"
"strings"
"time"
)
// / UssdRequestSession
// /
// / go representation of the structure of an AfricasTalking USSD call
type UssdRequestSession struct {
PhoneNumber string `json:"phoneNumber"`
SessionID string `json:"sessionID"`
Text string `json:"text"`
Channel string `json:"-"` // Deprecated - no longer being used
NetworkCode string `json:"networkCode"`
ServiceCode string `json:"serviceCode"`
// The State of the request
State int `json:"-"`
startedAt time.Time `json:"-"`
// Number of hops for this ussd session
hops int `json:"-"`
// The offset in the text from the last hop
textOffset int `json:"-"`
}
// / SessionStore
// /
// / Interface for storing session data
type SessionStore interface {
Get(sessionID string) (*UssdRequestSession, error)
PutHop(*UssdRequestSession) error
Delete(sessionID string)
}
func (u *UssdRequestSession) RecordHop(text string) {
if len(text) <= 1 {
u.Text = text
u.textOffset = 0
u.hops++
return
}
// add one to account for the asterisk
u.textOffset = len(u.Text) + 1
u.Text = text
u.hops++
}
// RecordHopAndReadIn
//
// Records input string for the ussd session and immediately returns
// the new input string
func (u *UssdRequestSession) RecordHopAndReadIn(text string) string {
u.RecordHop(text)
return u.ReadIn()
}
// ReadIn
//
// Reads the last input string recorded for this session
func (u *UssdRequestSession) ReadIn() string {
if u.textOffset > len(u.Text) {
u.textOffset = 0
return ""
}
currentHopInput := u.Text[u.textOffset:]
return currentHopInput
}
// SetState
//
// Set the state for this Ussd session
func (u *UssdRequestSession) SetState(state int) {
u.State = state
}
// GetHopN
//
// Get the data provided at the nth hop
func (u *UssdRequestSession) GetHopN(n int) string {
if n == 0 {
return ""
}
a := strings.Split(u.Text, "*")
if n > len(a) {
// TODO(zikani): errors.New(fmt.Sprintf("Cannot read hop %d, session only had %s hops", n, hops))
return ""
}
hopText := a[n-1]
return hopText
}
// Count Hops
//
// Count the number of hops (interactions) for the Ussd session
// the number of hops is based on the asterisk count so it's
// approximate
func (u *UssdRequestSession) CountHops() int {
a := strings.Split(u.Text, "*")
return len(a) + 1
}
// ToJSON
//
// Convert the UssdRequestSession to JSON string or empty string on error
func (u *UssdRequestSession) ToJSON() string {
b, err := json.Marshal(u)
if err != nil {
return ""
}
return string(b)
}
// ParseUssdRequestSession
//
// Parse the Request data to a UssdRequestSession if the parameters
// are present in the body
func ParseUssdRequest(req *http.Request) (*UssdRequestSession, error) {
if err := req.ParseForm(); err != nil {
return nil, err
}
return parseUrlValuesToUssdRequestSession(req.Form)
}
func parseUrlValuesToUssdRequestSession(form url.Values) (*UssdRequestSession, error) {
UssdRequestSession := &UssdRequestSession{
PhoneNumber: form.Get("phoneNumber"),
SessionID: form.Get("sessionId"),
Text: form.Get("text"),
Channel: form.Get("channel"), // Deprecated
NetworkCode: form.Get("networkCode"),
ServiceCode: form.Get("serviceCode"),
textOffset: 0,
startedAt: time.Now(),
}
err := validateUssdRequestSession(UssdRequestSession)
return UssdRequestSession, err
}
func validateUssdRequestSession(req *UssdRequestSession) error {
if req.PhoneNumber == "" {
return errors.New("UssdRequestSession PhoneNumber cannot be empty")
}
if req.SessionID == "" {
return errors.New("UssdRequestSession SessionID cannot be empty")
}
// req.Text can be empty
return nil
}