package main import ( "encoding/json" "io/ioutil" "log" "os" "time" ) //chat state that we might be use for collecting infomation from user type chatState struct { //back pointer style information, managed by general process OpenID string `json:"OpenID"` //whom is this belongs to Procedure string `json:"Procedure"` //which procedure this belongs to //below is managed by procedure only //real state information Name string `json:"Name"` //state name CreateAt int32 `json:"CreateAt"` //unix timestamp , when its created Expire int32 `json:"Expire"` //unix timestamp when this state expire //persistant sate Data map[string]string `json:"Data"` //the state save some data for later usage //runtime memory only //response string //被动回复消息的内容 } func createEmptyState(openID, procedure string, expireInSeconds int32) chatState { r := chatState{} r.Name = "" r.OpenID = openID r.Procedure = procedure r.CreateAt = int32(time.Now().Unix()) r.Expire = r.CreateAt + expireInSeconds r.Data = map[string]string{} return r } func (m *chatState) Load(openID, procedure string) (result chatState, err error) { result, err = getCurrentState(openID, procedure) *m = result return } //for individual state func getCurrentState(openID string, procedure string) (result chatState, err error) { path := getProcedurePath(openID, procedure) body, err := ioutil.ReadFile(path) if err != nil { //read file error if isFileExist(path) { log.Println("Error session reading " + path) } return //empty and expired session } err = json.Unmarshal(body, &result) if err != nil { log.Printf("Session Content [path=%s] not correct: ", path) log.Println(err) } result.OpenID = openID result.Procedure = procedure return } func (m *chatState) Save() (err error) { if m.isEndingState() { return m.Delete() } //save to disk j, err := json.Marshal(*m) if err != nil { return } path := getProcedurePath(m.OpenID, m.Procedure) err = ioutil.WriteFile(path, j, 0600) if err != nil { log.Println("write state error" + path) log.Println(err) return } return } func (m *chatState) Delete() (err error) { path := getProcedurePath(m.OpenID, m.Procedure) if isFileExist(path) { err = os.Remove(path) } return } func (m *chatState) isEndingState() bool { if isExpired(m.Expire) || m.Name == "" { return true } return false }