tencent-im/group/api.go

1316 lines
43 KiB
Go
Raw Normal View History

2022-09-27 11:31:23 +08:00
/**
* @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
}