您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

253 行
5.8KB

  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "log"
  8. "net/http"
  9. "strings"
  10. )
  11. //abstract CRUD operation for espoCRM Entity
  12. func crmCreateEntity(entityType string, jsonB []byte) (entity interface{}, err error) {
  13. url := CRMConfig.apiURL(entityType)
  14. jsonStr, err := postRAW(jsonB, url, crmBuildCommonAPIHeader())
  15. if err != nil {
  16. entity, _ = crmRescueDuplicateCreate(err, entityType)
  17. return
  18. }
  19. return crmJSON2Entity(entityType, jsonStr)
  20. }
  21. func crmUpdateEntity(entityType string, id string, jsonB []byte) (entity interface{}, err error) {
  22. url := CRMConfig.apiEntityURL(entityType, id)
  23. jsonStr, err := patchRAW(jsonB, url, crmBuildCommonAPIHeader())
  24. if err != nil {
  25. log.Println(err)
  26. return
  27. }
  28. return crmJSON2Entity(entityType, jsonStr)
  29. }
  30. func crmReplaceEntity(entityType string, id string, jsonB []byte) (entity interface{}, err error) {
  31. url := CRMConfig.apiEntityURL(entityType, id)
  32. jsonStr, err := putRAW(jsonB, url, crmBuildCommonAPIHeader())
  33. if err != nil {
  34. log.Println(err)
  35. return
  36. }
  37. return crmJSON2Entity(entityType, jsonStr)
  38. }
  39. func crmDeleteEntity(entityType string, id string) (deleted bool, err error) {
  40. url := CRMConfig.apiEntityURL(entityType, id)
  41. resp, err := deleteRAW(url, crmBuildCommonAPIHeader())
  42. if err != nil {
  43. log.Println(err)
  44. return
  45. }
  46. deleted = strings.ToLower(resp) == "true"
  47. return
  48. }
  49. //give an id, return json
  50. func crmGetEntity(entityType string, id string) (entity interface{}, err error) {
  51. url := CRMConfig.apiEntityURL(entityType, id)
  52. jsonStr, err := getRAW(url, crmBuildCommonAPIHeader())
  53. if err != nil {
  54. log.Println(err)
  55. return
  56. }
  57. return crmJSON2Entity(entityType, jsonStr)
  58. }
  59. func crmBuildCommonAPIHeader() (headers map[string]string) {
  60. headers = map[string]string{}
  61. headers["Authorization"] = crmAuthHeader()
  62. headers["Accept"] = "application/json"
  63. headers["Content-Type"] = "application/json"
  64. return headers
  65. }
  66. //given a json string, convert it to Typed structure
  67. func crmJSON2Entity(entityType string, data string) (r interface{}, err error) {
  68. switch entityType {
  69. case "Lead":
  70. e := crmdLead{}
  71. err = json.Unmarshal([]byte(data), &e)
  72. r = e
  73. case "Account":
  74. //r = crmdAccount{}
  75. case "Location":
  76. e := crmdLocation{}
  77. err = json.Unmarshal([]byte(data), &e)
  78. r = e
  79. case "Contact":
  80. e := crmdContact{}
  81. err = json.Unmarshal([]byte(data), &e)
  82. r = e
  83. default:
  84. log.Fatalf("crmJSON2Entity: Unknown EntityType %s", entityType)
  85. }
  86. if err != nil {
  87. log.Println(err)
  88. }
  89. return
  90. }
  91. func crmRescueDuplicateCreate(e error, entityType string) (entity interface{}, success bool) {
  92. if !isErrIndicateDuplicate(e) {
  93. return
  94. }
  95. entity, err := e.(errorHTTPResponse).XStatusReason().Data2Entity(entityType)
  96. success = err == nil
  97. return
  98. }
  99. func isErrIndicateDuplicate(e error) (yes bool) {
  100. err, isOurError := e.(errorHTTPResponse)
  101. if !isOurError {
  102. return
  103. }
  104. reason := err.XStatusReason()
  105. yes = strings.ToLower(reason.Reason) == "duplicate"
  106. return
  107. }
  108. type crmdSearchFilter struct {
  109. Attribute string
  110. CompareMethod string //startWith, equals, contains, endsWith, like, isNull, isNotNull , notEquals
  111. ExpectValue string
  112. }
  113. type crmdSearchResult struct {
  114. Total int `json:"total"`
  115. List *json.RawMessage `json:"list"`
  116. }
  117. func crmSearchEntity(entityType string, filters []crmdSearchFilter) (result crmdSearchResult, err error) {
  118. url := CRMConfig.apiURL(entityType)
  119. req, err := http.NewRequest("GET", url, nil)
  120. if err != nil {
  121. log.Println("crmGetRecord: cannot form good http Request")
  122. log.Print(err)
  123. return
  124. }
  125. //auth header
  126. req.Header.Set("Authorization", crmAuthHeader())
  127. req.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01")
  128. req.Header.Set("Content-Type", "application/json")
  129. //query string
  130. q := req.URL.Query()
  131. q.Add("maxSize", "20")
  132. q.Add("maxSize", "0")
  133. q.Add("sortBy", "createdAt")
  134. q.Add("asc", "false")
  135. for k, v := range filters {
  136. switch v.CompareMethod {
  137. case "startWith", "equals", "contains", "endsWith", "like", "notEquals":
  138. q.Add(fmt.Sprintf("where[%d][type]", k), v.CompareMethod)
  139. q.Add(fmt.Sprintf("where[%d][attribute]", k), v.Attribute)
  140. q.Add(fmt.Sprintf("where[%d][value]", k), v.ExpectValue)
  141. case "isNull", "isNotNull":
  142. q.Add(fmt.Sprintf("where[%d][type]", k), v.CompareMethod)
  143. q.Add(fmt.Sprintf("where[%d][attribute]", k), v.Attribute)
  144. default:
  145. log.Printf("Unknown Compare Method %s", v.CompareMethod)
  146. }
  147. }
  148. req.URL.RawQuery = q.Encode()
  149. //debugDumpHTTPRequest(req)
  150. client := &http.Client{}
  151. r, err := client.Do(req)
  152. //debugDumpHTTPResponse(r)
  153. if err != nil {
  154. return
  155. }
  156. defer r.Body.Close()
  157. jsonB, err := ioutil.ReadAll(r.Body)
  158. if err != nil {
  159. return
  160. }
  161. err = json.Unmarshal(jsonB, &result)
  162. return
  163. }
  164. func crmFindEntityByID(entityType string, id string) (entity interface{}, err error) {
  165. id = strings.TrimSpace(id)
  166. if id == "" {
  167. err = errors.New("empty ID not accepted")
  168. return
  169. }
  170. filters := []crmdSearchFilter{
  171. {"id", "equals", id},
  172. }
  173. cs, err := crmSearchEntity(entityType, filters)
  174. if err != nil || cs.Total < 1 {
  175. return
  176. }
  177. if cs.Total > 1 {
  178. log.Printf("ERROR: more than one(%d) %s associated with %s", cs.Total, entityType, id)
  179. }
  180. switch entityType {
  181. case "Lead":
  182. e := []crmdLead{}
  183. err = json.Unmarshal(*cs.List, &e)
  184. if (err != nil) || (len(e) != cs.Total) {
  185. return
  186. }
  187. entity = e[0]
  188. case "Account":
  189. return
  190. case "Livecast":
  191. e := []crmdLiveCast{}
  192. err = json.Unmarshal(*cs.List, &e)
  193. if (err != nil) || (len(e) != cs.Total) {
  194. return
  195. }
  196. entity = e[0]
  197. }
  198. return
  199. }
  200. func crmFindEntityByAttr(entityType, attribute, value string) (total int, list interface{}, err error) {
  201. filters := []crmdSearchFilter{
  202. {attribute, "equals", value},
  203. }
  204. cs, err := crmSearchEntity(entityType, filters)
  205. if err != nil || cs.Total < 1 {
  206. return
  207. }
  208. total = cs.Total
  209. switch entityType {
  210. case "Lead":
  211. e := []crmdLead{}
  212. err = json.Unmarshal(*cs.List, &e)
  213. list = e
  214. case "Account":
  215. return
  216. }
  217. return
  218. }