draft.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package draft
  2. import (
  3. "fmt"
  4. "github.com/silenceper/wechat/v2/officialaccount/context"
  5. "github.com/silenceper/wechat/v2/util"
  6. )
  7. const (
  8. addURL = "https://api.weixin.qq.com/cgi-bin/draft/add" // 新建草稿
  9. getURL = "https://api.weixin.qq.com/cgi-bin/draft/get" // 获取草稿
  10. deleteURL = "https://api.weixin.qq.com/cgi-bin/draft/delete" // 删除草稿
  11. updateURL = "https://api.weixin.qq.com/cgi-bin/draft/update" // 修改草稿
  12. countURL = "https://api.weixin.qq.com/cgi-bin/draft/count" // 获取草稿总数
  13. paginateURL = "https://api.weixin.qq.com/cgi-bin/draft/batchget" // 获取草稿列表
  14. )
  15. // Draft 草稿箱
  16. type Draft struct {
  17. *context.Context
  18. }
  19. // NewDraft init
  20. func NewDraft(ctx *context.Context) *Draft {
  21. return &Draft{
  22. Context: ctx,
  23. }
  24. }
  25. // Article 草稿
  26. type Article struct {
  27. Title string `json:"title"` // 标题
  28. Author string `json:"author"` // 作者
  29. Digest string `json:"digest"` // 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空。
  30. Content string `json:"content"` // 图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,且去除JS
  31. ContentSourceURL string `json:"content_source_url"` // 图文消息的原文地址,即点击“阅读原文”后的URL
  32. ThumbMediaID string `json:"thumb_media_id"` // 图文消息的封面图片素材id(必须是永久MediaID)
  33. ShowCoverPic uint `json:"show_cover_pic"` // 是否显示封面,0为false,即不显示,1为true,即显示(默认)
  34. NeedOpenComment uint `json:"need_open_comment"` // 是否打开评论,0不打开(默认),1打开
  35. OnlyFansCanComment uint `json:"only_fans_can_comment"` // 是否粉丝才可评论,0所有人可评论(默认),1粉丝才可评论
  36. }
  37. // AddDraft 新建草稿
  38. func (draft *Draft) AddDraft(articles []*Article) (mediaID string, err error) {
  39. accessToken, err := draft.GetAccessToken()
  40. if err != nil {
  41. return
  42. }
  43. var req struct {
  44. Articles []*Article `json:"articles"`
  45. }
  46. req.Articles = articles
  47. uri := fmt.Sprintf("%s?access_token=%s", addURL, accessToken)
  48. response, err := util.PostJSON(uri, req)
  49. if err != nil {
  50. return
  51. }
  52. var res struct {
  53. util.CommonError
  54. MediaID string `json:"media_id"`
  55. }
  56. err = util.DecodeWithError(response, &res, "AddDraft")
  57. if err != nil {
  58. return
  59. }
  60. mediaID = res.MediaID
  61. return
  62. }
  63. // GetDraft 获取草稿
  64. func (draft *Draft) GetDraft(mediaID string) (articles []*Article, err error) {
  65. accessToken, err := draft.GetAccessToken()
  66. if err != nil {
  67. return
  68. }
  69. var req struct {
  70. MediaID string `json:"media_id"`
  71. }
  72. req.MediaID = mediaID
  73. uri := fmt.Sprintf("%s?access_token=%s", getURL, accessToken)
  74. response, err := util.PostJSON(uri, req)
  75. if err != nil {
  76. return
  77. }
  78. var res struct {
  79. util.CommonError
  80. NewsItem []*Article `json:"news_item"`
  81. }
  82. err = util.DecodeWithError(response, &res, "GetDraft")
  83. if err != nil {
  84. return
  85. }
  86. articles = res.NewsItem
  87. return
  88. }
  89. // DeleteDraft 删除草稿
  90. func (draft *Draft) DeleteDraft(mediaID string) (err error) {
  91. accessToken, err := draft.GetAccessToken()
  92. if err != nil {
  93. return
  94. }
  95. var req struct {
  96. MediaID string `json:"media_id"`
  97. }
  98. req.MediaID = mediaID
  99. var response []byte
  100. uri := fmt.Sprintf("%s?access_token=%s", deleteURL, accessToken)
  101. response, err = util.PostJSON(uri, req)
  102. if err != nil {
  103. return
  104. }
  105. err = util.DecodeWithCommonError(response, "DeleteDraft")
  106. return
  107. }
  108. // UpdateDraft 修改草稿
  109. // index 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0
  110. func (draft *Draft) UpdateDraft(article *Article, mediaID string, index uint) (err error) {
  111. accessToken, err := draft.GetAccessToken()
  112. if err != nil {
  113. return
  114. }
  115. var req struct {
  116. MediaID string `json:"media_id"`
  117. Index uint `json:"index"`
  118. Article *Article `json:"articles"`
  119. }
  120. req.MediaID = mediaID
  121. req.Index = index
  122. req.Article = article
  123. uri := fmt.Sprintf("%s?access_token=%s", updateURL, accessToken)
  124. var response []byte
  125. response, err = util.PostJSON(uri, req)
  126. if err != nil {
  127. return
  128. }
  129. err = util.DecodeWithCommonError(response, "UpdateDraft")
  130. return
  131. }
  132. // CountDraft 获取草稿总数
  133. func (draft *Draft) CountDraft() (total uint, err error) {
  134. accessToken, err := draft.GetAccessToken()
  135. if err != nil {
  136. return
  137. }
  138. var response []byte
  139. uri := fmt.Sprintf("%s?access_token=%s", countURL, accessToken)
  140. response, err = util.HTTPGet(uri)
  141. if err != nil {
  142. return
  143. }
  144. var res struct {
  145. util.CommonError
  146. Total uint `json:"total_count"`
  147. }
  148. err = util.DecodeWithError(response, &res, "CountDraft")
  149. if nil != err {
  150. return
  151. }
  152. total = res.Total
  153. return
  154. }
  155. // ArticleList 草稿列表
  156. type ArticleList struct {
  157. util.CommonError
  158. TotalCount int64 `json:"total_count"` // 草稿素材的总数
  159. ItemCount int64 `json:"item_count"` // 本次调用获取的素材的数量
  160. Item []ArticleListItem `json:"item"`
  161. }
  162. // ArticleListItem 用于 ArticleList 的 item 节点
  163. type ArticleListItem struct {
  164. MediaID string `json:"media_id"` // 图文消息的id
  165. Content ArticleListContent `json:"content"` // 内容
  166. UpdateTime int64 `json:"update_time"` // 这篇图文消息素材的最后更新时间
  167. }
  168. // ArticleListContent 用于 ArticleListItem 的 content 节点
  169. type ArticleListContent struct {
  170. NewsItem []Article `json:"news_item"` // 这篇图文消息素材的内容
  171. }
  172. // PaginateDraft 获取草稿列表
  173. func (draft *Draft) PaginateDraft(offset, count int64, noReturnContent bool) (list ArticleList, err error) {
  174. accessToken, err := draft.GetAccessToken()
  175. if err != nil {
  176. return
  177. }
  178. var req struct {
  179. Count int64 `json:"count"`
  180. Offset int64 `json:"offset"`
  181. NoReturnContent bool `json:"no_content"`
  182. }
  183. req.Count = count
  184. req.Offset = offset
  185. req.NoReturnContent = noReturnContent
  186. var response []byte
  187. uri := fmt.Sprintf("%s?access_token=%s", paginateURL, accessToken)
  188. response, err = util.PostJSON(uri, req)
  189. if err != nil {
  190. return
  191. }
  192. err = util.DecodeWithError(response, &list, "PaginateDraft")
  193. return
  194. }