hotime/vendor/github.com/silenceper/wechat/v2/officialaccount/broadcast/broadcast.go

357 lines
8.9 KiB
Go
Raw Normal View History

2022-05-24 05:49:25 +00:00
package broadcast
import (
"fmt"
"github.com/silenceper/wechat/v2/officialaccount/context"
"github.com/silenceper/wechat/v2/util"
)
const (
sendURLByTag = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"
sendURLByOpenID = "https://api.weixin.qq.com/cgi-bin/message/mass/send"
deleteSendURL = "https://api.weixin.qq.com/cgi-bin/message/mass/delete"
previewSendURL = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"
massStatusSendURL = "https://api.weixin.qq.com/cgi-bin/message/mass/get"
getSpeedSendURL = "https://api.weixin.qq.com/cgi-bin/message/mass/speed/get"
setSpeedSendURL = "https://api.weixin.qq.com/cgi-bin/message/mass/speed/set"
)
// MsgType 发送消息类型
type MsgType string
const (
// MsgTypeNews 图文消息
MsgTypeNews MsgType = "mpnews"
// MsgTypeText 文本
MsgTypeText MsgType = "text"
// MsgTypeVoice 语音/音频
MsgTypeVoice MsgType = "voice"
// MsgTypeImage 图片
MsgTypeImage MsgType = "image"
// MsgTypeVideo 视频
MsgTypeVideo MsgType = "mpvideo"
// MsgTypeWxCard 卡券
MsgTypeWxCard MsgType = "wxcard"
)
// Broadcast 群发消息
type Broadcast struct {
*context.Context
preview bool
}
// NewBroadcast new
func NewBroadcast(ctx *context.Context) *Broadcast {
return &Broadcast{ctx, false}
}
// User 发送的用户
type User struct {
TagID int64
OpenID []string
}
// Result 群发返回结果
type Result struct {
util.CommonError
MsgID int64 `json:"msg_id"`
MsgDataID int64 `json:"msg_data_id"`
MsgStatus string `json:"msg_status"`
}
// SpeedResult 群发速度返回结果
type SpeedResult struct {
util.CommonError
Speed int64 `json:"speed"`
RealSpeed int64 `json:"realspeed"`
}
// sendRequest 发送请求的数据
type sendRequest struct {
// 根据tag获全部发送
Filter map[string]interface{} `json:"filter,omitempty"`
// 根据OpenID发送
ToUser interface{} `json:"touser,omitempty"`
// 发送文本
Text map[string]interface{} `json:"text,omitempty"`
// 发送图文消息
Mpnews map[string]interface{} `json:"mpnews,omitempty"`
// 发送语音
Voice map[string]interface{} `json:"voice,omitempty"`
// 发送图片
Images *Image `json:"images,omitempty"`
// 发送卡券
WxCard map[string]interface{} `json:"wxcard,omitempty"`
MsgType MsgType `json:"msgtype"`
SendIgnoreReprint int32 `json:"send_ignore_reprint,omitempty"`
}
// Image 发送图片
type Image struct {
MediaIDs []string `json:"media_ids"`
Recommend string `json:"recommend"`
NeedOpenComment int32 `json:"need_open_comment"`
OnlyFansCanComment int32 `json:"only_fans_can_comment"`
}
// SendText 群发文本
// user 为nil表示全员发送
// &User{TagID:2} 根据tag发送
// &User{OpenID:[]string("xxx","xxx")} 根据openid发送
func (broadcast *Broadcast) SendText(user *User, content string) (*Result, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := &sendRequest{
ToUser: nil,
MsgType: MsgTypeText,
}
req.Text = map[string]interface{}{
"content": content,
}
req, sendURL := broadcast.chooseTagOrOpenID(user, req)
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &Result{}
err = util.DecodeWithError(data, res, "SendText")
return res, err
}
// SendNews 发送图文
func (broadcast *Broadcast) SendNews(user *User, mediaID string, ignoreReprint bool) (*Result, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := &sendRequest{
ToUser: nil,
MsgType: MsgTypeNews,
}
if ignoreReprint {
req.SendIgnoreReprint = 1
}
req.Mpnews = map[string]interface{}{
"media_id": mediaID,
}
req, sendURL := broadcast.chooseTagOrOpenID(user, req)
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &Result{}
err = util.DecodeWithError(data, res, "SendNews")
return res, err
}
// SendVoice 发送语音
func (broadcast *Broadcast) SendVoice(user *User, mediaID string) (*Result, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := &sendRequest{
ToUser: nil,
MsgType: MsgTypeVoice,
}
req.Voice = map[string]interface{}{
"media_id": mediaID,
}
req, sendURL := broadcast.chooseTagOrOpenID(user, req)
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &Result{}
err = util.DecodeWithError(data, res, "SendVoice")
return res, err
}
// SendImage 发送图片
func (broadcast *Broadcast) SendImage(user *User, images *Image) (*Result, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := &sendRequest{
ToUser: nil,
MsgType: MsgTypeImage,
}
req.Images = images
req, sendURL := broadcast.chooseTagOrOpenID(user, req)
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &Result{}
err = util.DecodeWithError(data, res, "SendImage")
return res, err
}
// SendVideo 发送视频
func (broadcast *Broadcast) SendVideo(user *User, mediaID string, title, description string) (*Result, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := &sendRequest{
ToUser: nil,
MsgType: MsgTypeVideo,
}
req.Voice = map[string]interface{}{
"media_id": mediaID,
"title": title,
"description": description,
}
req, sendURL := broadcast.chooseTagOrOpenID(user, req)
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &Result{}
err = util.DecodeWithError(data, res, "SendVideo")
return res, err
}
// SendWxCard 发送卡券
func (broadcast *Broadcast) SendWxCard(user *User, cardID string) (*Result, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := &sendRequest{
ToUser: nil,
MsgType: MsgTypeWxCard,
}
req.WxCard = map[string]interface{}{
"card_id": cardID,
}
req, sendURL := broadcast.chooseTagOrOpenID(user, req)
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &Result{}
err = util.DecodeWithError(data, res, "SendWxCard")
return res, err
}
// Delete 删除群发消息
func (broadcast *Broadcast) Delete(msgID int64, articleIDx int64) error {
ak, err := broadcast.GetAccessToken()
if err != nil {
return err
}
req := map[string]interface{}{
"msg_id": msgID,
"article_idx": articleIDx,
}
url := fmt.Sprintf("%s?access_token=%s", deleteSendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return err
}
return util.DecodeWithCommonError(data, "Delete")
}
// Preview 预览
func (broadcast *Broadcast) Preview() *Broadcast {
broadcast.preview = true
return broadcast
}
// GetMassStatus 获取群发状态
func (broadcast *Broadcast) GetMassStatus(msgID string) (*Result, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := map[string]interface{}{
"msg_id": msgID,
}
url := fmt.Sprintf("%s?access_token=%s", massStatusSendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &Result{}
err = util.DecodeWithError(data, res, "GetMassStatus")
return res, err
}
// GetSpeed 获取群发速度
func (broadcast *Broadcast) GetSpeed() (*SpeedResult, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := map[string]interface{}{}
url := fmt.Sprintf("%s?access_token=%s", getSpeedSendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &SpeedResult{}
err = util.DecodeWithError(data, res, "GetSpeed")
return res, err
}
// SetSpeed 设置群发速度
func (broadcast *Broadcast) SetSpeed(speed int) (*SpeedResult, error) {
ak, err := broadcast.GetAccessToken()
if err != nil {
return nil, err
}
req := map[string]interface{}{
"speed": speed,
}
url := fmt.Sprintf("%s?access_token=%s", setSpeedSendURL, ak)
data, err := util.PostJSON(url, req)
if err != nil {
return nil, err
}
res := &SpeedResult{}
err = util.DecodeWithError(data, res, "SetSpeed")
return res, err
}
func (broadcast *Broadcast) chooseTagOrOpenID(user *User, req *sendRequest) (ret *sendRequest, url string) {
sendURL := ""
if user == nil {
req.Filter = map[string]interface{}{
"is_to_all": true,
}
sendURL = sendURLByTag
} else {
if broadcast.preview {
// 预览 默认发给第一个用户
if len(user.OpenID) != 0 {
req.ToUser = user.OpenID[0]
sendURL = previewSendURL
}
} else {
if user.TagID != 0 {
req.Filter = map[string]interface{}{
"is_to_all": false,
"tag_id": user.TagID,
}
sendURL = sendURLByTag
}
if len(user.OpenID) != 0 {
req.ToUser = user.OpenID
sendURL = sendURLByOpenID
}
}
}
return req, sendURL
}