You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tencent-im/group/api.go

1316 lines
43 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* @Author: Echo
* @Author:1711788888@qq.com
* @Date: 2021/5/27 20:46
* @Desc: Group Api Implementation.
*/
package group
import (
"fmt"
"git.echol.cn/loser/tencent-im/internal/conv"
"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 (
serviceGroup = "group_open_http_svc"
commandFetchGroupIds = "get_appid_group_list"
commandCreateGroup = "create_group"
commandDestroyGroup = "destroy_group"
commandGetGroups = "get_group_info"
commandFetchGroupMembers = "get_group_member_info"
commandUpdateGroup = "modify_group_base_info"
commandAddGroupMembers = "add_group_member"
commandDeleteGroupMember = "delete_group_member"
commandModifyGroupMemberInfo = "modify_group_member_info"
commandFetchMemberGroups = "get_joined_group_list"
commandGetRoleInGroup = "get_role_in_group"
commandForbidSendMsg = "forbid_send_msg"
commandGetGroupShuttedUin = "get_group_shutted_uin"
commandSendGroupMsg = "send_group_msg"
commandSendGroupSystemNotification = "send_group_system_notification"
commandChangeGroupOwner = "change_group_owner"
commandRecallGroupMsg = "group_msg_recall"
commandImportGroup = "import_group"
commandImportGroupMsg = "import_group_msg"
commandImportGroupMember = "import_group_member"
commandSetUnreadMsgNum = "set_unread_msg_num"
commandDeleteGroupMsgBySender = "delete_group_msg_by_sender"
commandGetGroupSimpleMsg = "group_msg_get_simple"
commandGetOnlineMemberNum = "get_online_member_num"
batchGetGroupsLimit = 50 // 批量获取群组限制
)
type API interface {
// FetchGroupIds 拉取App中的所有群组ID
// App 管理员可以通过该接口获取App中所有群组的ID。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1614
FetchGroupIds(limit int, next int, groupType ...Type) (ret *FetchGroupIdsRet, err error)
// FetchGroups 拉取App中的所有群组
// 本方法由“拉取App中的所有群组IDFetchGroupIds”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1614
FetchGroups(limit int, next int, groupTypeAndFilter ...interface{}) (ret *FetchGroupsRet, err error)
// PullGroups 续拉取App中的所有群组
// 本方法由“拉取App中的所有群组FetchGroups”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1614
PullGroups(arg *PullGroupsArg, fn func(ret *FetchGroupsRet)) (err error)
// CreateGroup 创建群组
// App 管理员可以通过该接口创建群组。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1615
CreateGroup(group *Group) (groupId string, err error)
// GetGroup 获取单个群详细资料
// 本方法由“获取多个群详细资料GetGroups”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1616
GetGroup(groupId string, filter ...*Filter) (group *Group, err error)
// GetGroups 获取多个群详细资料
// App 管理员可以根据群组 ID 获取群组的详细信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1616
GetGroups(groupIds []string, filter ...*Filter) (groups []*Group, err error)
// FetchMembers 拉取群成员详细资料
// App管理员可以根据群组ID获取群组成员的资料。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1617
FetchMembers(groupId string, limit, offset int, filter ...*Filter) (ret *FetchMembersRet, err error)
// PullMembers 续拉取群成员详细资料
// 本方法由“拉取群成员详细资料FetchMembers”拓展而来
// App管理员可以根据群组ID获取群组成员的资料。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1617
PullMembers(arg *PullMembersArg, fn func(ret *FetchMembersRet)) (err error)
// UpdateGroup 修改群基础资料
// App管理员可以通过该接口修改指定群组的基础信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1620
UpdateGroup(group *Group) (err error)
// AddMembers 增加群成员
// App管理员可以通过该接口向指定的群中添加新成员。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1621
AddMembers(groupId string, userIds []string, silence ...bool) (results []AddMembersResult, err error)
// DeleteMembers 删除群成员
// App管理员可以通过该接口删除群成员。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1622
DeleteMembers(groupId string, userIds []string, reasonAndSilence ...interface{}) (err error)
// UpdateMember 修改群成员资料
// App管理员可以通过该接口修改群成员资料。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1623
UpdateMember(groupId string, member *Member) (err error)
// DestroyGroup 解散群组
// App管理员通过该接口解散群。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1624
DestroyGroup(groupId string) (err error)
// FetchMemberGroups 拉取用户所加入的群组
// App管理员可以通过本接口获取某一用户加入的群信息。默认不获取用户已加入但未激活好友工作群Work以及直播群AVChatRoom群信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1625
FetchMemberGroups(arg *FetchMemberGroupsArg) (ret *FetchMemberGroupsRet, err error)
// PullMemberGroups 续拉取用户所加入的群组
// 本方法由“拉取用户所加入的群组FetchMemberGroups”拓展而来
// App管理员可以通过本接口获取某一用户加入的群信息。默认不获取用户已加入但未激活好友工作群Work以及直播群AVChatRoom群信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1625
PullMemberGroups(arg *PullMemberGroupsArg, fn func(ret *FetchMemberGroupsRet)) (err error)
// GetRolesInGroup 查询用户在群组中的身份
// App管理员可以通过该接口获取一批用户在群内的身份即“成员角色”。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1626
GetRolesInGroup(groupId string, userIds []string) (memberRoles map[string]string, err error)
// ForbidSendMessage 批量禁言
// App 管理员禁止指定群组中某些用户在一段时间内发言。
// App 管理员取消对某些用户的禁言。
// 被禁言用户退出群组之后再进入同一群组,禁言仍然有效。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1627
ForbidSendMessage(groupId string, userIds []string, shutUpTime int64) (err error)
// AllowSendMessage 取消禁言
// 本方法由“批量禁言ForbidSendMessage”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1627
AllowSendMessage(groupId string, userIds []string) (err error)
// GetShuttedUpMembers 获取被禁言群成员列表
// App管理员可以根据群组ID获取群组中被禁言的用户列表。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2925
GetShuttedUpMembers(groupId string) (shuttedUps map[string]int64, err error)
// SendMessage 在群组中发送普通消息
// App管理员可以通过该接口在群组中发送普通消息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1629
SendMessage(groupId string, message *Message) (ret *SendMessageRet, err error)
// SendNotification 在群组中发送系统通知
// App 管理员可以通过该接口在群组中发送系统通知。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1630
SendNotification(groupId, content string, userId ...string) (err error)
// ChangeGroupOwner 转让群主
// App 管理员可以通过该接口将群主身份转移给他人。
// 没有群主的群App 管理员可以通过此接口指定他人作为群主。
// 新群主必须为群内成员。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1633
ChangeGroupOwner(groupId, userId string) (err error)
// RevokeMessage 撤回单条群消息
// 本方法由“撤回多条群消息RevokeMessages”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/12341
RevokeMessage(groupId string, msgSeq int) (err error)
// RevokeMessages 撤回多条群消息
// App 管理员通过该接口撤回指定群组的消息,消息需要在漫游有效期以内。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/12341
RevokeMessages(groupId string, msgSeq ...int) (results map[int]int, err error)
// ImportGroup 导入群基础资料
// App 管理员可以通过该接口导入群组,不会触发回调、不会下发通知;当 App 需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议导入存量群组数据。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1634
ImportGroup(group *Group) (groupId string, err error)
// ImportMessages 导入群消息
// 该 API 接口的作用是导入群组的消息,不会触发回调、不会下发通知。
// 当 App 需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议导入存量群消息数据。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1635
ImportMessages(groupId string, messages ...*Message) (results []ImportMessagesResult, err error)
// ImportMembers 导入多个群成员
// 该 API 接口的作用是导入群组成员,不会触发回调、不会下发通知。
// 当 App 需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议导入存量群成员数据。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1636
ImportMembers(groupId string, members ...*Member) (results []ImportMemberResult, err error)
// SetMemberUnreadMsgNum 设置成员未读消息计数
// App管理员使用该接口设置群组成员未读消息数不会触发回调、不会下发通知。
// 当App需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议设置群成员的未读消息计数。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1637
SetMemberUnreadMsgNum(groupId, userId string, unreadMsgNum int) (err error)
// RevokeMemberMessages 撤回指定用户发送的消息
// 该API接口的作用是撤回最近1000条消息中指定用户发送的消息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2359
RevokeMemberMessages(groupId, userId string) (err error)
// FetchMessages 拉取群历史消息
// 即时通信 IM 的群消息是按 Seq 排序的,按照 server 收到群消息的顺序分配 Seq先发的群消息 Seq 小,后发的 Seq 大。
// 如果用户想拉取一个群的全量消息,首次拉取时不用填拉取 SeqServer 会自动返回最新的消息,以后拉取时拉取 Seq 填上次返回的最小 Seq 减1。
// 如果返回消息的 IsPlaceMsg 为1表示这个 Seq 的消息或者过期、或者存储失败、或者被删除了。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2738
FetchMessages(groupId string, limit int, msgSeq ...int) (ret *FetchMessagesRet, err error)
// PullMessages 续拉取群历史消息
// 本方法由“拉取群历史消息FetchMessages”拓展而来
// 即时通信 IM 的群消息是按 Seq 排序的,按照 server 收到群消息的顺序分配 Seq先发的群消息 Seq 小,后发的 Seq 大。
// 如果用户想拉取一个群的全量消息,首次拉取时不用填拉取 SeqServer 会自动返回最新的消息,以后拉取时拉取 Seq 填上次返回的最小 Seq 减1。
// 如果返回消息的 IsPlaceMsg 为1表示这个 Seq 的消息或者过期、或者存储失败、或者被删除了。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2738
PullMessages(groupId string, limit int, fn func(ret *FetchMessagesRet)) (err error)
// GetOnlineMemberNum 获取直播群在线人数
// App 管理员可以根据群组 ID 获取直播群在线人数。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/49180
GetOnlineMemberNum(groupId string) (num int, err error)
}
type api struct {
client core.Client
}
func NewAPI(client core.Client) API {
return &api{client: client}
}
// FetchGroupIds 拉取App中的所有群组ID
// App 管理员可以通过该接口获取App中所有群组的ID。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1614
func (a *api) FetchGroupIds(limit int, next int, groupType ...Type) (ret *FetchGroupIdsRet, err error) {
req := &fetchGroupIdsReq{Limit: limit, Next: next}
if len(groupType) > 0 {
req.Type = string(groupType[0])
}
resp := &fetchGroupIdsResp{}
if err = a.client.Post(serviceGroup, commandFetchGroupIds, req, resp); err != nil {
return
}
ret = &FetchGroupIdsRet{}
ret.Next = resp.Next
ret.Total = resp.TotalCount
ret.HasMore = ret.Next != 0
ret.List = make([]string, 0, len(resp.GroupIdList))
for _, item := range resp.GroupIdList {
ret.List = append(ret.List, item.GroupId)
}
return
}
// FetchGroups 拉取App中的所有群组
// 本方法由“拉取App中的所有群组IDFetchGroupIds”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1614
func (a *api) FetchGroups(limit int, next int, groupTypeAndFilter ...interface{}) (ret *FetchGroupsRet, err error) {
if limit > batchGetGroupsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of groups id cannot exceed %d", batchGetGroupsLimit))
return
}
var (
resp *FetchGroupIdsRet
filter *Filter
groupType Type
)
if len(groupTypeAndFilter) > 0 {
for i, val := range groupTypeAndFilter {
if i > 1 {
break
}
switch v := val.(type) {
case Type:
groupType = v
case *Filter:
filter = v
}
}
}
if resp, err = a.FetchGroupIds(limit, next, groupType); err != nil {
return
}
ret = &FetchGroupsRet{Next: resp.Next, Total: resp.Total, HasMore: resp.HasMore}
if len(resp.List) > 0 {
if ret.List, err = a.GetGroups(resp.List, filter); err != nil {
return
}
}
return
}
// PullGroups 续拉取App中的所有群组
// 本方法由“拉取App中的所有群组FetchGroups”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1614
func (a *api) PullGroups(arg *PullGroupsArg, fn func(ret *FetchGroupsRet)) (err error) {
var (
limit = arg.Limit
groupType = arg.Type
filter = arg.Filter
next int
ret *FetchGroupsRet
)
for ret == nil || ret.HasMore {
ret, err = a.FetchGroups(limit, next, groupType, filter)
if err != nil {
return
}
fn(ret)
if ret.HasMore {
next = ret.Next
break
}
}
return
}
// CreateGroup 创建群组
// App管理员可以通过该接口创建群组。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1615
func (a *api) CreateGroup(group *Group) (groupId string, err error) {
if err = group.checkCreateError(); err != nil {
return
}
req := &createGroupReq{}
req.GroupId = group.id
req.OwnerUserId = group.owner
req.Type = group.groupType
req.Name = group.name
req.FaceUrl = group.avatar
req.Introduction = group.introduction
req.Notification = group.notification
req.MaxMemberNum = group.maxMemberNum
req.ApplyJoinOption = group.applyJoinOption
if data := group.GetAllCustomData(); data != nil {
req.AppDefinedData = make([]*customDataItem, 0, len(data))
for key, val := range data {
req.AppDefinedData = append(req.AppDefinedData, &customDataItem{
Key: key,
Value: val,
})
}
}
if c := len(group.members); c > 0 {
req.MemberList = make([]*memberItem, 0, c)
var item *memberItem
for _, member := range group.members {
if err = member.checkError(); err != nil {
return
}
item = &memberItem{
UserId: member.userId,
Role: member.role,
JoinTime: member.joinTime,
NameCard: member.nameCard,
AppMemberDefinedData: make([]*customDataItem, 0, len(member.GetAllCustomData())),
}
for k, v := range member.GetAllCustomData() {
item.AppMemberDefinedData = append(item.AppMemberDefinedData, &customDataItem{
Key: k,
Value: v,
})
}
req.MemberList = append(req.MemberList, item)
}
}
resp := &createGroupResp{}
if err = a.client.Post(serviceGroup, commandCreateGroup, req, resp); err != nil {
return
} else {
groupId = resp.GroupId
}
return
}
// GetGroup 获取单个群详细资料
// 本方法由“获取多个群详细资料GetGroups”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1616
func (a *api) GetGroup(groupId string, filter ...*Filter) (group *Group, err error) {
var groups []*Group
if groups, err = a.GetGroups([]string{groupId}, filter...); err != nil {
return
}
if len(groups) > 0 {
if err = groups[0].err; err != nil {
return
}
group = groups[0]
}
return
}
// GetGroups 获取多个群详细资料
// App 管理员可以根据群组 ID 获取群组的详细信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1616
func (a *api) GetGroups(groupIds []string, filters ...*Filter) (groups []*Group, err error) {
if c := len(groupIds); c == 0 {
err = core.NewError(enum.InvalidParamsCode, "the group's id is not set")
return
} else if c > batchGetGroupsLimit {
err = core.NewError(enum.InvalidParamsCode, fmt.Sprintf("the number of group's id cannot exceed %d", batchGetGroupsLimit))
return
}
req := &getGroupsReq{GroupIds: groupIds}
resp := &getGroupsResp{}
if len(filters) > 0 {
if filter := filters[0]; filter != nil {
req.ResponseFilter = &responseFilter{
GroupBaseInfoFilter: filter.GetAllBaseInfoFilterFields(),
MemberInfoFilter: filter.GetAllMemberInfoFilterFields(),
GroupCustomDataFilter: filter.GetAllGroupCustomDataFilterFields(),
MemberCustomDataFilter: filter.GetAllMemberCustomDataFilterFields(),
}
}
}
if err = a.client.Post(serviceGroup, commandGetGroups, req, resp); err != nil {
return
}
groups = make([]*Group, 0, len(resp.GroupInfos))
for _, item := range resp.GroupInfos {
group := NewGroup()
group.setError(item.ErrorCode, item.ErrorInfo)
if group.err == nil {
group.id = item.GroupId
group.name = item.Name
group.groupType = item.Type
group.owner = item.OwnerUserId
group.avatar = item.FaceUrl
group.memberNum = item.MemberNum
group.maxMemberNum = item.MaxMemberNum
group.applyJoinOption = item.ApplyJoinOption
group.createTime = item.CreateTime
group.lastInfoTime = item.LastInfoTime
group.lastMsgTime = item.LastMsgTime
group.shutUpStatus = item.ShutUpAllMember
group.nextMsgSeq = item.NextMsgSeq
if item.AppDefinedData != nil && len(item.AppDefinedData) > 0 {
for _, v := range item.AppDefinedData {
group.SetCustomData(v.Key, v.Value)
}
}
if item.MemberList != nil && len(item.MemberList) > 0 {
for _, m := range item.MemberList {
member := &Member{
userId: m.UserId,
role: m.Role,
joinTime: m.JoinTime,
nameCard: m.NameCard,
msgSeq: m.MsgSeq,
msgFlag: MsgFlag(m.MsgFlag),
lastSendMsgTime: m.LastSendMsgTime,
}
if m.AppMemberDefinedData != nil && len(m.AppMemberDefinedData) > 0 {
for _, v := range m.AppMemberDefinedData {
member.SetCustomData(v.Key, v.Value)
}
}
group.AddMembers(member)
}
}
groups = append(groups, group)
}
}
return
}
// FetchMembers 拉取群成员详细资料
// App管理员可以根据群组ID获取群组成员的资料。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1617
func (a *api) FetchMembers(groupId string, limit, offset int, filters ...*Filter) (ret *FetchMembersRet, err error) {
req := &fetchMembersReq{GroupId: groupId, Limit: limit, Offset: offset}
if len(filters) > 0 {
if filter := filters[0]; filter != nil {
req.MemberInfoFilter = filter.GetAllMemberInfoFilterFields()
req.MemberRoleFilter = filter.GetAllMemberRoleFilterValues()
req.MemberCustomDataFilter = filter.GetAllMemberCustomDataFilterFields()
}
}
resp := &fetchMembersResp{}
if err = a.client.Post(serviceGroup, commandFetchGroupMembers, req, resp); err != nil {
return
}
ret = &FetchMembersRet{}
ret.Total = resp.MemberNum
ret.List = make([]*Member, 0, len(resp.MemberList))
ret.HasMore = resp.MemberNum > limit+offset
for _, m := range resp.MemberList {
member := &Member{
userId: m.UserId,
role: m.Role,
joinTime: m.JoinTime,
nameCard: m.NameCard,
msgSeq: m.MsgSeq,
msgFlag: MsgFlag(m.MsgFlag),
lastSendMsgTime: m.LastSendMsgTime,
}
if m.AppMemberDefinedData != nil && len(m.AppMemberDefinedData) > 0 {
for _, v := range m.AppMemberDefinedData {
member.SetCustomData(v.Key, v.Value)
}
}
ret.List = append(ret.List, member)
}
return
}
// PullMembers 续拉取群成员详细资料
// 本方法由“拉取群成员详细资料FetchMembers”拓展而来
// App管理员可以根据群组ID获取群组成员的资料。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1617
func (a *api) PullMembers(arg *PullMembersArg, fn func(ret *FetchMembersRet)) (err error) {
var (
offset int
ret *FetchMembersRet
)
for ret == nil || ret.HasMore {
ret, err = a.FetchMembers(arg.GroupId, arg.Limit, offset, arg.Filter)
if err != nil {
return
}
fn(ret)
if ret.HasMore {
offset += arg.Limit
}
}
return
}
// UpdateGroup 修改群基础资料
// App管理员可以通过该接口修改指定群组的基础信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1620
func (a *api) UpdateGroup(group *Group) (err error) {
if err = group.checkUpdateError(); err != nil {
return
}
req := &updateGroupReq{}
req.GroupId = group.id
req.Name = group.name
req.FaceUrl = group.avatar
req.Introduction = group.introduction
req.Notification = group.notification
req.MaxMemberNum = group.maxMemberNum
req.ApplyJoinOption = group.applyJoinOption
req.ShutUpAllMember = group.shutUpStatus
if data := group.GetAllCustomData(); data != nil {
req.AppDefinedData = make([]customDataItem, 0, len(data))
for key, val := range data {
req.AppDefinedData = append(req.AppDefinedData, customDataItem{
Key: key,
Value: val,
})
}
}
if err = a.client.Post(serviceGroup, commandUpdateGroup, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// AddMembers 增加群成员
// App管理员可以通过该接口向指定的群中添加新成员。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1621
func (a *api) AddMembers(groupId string, userIds []string, silence ...bool) (results []AddMembersResult, err error) {
req := &addMembersReq{}
req.GroupId = groupId
req.MemberList = make([]addMemberItem, 0, len(userIds))
for _, userId := range userIds {
req.MemberList = append(req.MemberList, addMemberItem{
UserId: userId,
})
}
if len(silence) > 0 && silence[0] {
req.Silence = 1
}
resp := &addMembersResp{}
if err = a.client.Post(serviceGroup, commandAddGroupMembers, req, resp); err != nil {
return
}
results = resp.MemberList
return
}
// DeleteMembers 删除群成员
// App管理员可以通过该接口删除群成员。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1622
func (a *api) DeleteMembers(groupId string, userIds []string, reasonAndSilence ...interface{}) (err error) {
req := &deleteMembersReq{}
req.GroupId = groupId
req.UserIds = userIds
if len(reasonAndSilence) > 0 {
for i, val := range reasonAndSilence {
if i > 1 {
break
}
switch v := val.(type) {
case string:
req.Reason = v
case bool:
if v {
req.Silence = 1
}
}
}
}
if err = a.client.Post(serviceGroup, commandDeleteGroupMember, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// UpdateMember 修改群成员资料
// App管理员可以通过该接口修改群成员资料。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1623
func (a *api) UpdateMember(groupId string, member *Member) (err error) {
if err = member.checkError(); err != nil {
return
}
req := &updateMemberReq{}
req.GroupId = groupId
req.UserId = member.userId
req.Role = member.role
req.MsgFlag = string(member.msgFlag)
req.NameCard = member.nameCard
req.ShutUpUntil = member.shutUpUntil
if data := member.GetAllCustomData(); data != nil {
req.AppMemberDefinedData = make([]customDataItem, 0, len(data))
for key, val := range data {
req.AppMemberDefinedData = append(req.AppMemberDefinedData, customDataItem{
Key: key,
Value: val,
})
}
}
if err = a.client.Post(serviceGroup, commandModifyGroupMemberInfo, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// DestroyGroup 解散群组
// App管理员通过该接口解散群。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1624
func (a *api) DestroyGroup(groupId string) (err error) {
req := &destroyGroupReq{GroupId: groupId}
if err = a.client.Post(serviceGroup, commandDestroyGroup, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// FetchMemberGroups 拉取用户所加入的群组
// App管理员可以通过本接口获取某一用户加入的群信息。默认不获取用户已加入但未激活好友工作群Work以及直播群AVChatRoom群信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1625
func (a *api) FetchMemberGroups(arg *FetchMemberGroupsArg) (ret *FetchMemberGroupsRet, err error) {
req := &fetchMemberGroupsReq{UserId: arg.UserId, Limit: arg.Limit, Offset: arg.Offset, Type: arg.Type}
if arg.Filter != nil {
req.ResponseFilter = &responseFilter{
GroupBaseInfoFilter: arg.Filter.GetAllBaseInfoFilterFields(),
SelfInfoFilter: arg.Filter.GetAllMemberInfoFilterFields(),
}
}
if arg.IsWithNoActiveGroups {
req.WithNoActiveGroups = 1
}
if arg.IsWithLiveRoomGroups {
req.WithHugeGroups = 1
}
resp := &fetchMemberGroupsResp{}
if err = a.client.Post(serviceGroup, commandFetchMemberGroups, req, resp); err != nil {
return
}
ret = &FetchMemberGroupsRet{}
ret.Total = resp.TotalCount
ret.List = make([]*Group, 0, len(resp.GroupList))
if arg.Limit == 0 {
ret.HasMore = false
} else {
ret.HasMore = arg.Limit+arg.Offset < resp.TotalCount
}
for _, item := range resp.GroupList {
group := NewGroup()
group.id = item.GroupId
group.name = item.Name
group.groupType = item.Type
group.owner = item.OwnerUserId
group.avatar = item.FaceUrl
group.memberNum = item.MemberNum
group.maxMemberNum = item.MaxMemberNum
group.applyJoinOption = item.ApplyJoinOption
group.createTime = item.CreateTime
group.lastInfoTime = item.LastInfoTime
group.lastMsgTime = item.LastMsgTime
group.shutUpStatus = item.ShutUpAllMember
group.nextMsgSeq = item.NextMsgSeq
if item.AppDefinedData != nil && len(item.AppDefinedData) > 0 {
for _, v := range item.AppDefinedData {
group.SetCustomData(v.Key, v.Value)
}
}
if item.MemberInfo != nil {
member := &Member{
userId: arg.UserId,
role: item.MemberInfo.Role,
joinTime: item.MemberInfo.JoinTime,
nameCard: item.MemberInfo.NameCard,
msgSeq: item.MemberInfo.MsgSeq,
msgFlag: MsgFlag(item.MemberInfo.MsgFlag),
lastSendMsgTime: item.MemberInfo.LastSendMsgTime,
}
if item.MemberInfo.AppMemberDefinedData != nil && len(item.MemberInfo.AppMemberDefinedData) > 0 {
for _, v := range item.MemberInfo.AppMemberDefinedData {
member.SetCustomData(v.Key, v.Value)
}
}
group.AddMembers(member)
}
ret.List = append(ret.List, group)
}
return
}
// PullMemberGroups 续拉取用户所加入的群组
// 本方法由“拉取用户所加入的群组FetchMemberGroups”拓展而来
// App管理员可以通过本接口获取某一用户加入的群信息。默认不获取用户已加入但未激活好友工作群Work以及直播群AVChatRoom群信息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1625
func (a *api) PullMemberGroups(arg *PullMemberGroupsArg, fn func(ret *FetchMemberGroupsRet)) (err error) {
var (
ret *FetchMemberGroupsRet
req = &FetchMemberGroupsArg{
UserId: arg.UserId,
Limit: arg.Limit,
Type: arg.Type,
Filter: arg.Filter,
IsWithNoActiveGroups: arg.IsWithNoActiveGroups,
IsWithLiveRoomGroups: arg.IsWithLiveRoomGroups,
}
)
for ret == nil || ret.HasMore {
ret, err = a.FetchMemberGroups(req)
if err != nil {
return
}
fn(ret)
if ret.HasMore {
req.Offset += arg.Limit
}
}
return
}
// GetRolesInGroup 查询用户在群组中的身份
// App管理员可以通过该接口获取一批用户在群内的身份即“成员角色”。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1626
func (a *api) GetRolesInGroup(groupId string, userIds []string) (roles map[string]string, err error) {
req := &getRolesInGroupReq{GroupId: groupId, UserIds: userIds}
resp := &getRolesInGroupResp{}
if err = a.client.Post(serviceGroup, commandGetRoleInGroup, req, resp); err != nil {
return
}
roles = make(map[string]string, len(resp.MemberRoleList))
for _, item := range resp.MemberRoleList {
roles[item.UserId] = item.Role
}
return
}
// ForbidSendMessage 批量禁言
// App 管理员禁止指定群组中某些用户在一段时间内发言。
// App 管理员取消对某些用户的禁言。
// 被禁言用户退出群组之后再进入同一群组,禁言仍然有效。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1627
func (a *api) ForbidSendMessage(groupId string, userIds []string, shutUpTime int64) (err error) {
req := &forbidSendMessageReq{
GroupId: groupId,
UserIds: userIds,
ShutUpTime: shutUpTime,
}
if err = a.client.Post(serviceGroup, commandForbidSendMsg, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// AllowSendMessage 取消禁言
// 本方法由“批量禁言ForbidSendMessage”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1627
func (a *api) AllowSendMessage(groupId string, userIds []string) (err error) {
return a.ForbidSendMessage(groupId, userIds, 0)
}
// GetShuttedUpMembers 获取被禁言群成员列表
// App管理员可以根据群组ID获取群组中被禁言的用户列表。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2925
func (a *api) GetShuttedUpMembers(groupId string) (shuttedUps map[string]int64, err error) {
req := &getShuttedUpMembersReq{GroupId: groupId}
resp := &getShuttedUpMembersResp{}
if err = a.client.Post(serviceGroup, commandGetGroupShuttedUin, req, resp); err != nil {
return
}
shuttedUps = make(map[string]int64)
for _, item := range resp.ShuttedUpList {
shuttedUps[item.UserId] = item.ShuttedUntil
}
return
}
// SendMessage 在群组中发送普通消息
// App管理员可以通过该接口在群组中发送普通消息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1629
func (a *api) SendMessage(groupId string, message *Message) (ret *SendMessageRet, err error) {
if err = message.checkSendError(); err != nil {
return
}
req := &sendMessageReq{}
req.GroupId = groupId
req.FromUserId = message.GetSender()
req.OfflinePushInfo = message.GetOfflinePushInfo()
req.MsgPriority = string(message.GetPriority())
req.MsgBody = message.GetBody()
req.Random = message.GetRandom()
req.CloudCustomData = conv.String(message.GetCustomData())
req.SendMsgControl = message.GetSendMsgControl()
req.ForbidCallbackControl = message.GetForbidCallbackControl()
req.OnlineOnlyFlag = int(message.GetOnlineOnlyFlag())
if message.atMembers != nil && len(message.atMembers) > 0 {
req.GroupAtInfo = make([]atInfo, 0, len(message.atMembers))
for userId, _ := range message.atMembers {
if userId == AtAllMembersFlag {
req.GroupAtInfo = append(req.GroupAtInfo, atInfo{
GroupAtAllFlag: 1,
})
} else {
req.GroupAtInfo = append(req.GroupAtInfo, atInfo{
GroupAtAllFlag: 0,
GroupAtUserId: userId,
})
}
}
}
resp := &sendMessageResp{}
if err = a.client.Post(serviceGroup, commandSendGroupMsg, req, resp); err != nil {
return
} else {
ret = &SendMessageRet{
MsgSeq: resp.MsgSeq,
MsgTime: resp.MsgTime,
}
}
return
}
// SendNotification 在群组中发送系统通知
// App 管理员可以通过该接口在群组中发送系统通知。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1630
func (a *api) SendNotification(groupId, content string, userIds ...string) (err error) {
req := &sendNotificationReq{GroupId: groupId, Content: content, UserIds: userIds}
if err = a.client.Post(serviceGroup, commandSendGroupSystemNotification, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// ChangeGroupOwner 转让群主
// App 管理员可以通过该接口将群主身份转移给他人。
// 没有群主的群App 管理员可以通过此接口指定他人作为群主。
// 新群主必须为群内成员。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1633
func (a *api) ChangeGroupOwner(groupId, userId string) (err error) {
req := &changeGroupOwnerReq{GroupId: groupId, OwnerUserId: userId}
if err = a.client.Post(serviceGroup, commandChangeGroupOwner, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// RevokeMessage 撤回单条群消息
// 本方法由“撤回多条群消息RevokeMessages”拓展而来
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/12341
func (a *api) RevokeMessage(groupId string, msgSeq int) (err error) {
var results map[int]int
if results, err = a.RevokeMessages(groupId, msgSeq); err != nil {
return
}
if results[msgSeq] != enum.SuccessCode {
err = core.NewError(results[msgSeq], "message revoke failed")
return
}
return
}
// RevokeMessages 撤回多条群消息
// App 管理员通过该接口撤回指定群组的消息,消息需要在漫游有效期以内。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/12341
func (a *api) RevokeMessages(groupId string, msgSeq ...int) (results map[int]int, err error) {
req := revokeMessagesReq{}
req.GroupId = groupId
req.MsgSeqList = make([]msgSeqItem, 0, len(msgSeq))
for _, seq := range msgSeq {
req.MsgSeqList = append(req.MsgSeqList, msgSeqItem{
MsgSeq: seq,
})
}
resp := &revokeMessagesResp{}
if err = a.client.Post(serviceGroup, commandRecallGroupMsg, req, resp); err != nil {
return
}
results = make(map[int]int)
for _, item := range resp.Results {
results[item.MsgSeq] = item.RetCode
}
return
}
// ImportGroup 导入群基础资料
// App 管理员可以通过该接口导入群组,不会触发回调、不会下发通知;当 App 需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议导入存量群组数据。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1634
func (a *api) ImportGroup(group *Group) (groupId string, err error) {
if err = group.checkImportError(); err != nil {
return
}
req := &importGroupReq{}
req.GroupId = group.id
req.OwnerUserId = group.owner
req.Type = group.groupType
req.Name = group.name
req.FaceUrl = group.avatar
req.Introduction = group.introduction
req.Notification = group.notification
req.MaxMemberNum = group.maxMemberNum
req.ApplyJoinOption = group.applyJoinOption
req.CreateTime = group.createTime
if data := group.GetAllCustomData(); data != nil {
req.AppDefinedData = make([]*customDataItem, 0, len(data))
for key, val := range data {
req.AppDefinedData = append(req.AppDefinedData, &customDataItem{
Key: key,
Value: val,
})
}
}
resp := &importGroupResp{}
if err = a.client.Post(serviceGroup, commandImportGroup, req, resp); err != nil {
return
} else {
groupId = resp.GroupId
}
return
}
// ImportMessages 导入群消息
// 该 API 接口的作用是导入群组的消息,不会触发回调、不会下发通知。
// 当 App 需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议导入存量群消息数据。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1635
func (a *api) ImportMessages(groupId string, messages ...*Message) (results []ImportMessagesResult, err error) {
req := &importMessagesReq{GroupId: groupId, Messages: make([]messageItem, 0, len(messages))}
for _, message := range messages {
if err = message.checkImportError(); err != nil {
return
}
req.Messages = append(req.Messages, messageItem{
FromUserId: message.GetSender(),
MsgBody: message.GetBody(),
SendTime: message.GetSendTime(),
Random: message.GetRandom(),
})
}
resp := &importMessagesResp{}
if err = a.client.Post(serviceGroup, commandImportGroupMsg, req, resp); err != nil {
return
}
results = resp.Results
return
}
// ImportMembers 导入多个群成员
// 该 API 接口的作用是导入群组成员,不会触发回调、不会下发通知。
// 当 App 需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议导入存量群成员数据。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1636
func (a *api) ImportMembers(groupId string, members ...*Member) (results []ImportMemberResult, err error) {
req := &importMembersReq{GroupId: groupId, Members: make([]*memberItem, 0, len(members))}
resp := &importMembersResp{}
for _, member := range members {
req.Members = append(req.Members, &memberItem{
UserId: member.userId,
Role: member.role,
JoinTime: member.joinTime,
UnreadMsgNum: member.unreadMsgNum,
})
}
if err = a.client.Post(serviceGroup, commandImportGroupMember, req, resp); err != nil {
return
}
results = resp.Results
return
}
// SetMemberUnreadMsgNum 设置成员未读消息计数
// App管理员使用该接口设置群组成员未读消息数不会触发回调、不会下发通知。
// 当App需要从其他即时通信系统迁移到即时通信 IM 时,使用该协议设置群成员的未读消息计数。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/1637
func (a *api) SetMemberUnreadMsgNum(groupId, userId string, unreadMsgNum int) (err error) {
req := &setMemberUnreadMsgNumReq{GroupId: groupId, UserId: userId, UnreadMsgNum: unreadMsgNum}
if err = a.client.Post(serviceGroup, commandSetUnreadMsgNum, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// RevokeMemberMessages 撤回指定用户发送的消息
// 该API接口的作用是撤回最近1000条消息中指定用户发送的消息。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2359
func (a *api) RevokeMemberMessages(groupId, userId string) (err error) {
req := &revokeMemberMessagesReq{GroupId: groupId, UserId: userId}
if err = a.client.Post(serviceGroup, commandDeleteGroupMsgBySender, req, &types.ActionBaseResp{}); err != nil {
return
}
return
}
// FetchMessages 拉取群历史消息
// 即时通信 IM 的群消息是按 Seq 排序的,按照 server 收到群消息的顺序分配 Seq先发的群消息 Seq 小,后发的 Seq 大。
// 如果用户想拉取一个群的全量消息,首次拉取时不用填拉取 SeqServer 会自动返回最新的消息,以后拉取时拉取 Seq 填上次返回的最小 Seq 减1。
// 如果返回消息的 IsPlaceMsg 为1表示这个 Seq 的消息或者过期、或者存储失败、或者被删除了。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2738
func (a *api) FetchMessages(groupId string, limit int, msgSeq ...int) (ret *FetchMessagesRet, err error) {
req := &fetchMessagesReq{GroupId: groupId, ReqMsgNumber: limit}
if len(msgSeq) > 0 {
req.ReqMsgSeq = msgSeq[0]
}
resp := &fetchMessagesResp{}
if err = a.client.Post(serviceGroup, commandGetGroupSimpleMsg, req, resp); err != nil {
return
}
ret = &FetchMessagesRet{}
ret.IsFinished = resp.IsFinished
if ret.IsFinished == 0 {
ret.HasMore = true
}
if count := len(resp.RspMsgList); count > 0 {
ret.NextSeq = resp.RspMsgList[count-1].MsgSeq - 1
if ret.IsFinished == 1 && count == limit {
ret.HasMore = true
}
}
ret.List = make([]*Message, 0, len(resp.RspMsgList))
for _, item := range resp.RspMsgList {
message := NewMessage()
message.SetSender(item.FromUserId)
message.SetRandom(item.MsgRandom)
message.seq = item.MsgSeq
message.timestamp = item.MsgTimeStamp
message.status = MsgStatus(item.IsPlaceMsg)
switch item.MsgPriority {
case 1:
message.priority = MsgPriorityHigh
case 2:
message.priority = MsgPriorityNormal
case 3:
message.priority = MsgPriorityLow
case 4:
message.priority = MsgPriorityLowest
}
}
return
}
// PullMessages 续拉取群历史消息
// 本方法由“拉取群历史消息FetchMessages”拓展而来
// 即时通信 IM 的群消息是按 Seq 排序的,按照 server 收到群消息的顺序分配 Seq先发的群消息 Seq 小,后发的 Seq 大。
// 如果用户想拉取一个群的全量消息,首次拉取时不用填拉取 SeqServer 会自动返回最新的消息,以后拉取时拉取 Seq 填上次返回的最小 Seq 减1。
// 如果返回消息的 IsPlaceMsg 为1表示这个 Seq 的消息或者过期、或者存储失败、或者被删除了。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/2738
func (a *api) PullMessages(groupId string, limit int, fn func(ret *FetchMessagesRet)) (err error) {
var (
ret *FetchMessagesRet
msgSeq int
)
for ret == nil || ret.HasMore {
ret, err = a.FetchMessages(groupId, limit, msgSeq)
if err != nil {
return
}
fn(ret)
if ret.HasMore {
msgSeq = ret.NextSeq
}
}
return
}
// GetOnlineMemberNum 获取直播群在线人数
// App 管理员可以根据群组 ID 获取直播群在线人数。
// 点击查看详细文档:
// https://cloud.tencent.com/document/product/269/49180
func (a *api) GetOnlineMemberNum(groupId string) (num int, err error) {
req := &getOnlineMemberNumReq{GroupId: groupId}
resp := &getOnlineMemberNumResp{}
if err = a.client.Post(serviceGroup, commandGetOnlineMemberNum, req, resp); err != nil {
return
}
num = resp.OnlineMemberNum
return
}