|
- package main
-
- import (
- "encoding/json"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
- "time"
- )
-
- //a Procedure is a alphanumerical string lessthan 128 bytes.
-
- //when messages comes in we need to differentiate what Procedure is this in.
- //default Procedure is where command can happen
-
- //where the Procedure is stored,
- // in sessions/openID.json
-
- //if there is no such file, we are in default Procedure.
-
- //First Procedure is to record user's name, email, and phone number.
- // for individual Procedure
- // Procedure/Procedurename/openID.json
-
- var sessionDir = "sessions"
-
- //where to find the procedure state information
- var ProcedureDir = "procedure"
-
- //openIDSessionData openID user's session
- type openIDSessionData struct {
- OpenID string `json:"OpenID"` //who's session this is belongs to
- Procedure string `json:"Procedure"` //name of the current current process, alphanumerical
- 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 Procedure expires
- States map[string]chatState `json:"States"` //each procedure will have a state
- }
-
- func writeSession(openid string, ss openIDSessionData) (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 setSessionProcedure(openID, procedure string, expireAfter int32) (updatedSession openIDSessionData, err error) {
- s, err := getCurrentSesssion(openID)
- now := int32(time.Now().Unix())
- if s.CreateAt == 0 {
- s.CreateAt = now
- }
- s.UpdateAt = now
- s.Procedure = procedure
- 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 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)
- if isFileExist(path) {
- err := os.Remove(path)
- if err != nil {
- log.Println(err)
- } else {
- log.Println("delete session :" + path)
- }
- }
- }
-
- //OneMessage a description of what to send /receive
- type OneMessage struct {
- Type string `json:"Type"` //MessageType
- Text string `json:"Text"` //for text messages
- Pic MediaID `json:"Pic"`
- Voice MediaID `json:"Voice"`
- ShortVideo MediaID `json:"ShortVideo"`
- Video MediaID `json:"Video"`
- }
-
- type initProcFunc func(openid string) (newstate chatState)
- type sendProcMsgFunc func(openid string) (newstate chatState)
- type recvProcMsgFunc func(openid string, msg OneMessage) (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() {
- //TODO: save real session date to disk
- }
-
- //read sessions/openID.json to check whether its a Procedure for ongoing dialog
- func getCurrentSesssion(openID string) (result openIDSessionData, err error) {
- result = createEmptySession(openID, 3600)
- path := getSessionPath(openID)
- if isFileExist(path) {
- log.Printf("read session from %s\r\n", path)
- body, err := ioutil.ReadFile(path)
- if err != nil { //read file error
- log.Println("Error session reading " + path)
- } else {
- err = json.Unmarshal(body, &result)
- if err != nil {
- log.Printf("Session Content [path=%s] not correct: ", path)
- result = createEmptySession(openID, 3600)
- }
- }
- }
- 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.States = map[string]chatState{}
- return
- }
|