diff --git a/chatSession.go b/chatSession.go index c27d9eb..c78e337 100644 --- a/chatSession.go +++ b/chatSession.go @@ -5,7 +5,6 @@ import ( "io/ioutil" "log" "os" - "path/filepath" "time" ) @@ -36,7 +35,18 @@ type openIDSessionData struct { state chatState } -func writeSession(ss openIDSessionData) (err error) { +func createEmptySession(openID string, expire int32) (result openIDSessionData) { + result.OpenID = openID + result.Procedure = "" + now := int32(time.Now().Unix()) + result.CreateAt = now + result.UpdateAt = now + result.Expire = now + expire + result.KvPair = map[string]string{} + return +} + +func (ss *openIDSessionData) writeSession() (err error) { openID := ss.OpenID path := getSessionPath(openID) r, err := json.Marshal(ss) @@ -47,6 +57,12 @@ func writeSession(ss openIDSessionData) (err error) { log.Println(err) } else { log.Println("write session to " + path) + //save state + err = ss.state.Save(openID, ss.Procedure) + if err != nil { + log.Printf("Error: cannot write session data %s", openID) + log.Println(err) + } } } else { log.Printf("Error encoding session %s ", openID) @@ -66,22 +82,8 @@ func getSessionPath(openID string) (path string) { return path } -func getProcedurePath(openID, ProcedureName string) (path string) { - path = procedureDir + string(os.PathSeparator) + ProcedureName + string(os.PathSeparator) + openID + ".json" - ensurePathExist(path) - return -} - -func ensurePathExist(path string) { - d := filepath.Dir(path) - if !isFileExist(d) { - log.Println("Creating path [" + d + "]") - os.MkdirAll(d, 0700) - } -} - -func deleteSession(openID string) { - path := getSessionPath(openID) +func (ss *openIDSessionData) Delete() { + path := getSessionPath(ss.OpenID) if isFileExist(path) { err := os.Remove(path) if err != nil { @@ -90,30 +92,17 @@ func deleteSession(openID string) { } } -type initProcFunc func(openid string) (newstate chatState) -type sendProcMsgFunc func(openid string) (newstate chatState) -type recvProcMsgFunc func(openid string) (newstate chatState) -type cleanProcFunc func(openid string) (newstate chatState) - -//Procedure a description about all procedure -type Procedure struct { - init initProcFunc //init function - send sendProcMsgFunc //function for sending customized message - recv recvProcMsgFunc //function for receiving message, possibly transfer to new state - clean cleanProcFunc //function for cleanning up -} - -func (c *openIDSessionData) Save() { +func (ss *openIDSessionData) Save() { //invalid procedure - if isExpired(c.Expire) || c.Procedure == "" { - deleteSession(c.OpenID) + if isExpired(ss.Expire) || ss.Procedure == "" { + ss.Delete() } else { - writeSession(*c) + ss.writeSession() } } //read sessions/openID.json to check whether its a Procedure for ongoing dialog -func getCurrentSesssion(openID string) (result openIDSessionData, err error) { +func (ss *openIDSessionData) Load(openID string) (result openIDSessionData, err error) { result = createEmptySession(openID, 3600) path := getSessionPath(openID) if isFileExist(path) { @@ -126,47 +115,46 @@ func getCurrentSesssion(openID string) (result openIDSessionData, err error) { if err != nil { log.Printf("Session Content [path=%s] not correct: ", path) result = createEmptySession(openID, 3600) + } else { //load procedure state if any + procedure := result.Procedure + result.state, err = getCurrentState(openID, procedure) } } } + *ss = result return } -func createEmptySession(openID string, expire int32) (result openIDSessionData) { - result.OpenID = openID - result.Procedure = "" - now := int32(time.Now().Unix()) - result.CreateAt = now - result.UpdateAt = now - result.Expire = now + expire - result.KvPair = map[string]string{} - return -} - -func (c *openIDSessionData) setProcedure(procedure string) { - c.Procedure = procedure - c.UpdateAt = int32(time.Now().Unix()) +func (ss *openIDSessionData) setProcedure(procedure string) { + ss.Procedure = procedure + ss.UpdateAt = int32(time.Now().Unix()) } -func (c *openIDSessionData) setKvPair(key, val string) { - c.KvPair[key] = val - c.UpdateAt = int32(time.Now().Unix()) +func (ss *openIDSessionData) setKvPair(key, val string) { + ss.KvPair[key] = val + ss.UpdateAt = int32(time.Now().Unix()) } //main entry point for processing each incoming message //this stage has session date available -func (c *openIDSessionData) incomingMsg(v InWechatMsg) { +func (ss *openIDSessionData) incomingMsg(v InWechatMsg) { openID := v.header.FromUserName + //kfSendTxtAs(openID, "信息收到"+v.header.MsgType, "孙鹏") //are we in an existing procedure inProc, state := isInProc(openID) //if inside a procedure, resume last saved state if inProc { - c.state = serveProc(state, v) //transit to new state + ss.state = serveProc(state, v) //transit to new state } else { state, processed := serveCommand(openID, v) //menu or txt command e.g. search if !processed { // transfer to Customer Service (kf) - kfSendTxt(openID, "未识别的命令,已转接校友会理事会,稍后答复您") + ss.state.response, _ = BuildTextMsg(openID, "已转接校友会理事会,稍后答复您") + } else { + ss.state = state } - c.state = state + } + + if ss.state.response != "" { + v.instantResponse <- ss.state.response } if !isEndingState(state) { diff --git a/chatSession_test.go b/chatSession_test.go index dcc26a6..ab12d74 100644 --- a/chatSession_test.go +++ b/chatSession_test.go @@ -10,8 +10,12 @@ func TestSession(t *testing.T) { id := "testopenid" procedure := "test procedure" + s := openIDSessionData{} + s.OpenID = id + s.Procedure = procedure + //delete any existing - deleteSession(id) + s.Delete() path := getSessionPath(id) AssertEqual(t, isFileExist(path), false, "Session file should not exist") @@ -26,7 +30,8 @@ func TestSession(t *testing.T) { log.Print("......waiting done") //read back , check state - s, _ := getCurrentSesssion(id) + s.Load(id) + AssertEqual(t, s.OpenID, id, "") AssertEqual(t, s.Procedure, procedure, "") now := int32(time.Now().Unix()) @@ -43,12 +48,13 @@ func TestSession(t *testing.T) { AssertEqual(t, s.CreateAt+1 == s.UpdateAt, true, "second Update should be bigger create") s.Save() - n, _ := getCurrentSesssion(id) + n := openIDSessionData{} + n.Load(id) AssertEqual(t, n.KvPair["key"], "value", "key = value ") AssertEqual(t, n.KvPair["key1"], "value1", "key1 = value1") //delete session, for clean up - deleteSession(id) + n.Delete() path = getSessionPath(id) AssertEqual(t, isFileExist(path), false, "Session file should not exist") }