初始化项目

This commit is contained in:
2022-09-27 11:31:23 +08:00
parent b4dc3c7305
commit 533ede4f66
54 changed files with 12011 additions and 25 deletions

398
push/api.go Normal file
View File

@@ -0,0 +1,398 @@
/**
* @Author: Echo
* @Author:1711788888@qq.com
* @Date: 2021/5/27 20:42
* @Desc: 全员推送
*/
package push
import (
"fmt"
"strconv"
"git.echol.cn/loser/tencent-im/internal/core"
"git.echol.cn/loser/tencent-im/internal/enum"
"git.echol.cn/loser/tencent-im/internal/types"
)
const (
service = "all_member_push"
commandPushMessage = "im_push"
commandSetAttrNames = "im_set_attr_name"
commandGetAttrNames = "im_get_attr_name"
commandGetUserAttrs = "im_get_attr"
commandSetUserAttrs = "im_set_attr"
commandDeleteUserAttrs = "im_remove_attr"
commandGetUserTags = "im_get_tag"
commandAddUserTags = "im_add_tag"
commandDeleteUserTags = "im_remove_tag"
commandDeleteUserAllTags = "im_remove_all_tags"
batchSetAttrNamesLimit = 10 // 批量设置应用属性名限制
batchGetUserAttrsLimit = 100 // 批量获取用户属性限制
batchSetUserAttrsLimit = 100 // 批量设置用户属性限制
batchDeleteUserAttrsLimit = 100 // 批量删除用户属性限制
batchAddUserTagsLimit = 100 // 批量添加用户标签限制
batchGetUserTagsLimit = 100 // 批量获取用户标签限制
batchDeleteUserTagsLimit = 100 // 批量删除用户标签限制
batchDeleteUserAllTagsUserLimit = 100 // 批量删除用户所有标签的用户限制
)
type API interface {
// PushMessage 全员推送
// 支持全员推送。
// 支持按用户属性推送。
// 支持按用户标签推送。
// 管理员推送消息,接收方看到消息发送者是管理员。
// 管理员指定某一帐号向其他帐号推送消息,接收方看到发送者不是管理员,而是管理员指定的帐号。
// 支持消息离线存储,不支持漫游。
// 由于全员推送需要下发的帐号数量巨大,下发完全部帐号需要一定时间(根据帐号总数而定,一般在一分钟内)。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45934
PushMessage(message *Message) (taskId string, err error)
// SetAttrNames 设置应用属性名称
// 每个应用可以设置自定义的用户属性最多可以有10个。通过本接口可以设置每个属性的名称设置完成后即可用于按用户属性推送等。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45935
SetAttrNames(attrNames map[int]string) (err error)
// GetAttrNames 获取应用属性名称
// 管理员获取应用属性名称。使用前请先 设置应用属性名称 。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45936
GetAttrNames() (attrNames map[int]string, err error)
// GetUserAttrs 获取用户属性
// 获取用户属性必须以管理员帐号调用每次最多只能获取100个用户的属性。使用前请先 设置应用属性名称 。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45937
GetUserAttrs(userIds ...string) (attrs map[string]map[string]interface{}, err error)
// SetUserAttrs 设置用户属性
// 管理员给用户设置属性。每次最多只能给100个用户设置属性。使用前请先 设置应用属性名称 。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45938
SetUserAttrs(userAttrs map[string]map[string]interface{}) (err error)
// DeleteUserAttrs 删除用户属性
// 管理员给用户删除属性。注意每次最多只能给100个用户删除属性。使用前请先 设置应用属性名称。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45939
DeleteUserAttrs(userAttrs map[string][]string) (err error)
// GetUserTags 获取用户标签
// 获取用户标签必须以管理员帐号调用。每次最多只能获取100个用户的标签。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45940
GetUserTags(userIds ...string) (tags map[string][]string, err error)
// AddUserTags 添加用户标签
// 管理员给用户添加标签。
// 每次请求最多只能给100个用户添加标签请求体中单个用户添加标签数最多为10个。
// 单个用户可设置最大标签数为100个若用户当前标签超过100则添加新标签之前请先删除旧标签。
// 单个标签最大长度为50字节。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45941
AddUserTags(userTags map[string][]string) (err error)
// DeleteUserTags 删除用户标签
// 管理员给用户删除标签。注意每次最多只能给100个用户删除标签。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45942
DeleteUserTags(userTags map[string][]string) (err error)
// DeleteUserAllTags 删除用户所有标签
// 管理员给用户删除所有标签。注意每次最多只能给100个用户删除所有标签。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45943
DeleteUserAllTags(userIds ...string) (err error)
}
type api struct {
client core.Client
}
func NewAPI(client core.Client) API {
return &api{client: client}
}
// PushMessage 全员推送
// 支持全员推送。
// 支持按用户属性推送。
// 支持按用户标签推送。
// 管理员推送消息,接收方看到消息发送者是管理员。
// 管理员指定某一帐号向其他帐号推送消息,接收方看到发送者不是管理员,而是管理员指定的帐号。
// 支持消息离线存储,不支持漫游。
// 由于全员推送需要下发的帐号数量巨大,下发完全部帐号需要一定时间(根据帐号总数而定,一般在一分钟内)。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45934
func (a *api) PushMessage(message *Message) (taskId string, err error) {
if err = message.checkError(); err != nil {
return
}
req := &pushMessageReq{}
req.FromUserId = message.GetSender()
req.MsgLifeTime = message.GetLifeTime()
req.OfflinePushInfo = message.GetOfflinePushInfo()
req.MsgBody = message.GetBody()
req.MsgRandom = message.GetRandom()
req.Condition = message.GetCondition()
resp := &pushMessageResp{}
if err = a.client.Post(service, commandPushMessage, req, resp); err != nil {
return
}
taskId = resp.TaskId
return
}
// SetAttrNames 设置应用属性名称
// 每个应用可以设置自定义的用户属性最多可以有10个。通过本接口可以设置每个属性的名称设置完成后即可用于按用户属性推送等。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45935
func (a *api) SetAttrNames(attrNames map[int]string) (err error) {
if c := len(attrNames); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the attribute names is not set")
return
} else if c > batchSetAttrNamesLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of attribute names to be set cannot exceed %d", batchSetAttrNamesLimit))
return
}
req := &setAttrNamesReq{AttrNames: make(map[string]string, len(attrNames))}
for i, attrName := range attrNames {
req.AttrNames[strconv.Itoa(i)] = attrName
}
if err = a.client.Post(service, commandSetAttrNames, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// GetAttrNames 获取应用属性名称
// 管理员获取应用属性名称。使用前请先 设置应用属性名称 。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45936
func (a *api) GetAttrNames() (attrNames map[int]string, err error) {
req := &getAttrNamesReq{}
resp := &getAttrNamesResp{}
if err = a.client.Post(service, commandGetAttrNames, req, resp); err != nil {
return
}
if len(resp.AttrNames) > 0 {
var i int
attrNames = make(map[int]string, len(resp.AttrNames))
for key, attrName := range resp.AttrNames {
i, _ = strconv.Atoi(key)
attrNames[i] = attrName
}
}
return
}
// GetUserAttrs 获取用户属性
// 获取用户属性必须以管理员帐号调用每次最多只能获取100个用户的属性。使用前请先 设置应用属性名称 。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45937
func (a *api) GetUserAttrs(userIds ...string) (attrs map[string]map[string]interface{}, err error) {
if c := len(userIds); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the accounts is not set")
return
} else if c > batchGetUserAttrsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of accounts being queried cannot exceed %d", batchGetUserAttrsLimit))
return
}
req := &getUserAttrsReq{UserIds: userIds}
resp := &getUserAttrsResp{}
if err = a.client.Post(service, commandGetUserAttrs, req, resp); err != nil {
return
}
attrs = make(map[string]map[string]interface{}, len(resp.Attrs))
for _, attr := range resp.Attrs {
attrs[attr.UserId] = attr.Attrs
}
return
}
// SetUserAttrs 设置用户属性
// 管理员给用户设置属性。每次最多只能给100个用户设置属性。使用前请先 设置应用属性名称 。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45938
func (a *api) SetUserAttrs(userAttrs map[string]map[string]interface{}) (err error) {
if c := len(userAttrs); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the attributes is not set")
return
} else if c > batchSetUserAttrsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of attributes to be set cannot exceed %d", batchSetUserAttrsLimit))
return
}
req := &setUserAttrsReq{Attrs: make([]*userAttrItem, 0, len(userAttrs))}
for userId, attrs := range userAttrs {
req.Attrs = append(req.Attrs, &userAttrItem{
UserId: userId,
Attrs: attrs,
})
}
if err = a.client.Post(service, commandSetUserAttrs, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// DeleteUserAttrs 删除用户属性
// 管理员给用户删除属性。注意每次最多只能给100个用户删除属性。使用前请先 设置应用属性名称。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45939
func (a *api) DeleteUserAttrs(userAttrs map[string][]string) (err error) {
if c := len(userAttrs); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the attributes is not set")
return
} else if c > batchDeleteUserAttrsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of attributes to be delete cannot exceed %d", batchDeleteUserAttrsLimit))
return
}
req := &deleteUserAttrsReq{Attrs: make([]deleteUserAttr, 0, len(userAttrs))}
for userId, attrs := range userAttrs {
req.Attrs = append(req.Attrs, deleteUserAttr{
UserId: userId,
Attrs: attrs,
})
}
if err = a.client.Post(service, commandDeleteUserAttrs, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// GetUserTags 获取用户标签
// 获取用户标签必须以管理员帐号调用。每次最多只能获取100个用户的标签。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45940
func (a *api) GetUserTags(userIds ...string) (tags map[string][]string, err error) {
if c := len(userIds); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the accounts is not set")
return
} else if c > batchGetUserTagsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of tags being queried cannot exceed %d", batchGetUserTagsLimit))
return
}
req := &getUserTagsReq{UserIds: userIds}
resp := &getUserTagsResp{}
if err = a.client.Post(service, commandGetUserTags, req, resp); err != nil {
return
}
if len(resp.Tags) > 0 {
tags = make(map[string][]string, len(resp.Tags))
for _, item := range resp.Tags {
tags[item.UserId] = item.Tags
}
}
return
}
// AddUserTags 添加用户标签
// 管理员给用户添加标签。
// 每次请求最多只能给100个用户添加标签请求体中单个用户添加标签数最多为10个。
// 单个用户可设置最大标签数为100个若用户当前标签超过100则添加新标签之前请先删除旧标签。
// 单个标签最大长度为50字节。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45941
func (a *api) AddUserTags(userTags map[string][]string) (err error) {
if c := len(userTags); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the tags of user is not set")
return
} else if c > batchAddUserTagsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of tags to be add cannot exceed %d", batchAddUserTagsLimit))
return
}
req := &addUserTagsReq{Tags: make([]*userTag, 0, len(userTags))}
for userId, tags := range userTags {
req.Tags = append(req.Tags, &userTag{
UserId: userId,
Tags: tags,
})
}
if err = a.client.Post(service, commandAddUserTags, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// DeleteUserTags 删除用户标签
// 管理员给用户删除标签。注意每次最多只能给100个用户删除标签。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45942
func (a *api) DeleteUserTags(userTags map[string][]string) (err error) {
if c := len(userTags); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the tags of user is not set")
return
} else if c > batchDeleteUserTagsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of tags to be delete cannot exceed %d", batchDeleteUserTagsLimit))
return
}
req := &deleteUserTagsReq{Tags: make([]*userTag, 0, len(userTags))}
for userId, tags := range userTags {
req.Tags = append(req.Tags, &userTag{
UserId: userId,
Tags: tags,
})
}
if err = a.client.Post(service, commandDeleteUserTags, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// DeleteUserAllTags 删除用户所有标签
// 管理员给用户删除所有标签。注意每次最多只能给100个用户删除所有标签。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/45943
func (a *api) DeleteUserAllTags(userIds ...string) (err error) {
if c := len(userIds); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the accounts is not set")
return
} else if c > batchDeleteUserAllTagsUserLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of accounts to be delete cannot exceed %d", batchDeleteUserAllTagsUserLimit))
return
}
req := &deleteUserAllTagsReq{UserIds: userIds}
if err = a.client.Post(service, commandDeleteUserAllTags, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}

38
push/enum.go Normal file
View File

@@ -0,0 +1,38 @@
/**
* @Author: Echo
* @Author:1711788888@qq.com
* @Date: 2021/9/7 10:16
* @Desc: TODO
*/
package push
import (
"git.echol.cn/loser/tencent-im/internal/enum"
)
const (
// 推送标识
PushFlagYes = enum.PushFlagYes // 正常推送
PushFlagNo = enum.PushFlagYes // 不离线推送
// 华为推送通知消息分类
HuaWeiImportanceLow = enum.HuaWeiImportanceLow // LOW类消息
HuaWeiImportanceNormal = enum.HuaWeiImportanceNormal // NORMAL类消息
// 华为推送为“打开应用内指定页面”的前提下透传参数行为
HuaweiIntentParamAction = enum.HuaweiIntentParamAction // 将透传内容Ext作为Action参数
HuaweiIntentParamIntent = enum.HuaweiIntentParamIntent // 将透传内容Ext作为Intent参数
// VIVO手机推送消息分类
VivoClassificationOperation = enum.VivoClassificationOperation // 运营类消息
VivoClassificationSystem = enum.VivoClassificationSystem // 系统类消息
// IOS徽章计数模式
BadgeModeNormal = enum.BadgeModeNormal // 本条消息需要计数
BadgeModeIgnore = enum.BadgeModeIgnore // 本条消息不需要计数
// IOS10的推送扩展开关
MutableContentNormal = enum.MutableContentNormal // 关闭iOS10的推送扩展
MutableContentEnable = enum.MutableContentEnable // 开启iOS10的推送扩展
)

152
push/message.go Normal file
View File

@@ -0,0 +1,152 @@
/**
* @Author: Echo
* @Author:1711788888@qq.com
* @Date: 2021/9/3 18:15
* @Desc: 推送消息实体
*/
package push
import (
"errors"
"git.echol.cn/loser/tencent-im/internal/entity"
)
var errInvalidPushCondition = errors.New("attrs and tags condition cannot be set at the same time")
type Message struct {
entity.Message
condition *condition
}
func NewMessage() *Message {
return &Message{}
}
// SetConditionTagsOr 设置标签的或条件(设置会冲掉之前的标签或条件)
func (m *Message) SetConditionTagsOr(tags ...string) {
if m.condition != nil && m.condition.TagsOr != nil {
m.condition.TagsOr = m.condition.TagsOr[0:0]
}
m.AddConditionTagsOr(tags...)
}
// AddConditionTagsOr 添加标签的或条件(添加会累加之前的条件或条件)
func (m *Message) AddConditionTagsOr(tags ...string) {
if m.condition == nil {
m.condition = &condition{}
}
if m.condition.TagsOr == nil {
m.condition.TagsOr = make([]string, 0)
}
m.condition.TagsOr = append(m.condition.TagsOr, tags...)
}
// SetConditionTagsAnd 设置标签的与条件(设置会冲掉之前的标签与条件)
func (m *Message) SetConditionTagsAnd(tags ...string) {
if m.condition != nil && m.condition.TagsAnd != nil {
m.condition.TagsAnd = m.condition.TagsAnd[0:0]
}
m.AddConditionTagsAnd(tags...)
}
// AddConditionTagsAnd 添加标签的与条件(添加会累加之前的标签与条件)
func (m *Message) AddConditionTagsAnd(tags ...string) {
if m.condition == nil {
m.condition = &condition{}
}
if m.condition.TagsAnd == nil {
m.condition.TagsAnd = make([]string, 0)
}
m.condition.TagsAnd = append(m.condition.TagsAnd, tags...)
}
// SetConditionAttrsOr 设置属性的或条件(设置会冲掉之前的属性或条件)
func (m *Message) SetConditionAttrsOr(attrs map[string]interface{}) {
if m.condition != nil && m.condition.AttrsOr != nil {
m.condition.AttrsOr = make(map[string]interface{})
}
m.AddConditionAttrsOr(attrs)
}
// AddConditionAttrsOr 添加属性的或条件(添加会累加之前的属性或条件)
func (m *Message) AddConditionAttrsOr(attrs map[string]interface{}) {
if m.condition == nil {
m.condition = &condition{}
}
if m.condition.AttrsOr == nil {
m.condition.AttrsOr = make(map[string]interface{})
}
for k, v := range attrs {
m.condition.AttrsOr[k] = v
}
}
// SetConditionAttrsAnd 设置属性的与条件(设置会冲掉之前的属性与条件)
func (m *Message) SetConditionAttrsAnd(attrs map[string]interface{}) {
if m.condition != nil && m.condition.AttrsAnd != nil {
m.condition.AttrsAnd = make(map[string]interface{})
}
m.AddConditionAttrsAnd(attrs)
}
// AddConditionAttrsAnd 添加属性的与条件(添加会累加之前的属性与条件)
func (m *Message) AddConditionAttrsAnd(attrs map[string]interface{}) {
if m.condition == nil {
m.condition = &condition{}
}
if m.condition.AttrsAnd == nil {
m.condition.AttrsAnd = make(map[string]interface{})
}
for k, v := range attrs {
m.condition.AttrsAnd[k] = v
}
}
// GetCondition 获取推送条件
func (m *Message) GetCondition() *condition {
return m.condition
}
// checkError 检测错误
func (m *Message) checkError() (err error) {
if err = m.CheckLifeTimeArgError(); err != nil {
return
}
if err = m.CheckBodyArgError(); err != nil {
return
}
if err = m.checkConditionArgError(); err != nil {
return
}
return
}
// checkConditionArgError 检测条件参数错误
func (m *Message) checkConditionArgError() error {
hasAttrs, hasTags := false, false
if m.condition != nil {
if m.condition.AttrsAnd != nil || m.condition.AttrsOr != nil {
hasAttrs = true
}
if m.condition.TagsAnd != nil || m.condition.TagsOr != nil {
hasTags = true
}
}
if hasAttrs && hasTags {
return errInvalidPushCondition
}
return nil
}

126
push/types.go Normal file
View File

@@ -0,0 +1,126 @@
/**
* @Author: Echo
* @Author:1711788888@qq.com
* @Date: 2021/5/29 17:39
* @Desc: Push Api Request And Response Type Definition.
*/
package push
import "git.echol.cn/loser/tencent-im/internal/types"
type (
// 推送条件
condition struct {
TagsAnd []string `json:"TagsAnd"` // 选填标签条件的交集。标签是一个不超过50字节的字符串。注意属性推送和标签推送不可同时作为推送条件。TagsAnd 条件中的标签个数不能超过10个
TagsOr []string `json:"TagsOr"` // 选填标签条件的并集。标签是一个不超过50字节的字符串。注意属性推送和标签推送不可同时作为推送条件。TagsOr 条件中的标签个数不能超过10个
AttrsAnd map[string]interface{} `json:"AttrsAnd"` // (选填)属性条件的交集。注意属性推送和标签推送不可同时作为推送条件
AttrsOr map[string]interface{} `json:"AttrsOr"` // (选填)属性条件的并集。注意属性推送和标签推送不可同时作为推送条件
}
// 推送(请求)
pushMessageReq struct {
FromUserId string `json:"From_Account,omitempty"` // (选填)消息推送方帐号
Condition *condition `json:"Condition,omitempty"` // (选填)推送条件
MsgRandom uint32 `json:"MsgRandom"` // (必填)消息随机数,由随机函数产生
MsgBody []*types.MsgBody `json:"MsgBody"` // (必填)消息内容
MsgLifeTime int `json:"MsgLifeTime,omitempty"` // 选填消息离线存储时间单位秒最多保存7天604800秒。默认为0表示不离线存储
OfflinePushInfo *types.OfflinePushInfo `json:"OfflinePushInfo,omitempty"` // (选填)离线推送信息配置
}
// 推送(响应)
pushMessageResp struct {
types.ActionBaseResp
TaskId string `json:"TaskId"` // 推送任务ID
}
// 设置应用属性名称(请求)
setAttrNamesReq struct {
AttrNames map[string]string `json:"AttrNames"` // (必填)属性名
}
// 获取应用属性名称(请求)
getAttrNamesReq struct {
}
// 获取应用属性名称(响应)
getAttrNamesResp struct {
types.ActionBaseResp
AttrNames map[string]string `json:"AttrNames"` // 属性名
}
// 获取用户属性(请求)
getUserAttrsReq struct {
UserIds []string `json:"To_Account"` // (必填)目标用户帐号列表
}
// 获取用户属性(响应)
getUserAttrsResp struct {
types.ActionBaseResp
Attrs []*userAttrItem `json:"Attrs"`
}
// 用户属性
userAttrItem struct {
UserId string `json:"To_Account"` // 用户UserId
Attrs map[string]interface{} `json:"Attrs"` // 用户属性
}
// 设置用户属性(请求)
setUserAttrsReq struct {
Attrs []*userAttrItem `json:"Attrs"` // (必填)用户属性
}
// 删除用户属性(请求)
deleteUserAttrsReq struct {
Attrs []deleteUserAttr `json:"Attrs"` // (必填)用户属性
}
// 删除的用户属性
deleteUserAttr struct {
UserId string `json:"To_Account"` // 用户UserId
Attrs []string `json:"Attrs"` // 用户属性
}
// 获取用户标签(请求)
getUserTagsReq struct {
UserIds []string `json:"To_Account"` // (必填)目标用户帐号列表
}
// 获取用户标签(响应)
getUserTagsResp struct {
types.ActionBaseResp
Tags []userTag `json:"Tags"` // 用户标签内容列表
}
// 用户标签
userTag struct {
UserId string `json:"To_Account"`
Tags []string `json:"Tags"`
}
// 添加用户标签(请求)
addUserTagsReq struct {
Tags []*userTag `json:"Tags"` // (必填)用户标签内容列表
}
// 删除用户标签(请求)
deleteUserTagsReq struct {
Tags []*userTag `json:"Tags"` // (必填)用户标签内容列表
}
// 删除用户所有标签(请求)
deleteUserAllTagsReq struct {
UserIds []string `json:"To_Account"`
}
ImageInfo = types.ImageInfo
MsgTextContent = types.MsgTextContent
MsgFaceContent = types.MsgFaceContent
MsgFileContent = types.MsgFileContent
MsgImageContent = types.MsgImageContent
MsgSoundContent = types.MsgSoundContent
MsgVideoContent = types.MsgVideoContent
MsgCustomContent = types.MsgCustomContent
MsgLocationContent = types.MsgLocationContent
)