Przeglądaj źródła

chat session re-invented.

master
Patrick Peng Sun 8 lat temu
rodzic
commit
5edb741019
2 zmienionych plików z 55 dodań i 61 usunięć
  1. +45
    -57
      chatSession.go
  2. +10
    -4
      chatSession_test.go

+ 45
- 57
chatSession.go Wyświetl plik

@@ -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) {

+ 10
- 4
chatSession_test.go Wyświetl plik

@@ -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")
}

Ładowanie…
Anuluj
Zapisz