package main import ( "encoding/json" "io/ioutil" "log" "os" "path/filepath" "time" ) //a state is a alphanumerical string lessthan 128 bytes. //when messages comes in we need to differentiate what state is this in. //default state is where command can happen //where the state is stored, // in sessions/openID.json //if there is no such file, we are in default state. //First state is to record user's name, email, and phone number. // for individual state // state/statename/openID.json var sessionDir = "sessions" var stateDir = "state" //openIDSession openID user's session type openIDSession struct { State string `json:"State"` //name of the current state alphanumerical string CreateAt int32 `json:"CreateAt"` //when is this session created UpdateAt int32 `json:"UpdateAt"` //when is this session updated Expire int32 `json:"Expire"` //unix timestamp of when this state expires } //read sessions/openID.json to check whether its a state for ongoing dialog func getCurrentSesssion(openID string) (result openIDSession, err error) { path := getSessionPath(openID) log.Printf("read session 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) } //we don't check Expire, we give the caller full control on //how to deal wiht expired session return } func writeSession(openid string, ss openIDSession) (err error) { path := getSessionPath(openid) r, err := json.Marshal(ss) if err == nil { err = ioutil.WriteFile(path, r, 0600) if err != nil { log.Printf("Error writing session %s: \r\n %s \r\n", openid, r) log.Println(err) } else { log.Println("write session to " + path) } } else { log.Printf("Error encoding session %s ", openid) log.Println(err) } return } //create if not available func setSessionState(openID, state string, expireAfter int32) (updatedSession openIDSession, err error) { s, err := getCurrentSesssion(openID) now := int32(time.Now().Unix()) if s.CreateAt == 0 { s.CreateAt = now } s.UpdateAt = now s.State = state s.Expire = now + expireAfter err = writeSession(openID, s) return s, err } func isExpired(timestamp int32) bool { now := int32(time.Now().Unix()) return now > timestamp } func getSessionPath(openID string) (path string) { path = sessionDir + string(os.PathSeparator) + openID + ".json" ensurePathExist(path) return path } func getStatePath(openID, stateName string) (path string) { path = stateDir + string(os.PathSeparator) + stateName + 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) if isFileExist(path) { err := os.Remove(path) if err != nil { log.Println(err) } else { log.Println("delete session :" + path) } } }