Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

167 Zeilen
4.7KB

  1. package main
  2. import (
  3. "encoding/json"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "time"
  9. )
  10. //a Procedure is a alphanumerical string lessthan 128 bytes.
  11. //when messages comes in we need to differentiate what Procedure is this in.
  12. //default Procedure is where command can happen
  13. //where the Procedure is stored,
  14. // in sessions/openID.json
  15. //if there is no such file, we are in default Procedure.
  16. //First Procedure is to record user's name, email, and phone number.
  17. // for individual Procedure
  18. // Procedure/Procedurename/openID.json
  19. var sessionDir = "sessions"
  20. //where to find the procedure state information
  21. var ProcedureDir = "procedure"
  22. //openIDSessionData openID user's session
  23. type openIDSessionData struct {
  24. OpenID string `json:"OpenID"` //who's session this is belongs to
  25. Procedure string `json:"Procedure"` //name of the current current process, alphanumerical
  26. CreateAt int32 `json:"CreateAt"` //when is this session created
  27. UpdateAt int32 `json:"UpdateAt"` //when is this session updated
  28. Expire int32 `json:"Expire"` //unix timestamp of when this Procedure expires
  29. States map[string]chatState `json:"States"` //each procedure will have a state
  30. }
  31. func writeSession(openid string, ss openIDSessionData) (err error) {
  32. path := getSessionPath(openid)
  33. r, err := json.Marshal(ss)
  34. if err == nil {
  35. err = ioutil.WriteFile(path, r, 0600)
  36. if err != nil {
  37. log.Printf("Error writing session %s: \r\n %s \r\n", openid, r)
  38. log.Println(err)
  39. } else {
  40. log.Println("write session to " + path)
  41. }
  42. } else {
  43. log.Printf("Error encoding session %s ", openid)
  44. log.Println(err)
  45. }
  46. return
  47. }
  48. //create if not available
  49. func setSessionProcedure(openID, procedure string, expireAfter int32) (updatedSession openIDSessionData, err error) {
  50. s, err := getCurrentSesssion(openID)
  51. now := int32(time.Now().Unix())
  52. if s.CreateAt == 0 {
  53. s.CreateAt = now
  54. }
  55. s.UpdateAt = now
  56. s.Procedure = procedure
  57. s.Expire = now + expireAfter
  58. err = writeSession(openID, s)
  59. return s, err
  60. }
  61. func isExpired(timestamp int32) bool {
  62. now := int32(time.Now().Unix())
  63. return now > timestamp
  64. }
  65. func getSessionPath(openID string) (path string) {
  66. path = sessionDir + string(os.PathSeparator) + openID + ".json"
  67. ensurePathExist(path)
  68. return path
  69. }
  70. func getProcedurePath(openID, ProcedureName string) (path string) {
  71. path = ProcedureDir + string(os.PathSeparator) + ProcedureName + string(os.PathSeparator) + openID + ".json"
  72. ensurePathExist(path)
  73. return
  74. }
  75. func ensurePathExist(path string) {
  76. d := filepath.Dir(path)
  77. if !isFileExist(d) {
  78. log.Println("Creating path [" + d + "]")
  79. os.MkdirAll(d, 0700)
  80. }
  81. }
  82. func deleteSession(openID string) {
  83. path := getSessionPath(openID)
  84. if isFileExist(path) {
  85. err := os.Remove(path)
  86. if err != nil {
  87. log.Println(err)
  88. } else {
  89. log.Println("delete session :" + path)
  90. }
  91. }
  92. }
  93. //OneMessage a description of what to send /receive
  94. type OneMessage struct {
  95. Type string `json:"Type"` //MessageType
  96. Text string `json:"Text"` //for text messages
  97. Pic MediaID `json:"Pic"`
  98. Voice MediaID `json:"Voice"`
  99. ShortVideo MediaID `json:"ShortVideo"`
  100. Video MediaID `json:"Video"`
  101. }
  102. type initProcFunc func(openid string) (newstate chatState)
  103. type sendProcMsgFunc func(openid string) (newstate chatState)
  104. type recvProcMsgFunc func(openid string, msg OneMessage) (newstate chatState)
  105. type cleanProcFunc func(openid string) (newstate chatState)
  106. //Procedure a description about all procedure
  107. type Procedure struct {
  108. init initProcFunc //init function
  109. send sendProcMsgFunc //function for sending customized message
  110. recv recvProcMsgFunc //function for receiving message, possibly transfer to new state
  111. clean cleanProcFunc //function for cleanning up
  112. }
  113. func (c *openIDSessionData) Save() {
  114. //TODO: save real session date to disk
  115. }
  116. //read sessions/openID.json to check whether its a Procedure for ongoing dialog
  117. func getCurrentSesssion(openID string) (result openIDSessionData, err error) {
  118. result = createEmptySession(openID, 3600)
  119. path := getSessionPath(openID)
  120. if isFileExist(path) {
  121. log.Printf("read session from %s\r\n", path)
  122. body, err := ioutil.ReadFile(path)
  123. if err != nil { //read file error
  124. log.Println("Error session reading " + path)
  125. } else {
  126. err = json.Unmarshal(body, &result)
  127. if err != nil {
  128. log.Printf("Session Content [path=%s] not correct: ", path)
  129. result = createEmptySession(openID, 3600)
  130. }
  131. }
  132. }
  133. return
  134. }
  135. func createEmptySession(openID string, expire int32) (result openIDSessionData) {
  136. result.OpenID = openID
  137. result.Procedure = ""
  138. now := int32(time.Now().Unix())
  139. result.CreateAt = now
  140. result.UpdateAt = now
  141. result.Expire = now + expire
  142. result.States = map[string]chatState{}
  143. return
  144. }