|
- package main
-
- import (
- "encoding/json"
- "errors"
- "io/ioutil"
- "log"
- "os"
- )
-
- //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
- Expire int32 `json:"Expire"` //unix timestamp when this state expire
-
- //persistant sate
- Save map[string]string `json:"Save"` //the state save some data for later usage
-
- //runtime memory only
- response string //被动回复消息的内容
- }
-
- //for individual state
- func getCurrentState(openID string, procedure string) (result chatState, err error) {
- path := getProcedurePath(openID, procedure)
- //log.Printf("read state from %s\r\n", path)
- 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)
- }
- err = sanityCheckState(openID, procedure, result)
- return
- }
-
- func sanityCheckState(openID, procedure string, result chatState) (err error) {
- //check whether state is for the correct openID and procedure
- if result.OpenID != openID {
- err = errors.New("Error: State for " + openID + " is actually for " + result.OpenID)
- return
- }
-
- if result.Procedure != procedure {
- err = errors.New("Error: Proecdure for " + procedure + " is actually for " + result.Procedure)
- return
- }
- return
- }
-
- func setCurrentState(openID, procedure string, state chatState) (err error) {
- state.OpenID = openID
- state.Procedure = procedure
-
- j, err := json.Marshal(state)
- if err != nil {
- return
- }
- path := getProcedurePath(openID, procedure)
- err = ioutil.WriteFile(path, j, 0600)
- if err != nil {
- log.Println("write state error" + path)
- log.Println(err)
- return
- }
- return
- }
-
- func deleteChatState(openID, procedure string) (err error) {
- path := getProcedurePath(openID, procedure)
- err = os.Remove(path)
- return
- }
-
- //ValidationResult After input validation, what is the result
- type ValidationResult struct {
- accept bool
- Hint string
- Error string
- Warning string
- }
-
- //Validator function type for validating all wechat inputs
- type Validator func(s chatState) ValidationResult
-
- func saveChatState(openID, procedure string, state chatState) (err error) {
- if isExpired(state.Expire) {
- //skip saving sate
- return
- }
- err = setCurrentState(openID, procedure, state)
- return
- }
-
- func isEndingState(state chatState) bool {
- if isExpired(state.Expire) || state.Name == "" {
- return true
- }
-
- if state.Name == "delete" {
- return true
- }
- return false
- }
|