|
|
|
|
|
|
|
|
"time" |
|
|
"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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//openSession is the biggest description for a user's openID |
|
|
|
|
|
// | it contains a name called procedure, whose data is stored elsewhere |
|
|
|
|
|
// | |
|
|
|
|
|
// +-- a Procedure name is a alphanumerical string lessthan 128 bytes. |
|
|
|
|
|
// | |
|
|
|
|
|
// +--- state is part of procedure, a procedure consists of sequence of states |
|
|
|
|
|
|
|
|
|
|
|
//where to find session data |
|
|
var sessionDir = "sessions" |
|
|
var sessionDir = "sessions" |
|
|
|
|
|
|
|
|
//where to find the procedure state information |
|
|
//where to find the procedure state information |
|
|
var ProcedureDir = "procedure" |
|
|
|
|
|
|
|
|
var procedureDir = "procedure" |
|
|
|
|
|
|
|
|
//openIDSessionData openID user's session |
|
|
//openIDSessionData openID user's session |
|
|
type openIDSessionData struct { |
|
|
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 |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
KvPair map[string]string `json:"KvPair"` //key value pair persistant for this session |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func writeSession(openid string, ss openIDSessionData) (err error) { |
|
|
|
|
|
path := getSessionPath(openid) |
|
|
|
|
|
|
|
|
func writeSession(ss openIDSessionData) (err error) { |
|
|
|
|
|
openID := ss.OpenID |
|
|
|
|
|
path := getSessionPath(openID) |
|
|
r, err := json.Marshal(ss) |
|
|
r, err := json.Marshal(ss) |
|
|
if err == nil { |
|
|
if err == nil { |
|
|
err = ioutil.WriteFile(path, r, 0600) |
|
|
err = ioutil.WriteFile(path, r, 0600) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.Printf("Error writing session %s: \r\n %s \r\n", openid, r) |
|
|
|
|
|
|
|
|
log.Printf("Error writing session %s: \r\n %s \r\n", openID, r) |
|
|
log.Println(err) |
|
|
log.Println(err) |
|
|
} else { |
|
|
} else { |
|
|
log.Println("write session to " + path) |
|
|
log.Println("write session to " + path) |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
log.Printf("Error encoding session %s ", openid) |
|
|
|
|
|
|
|
|
log.Printf("Error encoding session %s ", openID) |
|
|
log.Println(err) |
|
|
log.Println(err) |
|
|
} |
|
|
} |
|
|
return |
|
|
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 { |
|
|
func isExpired(timestamp int32) bool { |
|
|
now := int32(time.Now().Unix()) |
|
|
now := int32(time.Now().Unix()) |
|
|
return now > timestamp |
|
|
return now > timestamp |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func getProcedurePath(openID, ProcedureName string) (path string) { |
|
|
func getProcedurePath(openID, ProcedureName string) (path string) { |
|
|
path = ProcedureDir + string(os.PathSeparator) + ProcedureName + string(os.PathSeparator) + openID + ".json" |
|
|
|
|
|
|
|
|
path = procedureDir + string(os.PathSeparator) + ProcedureName + string(os.PathSeparator) + openID + ".json" |
|
|
ensurePathExist(path) |
|
|
ensurePathExist(path) |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
err := os.Remove(path) |
|
|
err := os.Remove(path) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.Println(err) |
|
|
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 initProcFunc func(openid string) (newstate chatState) |
|
|
type sendProcMsgFunc func(openid string) (newstate chatState) |
|
|
type sendProcMsgFunc func(openid string) (newstate chatState) |
|
|
type recvProcMsgFunc func(openid string, msg OneMessage) (newstate chatState) |
|
|
|
|
|
|
|
|
type recvProcMsgFunc func(openid string) (newstate chatState) |
|
|
type cleanProcFunc func(openid string) (newstate chatState) |
|
|
type cleanProcFunc func(openid string) (newstate chatState) |
|
|
|
|
|
|
|
|
//Procedure a description about all procedure |
|
|
//Procedure a description about all procedure |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *openIDSessionData) Save() { |
|
|
func (c *openIDSessionData) Save() { |
|
|
//TODO: save real session date to disk |
|
|
|
|
|
|
|
|
//invalid procedure |
|
|
|
|
|
if isExpired(c.Expire) || c.Procedure == "" { |
|
|
|
|
|
deleteSession(c.OpenID) |
|
|
|
|
|
} else { |
|
|
|
|
|
writeSession(*c) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//read sessions/openID.json to check whether its a Procedure for ongoing dialog |
|
|
//read sessions/openID.json to check whether its a Procedure for ongoing dialog |
|
|
|
|
|
|
|
|
result.CreateAt = now |
|
|
result.CreateAt = now |
|
|
result.UpdateAt = now |
|
|
result.UpdateAt = now |
|
|
result.Expire = now + expire |
|
|
result.Expire = now + expire |
|
|
result.States = map[string]chatState{} |
|
|
|
|
|
|
|
|
result.KvPair = map[string]string{} |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *openIDSessionData) setProcedure(procedure string) { |
|
|
|
|
|
c.Procedure = procedure |
|
|
|
|
|
c.UpdateAt = int32(time.Now().Unix()) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *openIDSessionData) setKvPair(key, val string) { |
|
|
|
|
|
c.KvPair[key] = val |
|
|
|
|
|
c.UpdateAt = int32(time.Now().Unix()) |
|
|
|
|
|
} |