Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

117 lignes
2.8KB

  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "log"
  7. "os"
  8. )
  9. //chat state that we might be use for collecting infomation from user
  10. type chatState struct {
  11. //back pointer style information, managed by general process
  12. OpenID string `json:"OpenID"` //whom is this belongs to
  13. Procedure string `json:"Procedure"` //which procedure this belongs to
  14. //below is managed by procedure only
  15. //real state information
  16. Name string `json:"Name"` //state name
  17. Expire int32 `json:"Expire"` //unix timestamp when this state expire
  18. //persistant sate
  19. Save map[string]string `json:"Save"` //the state save some data for later usage
  20. //runtime memory only
  21. response string //被动回复消息的内容
  22. }
  23. //for individual state
  24. func getCurrentState(openID string, procedure string) (result chatState, err error) {
  25. path := getProcedurePath(openID, procedure)
  26. //log.Printf("read state from %s\r\n", path)
  27. body, err := ioutil.ReadFile(path)
  28. if err != nil { //read file error
  29. if isFileExist(path) {
  30. log.Println("Error session reading " + path)
  31. }
  32. return //empty and expired session
  33. }
  34. err = json.Unmarshal(body, &result)
  35. if err != nil {
  36. log.Printf("Session Content [path=%s] not correct: ", path)
  37. log.Println(err)
  38. }
  39. err = sanityCheckState(openID, procedure, result)
  40. return
  41. }
  42. func sanityCheckState(openID, procedure string, result chatState) (err error) {
  43. //check whether state is for the correct openID and procedure
  44. if result.OpenID != openID {
  45. err = errors.New("Error: State for " + openID + " is actually for " + result.OpenID)
  46. return
  47. }
  48. if result.Procedure != procedure {
  49. err = errors.New("Error: Proecdure for " + procedure + " is actually for " + result.Procedure)
  50. return
  51. }
  52. return
  53. }
  54. func setCurrentState(openID, procedure string, state chatState) (err error) {
  55. state.OpenID = openID
  56. state.Procedure = procedure
  57. j, err := json.Marshal(state)
  58. if err != nil {
  59. return
  60. }
  61. path := getProcedurePath(openID, procedure)
  62. err = ioutil.WriteFile(path, j, 0600)
  63. if err != nil {
  64. log.Println("write state error" + path)
  65. log.Println(err)
  66. return
  67. }
  68. return
  69. }
  70. func deleteChatState(openID, procedure string) (err error) {
  71. path := getProcedurePath(openID, procedure)
  72. err = os.Remove(path)
  73. return
  74. }
  75. //ValidationResult After input validation, what is the result
  76. type ValidationResult struct {
  77. accept bool
  78. Hint string
  79. Error string
  80. Warning string
  81. }
  82. //Validator function type for validating all wechat inputs
  83. type Validator func(s chatState) ValidationResult
  84. func saveChatState(openID, procedure string, state chatState) (err error) {
  85. if isExpired(state.Expire) {
  86. //skip saving sate
  87. return
  88. }
  89. err = setCurrentState(openID, procedure, state)
  90. return
  91. }
  92. func isEndingState(state chatState) bool {
  93. if isExpired(state.Expire) || state.Name == "" {
  94. return true
  95. }
  96. if state.Name == "delete" {
  97. return true
  98. }
  99. return false
  100. }