forked from chanxuehong/wechat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
news.go
220 lines (191 loc) · 6.01 KB
/
news.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package material
import (
"fmt"
"github.com/masiqi/wechat.v2/mp/core"
)
type Article struct {
ThumbMediaId string `json:"thumb_media_id"` // 图文消息的封面图片素材id(必须是永久mediaID)
Title string `json:"title"` // 标题
Author string `json:"author,omitempty"` // 作者
Digest string `json:"digest,omitempty"` // 图文消息的摘要, 仅有单图文消息才有摘要, 多图文此处为空
Content string `json:"content"` // 图文消息的具体内容, 支持HTML标签, 必须少于2万字符, 小于1M, 且此处会去除JS
ContentSourceURL string `json:"content_source_url,omitempty"` // 图文消息的原文地址, 即点击"阅读原文"后的URL
ShowCoverPic int `json:"show_cover_pic"` // 是否显示封面, 0为false, 即不显示, 1为true, 即显示
URL string `json:"url,omitempty"` // !!!创建时不需要此参数!!! 图文页的URL, 文章创建成功以后, 会由微信自动生成
}
type News struct {
Articles []Article `json:"articles,omitempty"`
}
// 新增永久图文素材.
func AddNews(clt *core.Client, news *News) (mediaId string, err error) {
const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token="
var result struct {
core.Error
MediaId string `json:"media_id"`
}
if err = clt.PostJSON(incompleteURL, news, &result); err != nil {
return
}
if result.ErrCode != core.ErrCodeOK {
err = &result.Error
return
}
mediaId = result.MediaId
return
}
// 获取永久图文素材.
func GetNews(clt *core.Client, mediaId string) (news *News, err error) {
const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token="
var request = struct {
MediaId string `json:"media_id"`
}{
MediaId: mediaId,
}
var result struct {
core.Error
Articles []Article `json:"news_item"`
}
if err = clt.PostJSON(incompleteURL, &request, &result); err != nil {
return
}
if result.ErrCode != core.ErrCodeOK {
err = &result.Error
return
}
news = &News{
Articles: result.Articles,
}
return
}
// 修改永久图文素材.
func UpdateNews(clt *core.Client, mediaId string, index int, article *Article) (err error) {
const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/update_news?access_token="
var request = struct {
MediaId string `json:"media_id"`
Index int `json:"index"`
Article *Article `json:"articles,omitempty"`
}{
MediaId: mediaId,
Index: index,
Article: article,
}
var result core.Error
if err = clt.PostJSON(incompleteURL, &request, &result); err != nil {
return
}
if result.ErrCode != core.ErrCodeOK {
err = &result
return
}
return
}
type BatchGetNewsResult struct {
TotalCount int `json:"total_count"` // 该类型的素材的总数
ItemCount int `json:"item_count"` // 本次调用获取的素材的数量
Items []NewsInfo `json:"item"` // 本次调用获取的素材列表
}
type NewsInfo struct {
MediaId string `json:"media_id"` // 素材id
UpdateTime int64 `json:"update_time"` // 最后更新时间
Content struct {
Articles []Article `json:"news_item,omitempty"`
} `json:"content"`
}
// 获取图文素材列表.
// offset: 从全部素材的该偏移位置开始返回, 0表示从第一个素材
// count: 返回素材的数量, 取值在1到20之间
func BatchGetNews(clt *core.Client, offset, count int) (rslt *BatchGetNewsResult, err error) {
const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token="
if offset < 0 {
err = fmt.Errorf("Incorrect offset: %d", offset)
return
}
if count <= 0 {
err = fmt.Errorf("Incorrect count: %d", count)
return
}
var request = struct {
MaterialType string `json:"type"`
Offset int `json:"offset"`
Count int `json:"count"`
}{
MaterialType: MaterialTypeNews,
Offset: offset,
Count: count,
}
var result struct {
core.Error
BatchGetNewsResult
}
if err = clt.PostJSON(incompleteURL, &request, &result); err != nil {
return
}
if result.ErrCode != core.ErrCodeOK {
err = &result.Error
return
}
rslt = &result.BatchGetNewsResult
return
}
// =====================================================================================================================
// NewsIterator
//
// iter, err := NewNewsIterator(clt, 0, 10)
// if err != nil {
// // TODO: 增加你的代码
// }
//
// for iter.HasNext() {
// items, err := iter.NextPage()
// if err != nil {
// // TODO: 增加你的代码
// }
// // TODO: 增加你的代码
// }
type NewsIterator struct {
clt *core.Client
nextOffset int
count int
lastBatchGetNewsResult *BatchGetNewsResult
nextPageCalled bool
}
func (iter *NewsIterator) TotalCount() int {
return iter.lastBatchGetNewsResult.TotalCount
}
func (iter *NewsIterator) HasNext() bool {
if !iter.nextPageCalled {
return iter.lastBatchGetNewsResult.ItemCount > 0 || iter.nextOffset < iter.lastBatchGetNewsResult.TotalCount
}
return iter.nextOffset < iter.lastBatchGetNewsResult.TotalCount
}
func (iter *NewsIterator) NextPage() (items []NewsInfo, err error) {
if !iter.nextPageCalled {
iter.nextPageCalled = true
items = iter.lastBatchGetNewsResult.Items
return
}
rslt, err := BatchGetNews(iter.clt, iter.nextOffset, iter.count)
if err != nil {
return
}
iter.lastBatchGetNewsResult = rslt
iter.nextOffset += rslt.ItemCount
items = rslt.Items
return
}
func NewNewsIterator(clt *core.Client, offset, count int) (iter *NewsIterator, err error) {
// 逻辑上相当于第一次调用 NewsIterator.NextPage,
// 因为第一次调用 NewsIterator.HasNext 需要数据支撑, 所以提前获取了数据
rslt, err := BatchGetNews(clt, offset, count)
if err != nil {
return
}
iter = &NewsIterator{
clt: clt,
nextOffset: offset + rslt.ItemCount,
count: count,
lastBatchGetNewsResult: rslt,
nextPageCalled: false,
}
return
}