1046 lines
33 KiB
Go
1046 lines
33 KiB
Go
package Netease
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"strings"
|
||
|
||
"gitea.ddegame.cn/open/servicebase/pkg/common"
|
||
"gitea.ddegame.cn/open/servicebase/pkg/common/HyTools"
|
||
yunxin "gitea.ddegame.cn/open/servicebase/pkg/common/netease/dto"
|
||
"gitea.ddegame.cn/open/servicebase/pkg/htools"
|
||
"gitea.ddegame.cn/open/servicebase/pkg/log"
|
||
|
||
"github.com/pkg/errors"
|
||
"github.com/spf13/cast"
|
||
|
||
"math/rand"
|
||
"strconv"
|
||
"time"
|
||
|
||
"github.com/anxpp/beego/logs"
|
||
"github.com/spf13/viper"
|
||
)
|
||
|
||
type ImClient struct {
|
||
AppKey string
|
||
AppSecret string
|
||
}
|
||
|
||
type CreateImRes struct {
|
||
Code int
|
||
Desc string
|
||
}
|
||
|
||
type BroadcastNotificationReq struct {
|
||
FromAccountId string `json:"from_account_id"`
|
||
Content string `json:"content"`
|
||
TargetOs []string `json:"target_os"`
|
||
}
|
||
|
||
func NewImClient() *ImClient {
|
||
fmt.Printf("NewImClient: %s\n", viper.GetString("netease.im.key"))
|
||
key := viper.GetString("netease.im.key")
|
||
secret := viper.GetString("netease.im.secret")
|
||
return &ImClient{AppKey: key, AppSecret: secret}
|
||
}
|
||
|
||
// 生成云信header
|
||
func (client *ImClient) generateHeader() map[string]string {
|
||
nonce := randNumber()
|
||
t := time.Now()
|
||
currentTime := strconv.FormatInt(t.UTC().Unix(), 10)
|
||
result := make(map[string]string)
|
||
result["AppKey"] = client.AppKey
|
||
result["Nonce"] = nonce
|
||
result["CurTime"] = currentTime
|
||
result["CheckSum"] = client.generateCheckSum(nonce, currentTime)
|
||
result["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8"
|
||
return result
|
||
}
|
||
|
||
func (client *ImClient) generateJsonHeader() map[string]string {
|
||
nonce := randNumber()
|
||
t := time.Now()
|
||
currentTime := strconv.FormatInt(t.UTC().Unix(), 10)
|
||
result := make(map[string]string)
|
||
result["AppKey"] = client.AppKey
|
||
result["Nonce"] = nonce
|
||
result["CurTime"] = currentTime
|
||
result["CheckSum"] = client.generateCheckSum(nonce, currentTime)
|
||
result["Content-Type"] = "application/json"
|
||
return result
|
||
}
|
||
|
||
// 生成云信签名
|
||
func (client *ImClient) generateCheckSum(nonce, currentTime string) string {
|
||
waitSignStr := client.AppSecret + nonce + currentTime
|
||
result := HyTools.StringToSHA1(waitSignStr)
|
||
return result
|
||
}
|
||
|
||
// 创建云信账户
|
||
// imService.CreateImUser(common.SYNC_DATA_USER_ID,"数据同步",common.PHOTO_DOMAIN_URL+"assets/sys/guanfanggonggao.png")
|
||
func (client *ImClient) CreateImUser(userId, nickName, avatar string) error {
|
||
url := "https://api.netease.im/nimserver/user/create.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := HyTools.NewStringBuilder()
|
||
sb.Append("accid=" + userId)
|
||
sb.Append("&")
|
||
sb.Append("token=123456")
|
||
sb.Append("&")
|
||
sb.Append("name=" + nickName)
|
||
sb.Append("&")
|
||
sb.Append("icon=" + avatar)
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
if err != nil {
|
||
// {"desc":"already register","code":414}
|
||
logs.Info("YunXin_SignUp_Fail_AccID_%s:"+err.Error(), userId)
|
||
return err
|
||
} else {
|
||
var resDTO CreateImRes
|
||
json.Unmarshal([]byte(res), &resDTO)
|
||
if resDTO.Code != 200 {
|
||
logs.Info("YunXin_SignUp_Fail_AccID_%s:"+resDTO.Desc, userId)
|
||
} else {
|
||
logs.Info("YunXin_SignUp_Success_AccID_%s:"+res, userId)
|
||
}
|
||
}
|
||
var body map[string]any
|
||
if errJson := json.Unmarshal([]byte(res), &body); errJson != nil {
|
||
return errJson
|
||
}
|
||
if int(body["code"].(float64)) != 200 {
|
||
return errors.New(body["desc"].(string))
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 查询用户信息
|
||
func (client *ImClient) GetImUserInfo(userId string) error {
|
||
url := "https://api.netease.im/nimserver/user/getUinfos.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := HyTools.NewStringBuilder()
|
||
accids := []string{userId}
|
||
byteData, _ := json.Marshal(accids)
|
||
sb.Append("accids=" + string(byteData))
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info("#" + "查询云信用户信息结果:" + res + "#")
|
||
var body map[string]any
|
||
if errJson := json.Unmarshal([]byte(res), &body); errJson != nil {
|
||
return errJson
|
||
}
|
||
if int(body["code"].(float64)) != 200 {
|
||
return errors.New(body["desc"].(string))
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 更新云信信息
|
||
func (client *ImClient) UpdateImUserInfo(accid, nickName, avatar string) error {
|
||
url := "https://api.netease.im/nimserver/user/updateUinfo.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := htools.NewStringBuilder()
|
||
sb.Append("accid=" + accid)
|
||
sb.Append("&")
|
||
sb.Append("name=" + nickName)
|
||
sb.Append("&")
|
||
sb.Append("icon=" + avatar)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信更新用户信息结果:" + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 更新云信用户扩展信息
|
||
func (client *ImClient) UpdateImUserExt(accid, ext string) error {
|
||
url := "https://api.netease.im/nimserver/user/updateUinfo.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := htools.NewStringBuilder()
|
||
sb.Append("accid=" + accid)
|
||
sb.Append("&")
|
||
sb.Append("ex=" + ext)
|
||
logs.Info("update_im_user userID[%s] ext:%s", accid, ext)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING+"云信更新用户ext%s信息结果:"+res+common.LOG_QUOTE_STRING, ext)
|
||
return err
|
||
}
|
||
|
||
// 封禁云信帐号
|
||
func (client *ImClient) BlockImUser(accid string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/user/block.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
sb.Append("accid=" + accid)
|
||
sb.Append("&")
|
||
sb.Append("needkick=true")
|
||
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "封禁云信帐号结果:" + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 解禁云信帐号
|
||
func (client *ImClient) UnBlockImUser(accid string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/user/unblock.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
sb.Append("accid=" + accid)
|
||
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "解禁云信帐号结果:" + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 创建云信聊天室
|
||
func (client *ImClient) CreateChatroom(ownerUserId string, roomName string) (chatroomModel NeteaseChatroomDTO) {
|
||
logs.Info("CreateChatroom ownerUserId=%s roomName=%s", ownerUserId, roomName)
|
||
url := "https://api.netease.im/nimserver/chatroom/create.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := htools.NewStringBuilder()
|
||
sb.Append("creator=" + ownerUserId)
|
||
sb.Append("&")
|
||
sb.Append("name=" + roomName)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
if err != nil {
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信创建聊天室请求失败:" + err.Error() + common.LOG_QUOTE_STRING)
|
||
return
|
||
}
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信创建聊天室结果:" + res + common.LOG_QUOTE_STRING)
|
||
var createRes CreateChatroomResponse
|
||
err1 := json.Unmarshal([]byte(res), &createRes)
|
||
if err1 != nil {
|
||
logs.Info(common.LOG_QUOTE_STRING + "创建聊天室失败,解析结果错误:" + res + common.LOG_QUOTE_STRING)
|
||
panic(err1)
|
||
}
|
||
if createRes.Code != 200 {
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "创建Im聊天室失败:code= " + strconv.Itoa(createRes.Code) + common.LOG_QUOTE_STRING)
|
||
panic(errors.New("创建云信Im聊天室失败"))
|
||
}
|
||
chatroomModel = createRes.Chatroom
|
||
return
|
||
}
|
||
|
||
// IM发送消息
|
||
func (client *ImClient) SendMsg(parameters map[string]string) error {
|
||
url := "https://api.netease.im/nimserver/msg/sendMsg.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发消息结果:" + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 添加机器人
|
||
func (client *ImClient) AddRobot(parameters map[string]string) error {
|
||
url := "https://api.netease.im/nimserver/chatroom/addRobot.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
logs.Info(common.LOG_QUOTE_STRING + "添加机器人:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "添加机器人:" + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 移除机器人
|
||
func (client *ImClient) RemoveRobot(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/removeRobot.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
logs.Info(common.LOG_QUOTE_STRING + "移除机器人:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "移除机器人:" + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 发送聊天室消息
|
||
func (client *ImClient) SendChatroomMsg(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/sendMsg.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室发消息结果:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
return err
|
||
}
|
||
|
||
// 获取在线成员信息
|
||
func (client *ImClient) GetChatroomMembers(parameters map[string]string) (imResponse ImResponse, err error) {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/queryMembers.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
|
||
header := client.generateHeader()
|
||
|
||
body := generateBodyData(parameters)
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "获取在线成员请求:" + body + common.LOG_QUOTE_STRING)
|
||
|
||
res, err1 := htools.HttpDo(httpMethod, url, header, body)
|
||
|
||
if err1 != nil {
|
||
logs.Error(common.LOG_QUOTE_STRING + "获取在线成员失败:" + err1.Error() + common.LOG_QUOTE_STRING)
|
||
err = err1
|
||
return
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "获取在线成员结果:" + res + common.LOG_QUOTE_STRING)
|
||
var response ImResponse
|
||
if err2 := json.Unmarshal([]byte(res), &response); err2 != nil {
|
||
|
||
logs.Error(common.LOG_QUOTE_STRING + "获取在线成员解析失败:" + err2.Error() + common.LOG_QUOTE_STRING)
|
||
err = err2
|
||
return
|
||
}
|
||
|
||
imResponse = response
|
||
|
||
return
|
||
|
||
}
|
||
|
||
// 分页获取聊天室在线用户列表
|
||
func (client *ImClient) GetChatroomOnlineUserListByPage(parameters map[string]string) (imResponse ImResponse, err error) {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/membersByPage.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
|
||
header := client.generateHeader()
|
||
|
||
body := generateBodyData(parameters)
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表:" + body + common.LOG_QUOTE_STRING)
|
||
|
||
res, err1 := htools.HttpDo(httpMethod, url, header, body)
|
||
|
||
if err1 != nil {
|
||
logs.Error(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表失败:" + err1.Error() + common.LOG_QUOTE_STRING)
|
||
err = err1
|
||
return
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表结果:" + res + common.LOG_QUOTE_STRING)
|
||
var response ImResponse
|
||
if err2 := json.Unmarshal([]byte(res), &response); err2 != nil {
|
||
|
||
logs.Error(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表失败:" + err2.Error() + common.LOG_QUOTE_STRING)
|
||
err = err2
|
||
return
|
||
}
|
||
|
||
imResponse = response
|
||
|
||
return
|
||
}
|
||
|
||
// 更新聊天室房间信息
|
||
func (client *ImClient) UpdateRoomInfo(request yunxin.UpdateRoomInfoRequest) (err error) {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/update.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
sb.Append("roomid=" + request.Roomid)
|
||
sb.Append("&")
|
||
sb.Append("name=")
|
||
sb.Append("&")
|
||
sb.Append("announcement=")
|
||
sb.Append("&")
|
||
sb.Append("ext=")
|
||
sb.Append("&")
|
||
sb.Append("notifyExt=" + request.NotifyExt)
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, httpErr := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息结果:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
if httpErr != nil {
|
||
logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息失败:" + httpErr.Error() + common.LOG_QUOTE_STRING)
|
||
err = httpErr
|
||
return
|
||
}
|
||
|
||
resMap := make(map[string]any)
|
||
jsonErr := json.Unmarshal([]byte(res), &resMap)
|
||
|
||
if jsonErr != nil {
|
||
logs.Info(common.LOG_QUOTE_STRING + "解析更新房间信息结果失败:" + jsonErr.Error() + common.LOG_QUOTE_STRING)
|
||
err = jsonErr
|
||
return
|
||
}
|
||
|
||
code := resMap["code"].(float64)
|
||
codeStr := htools.Float64ToString(code)
|
||
if codeStr != "200" {
|
||
logs.Info(common.LOG_QUOTE_STRING + "更新房间信息结果失败: code=" + codeStr + common.LOG_QUOTE_STRING)
|
||
err = errors.New("更新失败 code=" + codeStr)
|
||
return
|
||
}
|
||
|
||
return
|
||
|
||
}
|
||
|
||
// 聊天室临时禁言
|
||
func (client *ImClient) ChatroomMuteUser(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/temporaryMute.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室临时禁言请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室临时禁言结果:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
return err
|
||
}
|
||
|
||
// 切换聊天室状态
|
||
func (client *ImClient) ChangeChatroomStat(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/toggleCloseStat.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
|
||
requestId := HyTools.GetUUID()
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态请求:requestId " + requestId + " body " + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
if len(res) == 0 {
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果:失败 res为空 requestId " + requestId + common.LOG_QUOTE_STRING)
|
||
return errors.New("操作失败")
|
||
}
|
||
|
||
if err != nil {
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果:失败 返回error requestId " + requestId + "error " + err.Error() + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
var resData struct {
|
||
Code int `json:"code"`
|
||
Desc string `json:"desc"`
|
||
}
|
||
|
||
_ = json.Unmarshal([]byte(res), &resData)
|
||
|
||
if resData.Code != 200 {
|
||
if resData.Code != 417 { // 重复操作 直接忽略
|
||
logs.Info(fmt.Sprintf(common.LOG_QUOTE_STRING+"聊天室切换聊天室开关状态结果:失败 code[%d] requestId "+requestId+" desc[%s] "+common.LOG_QUOTE_STRING, resData.Code, resData.Desc))
|
||
return errors.New("操作失败")
|
||
}
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果: requestId " + requestId + " response " + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 设置聊天室成员角色
|
||
func (client *ImClient) SetChatroomMemberRole(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/chatroom/setMemberRole.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "设置聊天室成员角色请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "设置聊天室成员角色结果:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
return err
|
||
}
|
||
|
||
// 发送广播消息
|
||
func (client *ImClient) SendBroadCastMsg(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/msg/broadcastMsg.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "发送广播请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "发送广播结果:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
return err
|
||
}
|
||
|
||
// 发送全员广播 V2
|
||
func (client *ImClient) SendBroadCastMsgV2(req BroadcastNotificationReq) error {
|
||
|
||
url := "https://open.yunxinapi.com/im/v2/broadcast_notification"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateJsonHeader()
|
||
|
||
bodyStr := HyTools.JsonStr(req)
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "发送广播请求V2:" + bodyStr + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, bodyStr)
|
||
logs.Info(common.LOG_QUOTE_STRING + "发送广播结果V2:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
return err
|
||
}
|
||
|
||
// 踢出用户登录 V2 https://{endpoint}/im/v2/accounts/{account_id}/actions/kick
|
||
|
||
func (client *ImClient) KickOutUserV2(userId string) error {
|
||
|
||
url := "https://open.yunxinapi.com/im/v2/accounts/" + userId + "/actions/kick"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateJsonHeader()
|
||
|
||
req := make(map[string]any, 3)
|
||
req["type"] = 1
|
||
req["device_id_list"] = []string{}
|
||
req["kick_notify_extension"] = ""
|
||
|
||
bodyStr := HyTools.JsonStr(req)
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "发送踢下线请求V2:" + bodyStr + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, bodyStr)
|
||
logs.Info(common.LOG_QUOTE_STRING + "发送踢下线结果V2:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
return err
|
||
}
|
||
|
||
// 设置/取消 拉黑 静音
|
||
func (client *ImClient) SetSpecialRelation(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/user/setSpecialRelation.action"
|
||
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
|
||
logs.Info(common.LOG_QUOTE_STRING + "设置/取消 拉黑请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "设置/取消 拉黑结果:" + res + common.LOG_QUOTE_STRING)
|
||
|
||
return err
|
||
}
|
||
|
||
// 发送自定义系统通知
|
||
func (client *ImClient) BatchSendMsg(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/msg/sendBatchMsg.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信IM批量发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信IM批量发消息结果:" + res + common.LOG_QUOTE_STRING)
|
||
return err
|
||
}
|
||
|
||
// 批量发送消息
|
||
func (client *ImClient) SendAttachMsg(parameters map[string]string) error {
|
||
|
||
url := "https://api.netease.im/nimserver/msg/sendAttachMsg.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发系统通知请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发系统通知结果:" + res + common.LOG_QUOTE_STRING)
|
||
if parameters["to"] == "b260b07ff3d1411f926e2d767cb9d6f3" {
|
||
log.Info("完成给老板发接单消息")
|
||
}
|
||
return err
|
||
}
|
||
|
||
// CreateChatGroup 创建群组
|
||
func (client *ImClient) CreateChatGroup(ctx context.Context, ownerUserId string, groupName string, inviteMem []string) (string, error) {
|
||
url := "https://open.yunxinapi.com/im/v2.1/teams"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateJsonHeader()
|
||
reqBody := &CreateChatGroupReq{
|
||
OwnerAccountID: ownerUserId,
|
||
TeamType: 1,
|
||
Name: groupName,
|
||
MembersLimit: 3000,
|
||
InviteAccountIDs: inviteMem,
|
||
InviteMsg: "管理",
|
||
Configuration: &TeamConfiguration{
|
||
JoinMode: 1,
|
||
},
|
||
AntispamConfiguration: nil,
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return "", errors.WithStack(err)
|
||
}
|
||
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
// {"desc":"already register","code":414}
|
||
logs.Info("YunXin_CreateChatGroup_Fail_AccID_%s:"+err.Error(), ownerUserId)
|
||
return "", errors.WithStack(err)
|
||
}
|
||
log.InfoF("create group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return "", errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return "", errors.Errorf("YunXin_CreateChatGroup code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
if len(body.Data.FailedList) > 0 {
|
||
var errInfo []string
|
||
for _, member := range body.Data.FailedList {
|
||
errInfo = append(errInfo, fmt.Sprintf("account: %s ,code: %d ,msg: %s", member.AccountID, member.ErrorCode, member.ErrorMsg))
|
||
}
|
||
return "", errors.Errorf("YunXin_CreateChatGroup err: %s", strings.Join(errInfo, ";"))
|
||
}
|
||
|
||
return cast.ToString(body.Data.TeamInfo.TeamID), nil
|
||
}
|
||
|
||
// 创建云信账户
|
||
// 创建高级群,创建时即可通过设置群成员列表邀请用户入群。
|
||
// 建群成功会返回 tid,网易云信服务器产生,群唯一标识,该字段需要保存,以便于加人与踢人等后续操作。
|
||
// 如果创建时邀请的成员中存在加群数量超过限制的情况,会返回 faccid(加群失败成员的 IM 账号)。
|
||
// 每个用户可创建的群数量有限制,限制值由 IM 套餐的群组配置决定,具体可前往 网易云信控制台 查看。
|
||
func (client *ImClient) CreateProGroup(tname, owner, announcement, avatar string) (string, error) {
|
||
url := "https://api.netease.im/nimserver/team/create.action"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateHeader()
|
||
sb := HyTools.NewStringBuilder()
|
||
sb.Append("tname=" + tname)
|
||
sb.Append("&")
|
||
sb.Append("owner=owner")
|
||
sb.Append("&")
|
||
sb.Append("announcement=" + announcement)
|
||
sb.Append("&")
|
||
sb.Append("icon=" + avatar)
|
||
sb.Append("&")
|
||
sb.Append("joinmode=" + "0")
|
||
sb.Append("&")
|
||
sb.Append("invitemode=" + "1") // 邀请权限,即谁可以邀请他人入群0,群主和管理员(默认)。1,所有人
|
||
sb.Append("&")
|
||
sb.Append("teamMemberLimit=" + "3000") // 最大群成员数(包含群主),[2,200(默认)]
|
||
sb.Append("&")
|
||
sb.Append("isNotifyCloseOnline=" + "0") // 是否关闭群通知消息在线发送0,否。1,是
|
||
sb.Append("&")
|
||
sb.Append("isNotifyClosePersistent=" + "0") // 是否关闭存储离线/漫游/历史的群通知消息0,否。1,是
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, sb.ToString())
|
||
// code Integer 状态码
|
||
// tid Long 网易云信服务器产生,群唯一标识
|
||
// faccid String 入群失败的账号(accid)列表,格式为 JSONArray,如果创建时邀请的成员中存在加群数量超过限制的情况,会返回入群失败的 accid 以及附言(msg)
|
||
if err != nil {
|
||
// {"desc":"already register","code":414}
|
||
log.Info("CreateProGroup %s:" + err.Error())
|
||
return "", err
|
||
} else {
|
||
var resDTO CreateImRes
|
||
json.Unmarshal([]byte(res), &resDTO)
|
||
if resDTO.Code != 200 {
|
||
log.Info("CreateProGroup_%s:" + resDTO.Desc)
|
||
} else {
|
||
log.Info("CreateProGroup_%s:" + res)
|
||
}
|
||
}
|
||
var body map[string]any
|
||
if errJson := json.Unmarshal([]byte(res), &body); errJson != nil {
|
||
return "", errJson
|
||
}
|
||
if int(body["code"].(float64)) != 200 {
|
||
return "", errors.New(body["desc"].(string))
|
||
}
|
||
return body["tid"].(string), nil
|
||
}
|
||
|
||
// GroupUpdate 更新群组
|
||
func (client *ImClient) GroupUpdate(ctx context.Context, id, operator_id, name, announcement, icon string) error {
|
||
url := "https://open.yunxinapi.com/im/v2.1/teams/" + id
|
||
httpMethod := common.HTTP_METHOD_PATCH
|
||
header := client.generateJsonHeader()
|
||
reqBody := map[string]any{
|
||
"operator_id": operator_id,
|
||
"team_type": 1,
|
||
"name": name,
|
||
"announcement": announcement,
|
||
// "intro": intro,
|
||
// "members_limit": members_limit,
|
||
// "join_mode": join_mode, 通过 SDK 侧操作申请入群的验证方式。 0(默认):无需验证,直接入群。 1:需要群主或管理员验证通过才能入群。 2:不允许任何人申请入群。
|
||
// "agree_mode": agree_mode, 邀请入群时是否需要被邀请人的同意。0(默认):需要被邀请人同意才能入群。1:不需要被邀请人同意,直接入群。
|
||
// "invite_mode": invite_mode, 邀请权限,即谁可以邀请他人入群。0(默认):群主和管理员。1:所有人。
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
log.InfoF("GroupUpdate %s:"+err.Error(), operator_id)
|
||
return errors.WithStack(err)
|
||
}
|
||
log.InfoF("update group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return errors.Errorf("GroupUpdate code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// GroupTransfer 转让群组
|
||
func (client *ImClient) GroupTransfer(ctx context.Context, id, new_owner, extension string) error {
|
||
url := "https://open.yunxinapi.com/im/v2.1/teams/" + id + "/actions/transfer_owner"
|
||
httpMethod := common.HTTP_METHOD_PATCH
|
||
header := client.generateJsonHeader()
|
||
reqBody := map[string]any{
|
||
"team_type": 1,
|
||
"new_owner_account_id": new_owner,
|
||
"leave": 2,
|
||
"extension": extension,
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
log.InfoF("GroupTransfer %s:"+err.Error(), id)
|
||
return errors.WithStack(err)
|
||
}
|
||
log.InfoF("GroupTransfer group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return errors.Errorf("GroupTransfer code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// GroupManagerAdd
|
||
func (client *ImClient) GroupManagerAdd(ctx context.Context, id, operator_id, extension string, managers []string) error {
|
||
url := "https://open.yunxinapi.com/im/v2.1/teams/" + id + "/actions/add_manager"
|
||
httpMethod := common.HTTP_METHOD_POST
|
||
header := client.generateJsonHeader()
|
||
reqBody := map[string]any{
|
||
"team_type": 1,
|
||
"managers": managers,
|
||
"operator_id": operator_id,
|
||
"extension": extension,
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
log.InfoF("GroupManagerAdd %s:"+err.Error(), operator_id)
|
||
return errors.WithStack(err)
|
||
}
|
||
log.InfoF("GroupManagerAdd group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return errors.Errorf("GroupManagerAdd code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// GroupManagerRemove
|
||
func (client *ImClient) GroupManagerRemove(ctx context.Context, id, operator_id, extension string, managers []string) error {
|
||
url := "https://open.yunxinapi.com/im/v2.1/teams/" + id + "/actions/remove_manager"
|
||
httpMethod := common.HTTP_METHOD_DELETE
|
||
header := client.generateJsonHeader()
|
||
reqBody := map[string]any{
|
||
"team_type": 1,
|
||
"managers": managers,
|
||
"operator_id": operator_id,
|
||
"extension": extension,
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
log.InfoF("GroupManagerRemove %s:"+err.Error(), operator_id)
|
||
return errors.WithStack(err)
|
||
}
|
||
log.InfoF("GroupManagerRemove group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return errors.Errorf("GroupManagerRemove code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// GroupRemove
|
||
func (client *ImClient) GroupRemove(ctx context.Context, id, operator_id, extension string) error {
|
||
url := "https://open.yunxinapi.com/im/v2.1/teams/" + id
|
||
httpMethod := common.HTTP_METHOD_DELETE
|
||
header := client.generateJsonHeader()
|
||
reqBody := map[string]any{
|
||
"team_type": 1,
|
||
"operator_id": operator_id,
|
||
"extension": extension,
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
log.InfoF("GroupRemove %s:"+err.Error(), operator_id)
|
||
return errors.WithStack(err)
|
||
}
|
||
log.InfoF("GroupRemove group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return errors.Errorf("GroupRemove code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// GroupMemberKick
|
||
func (client *ImClient) GroupMemberKick(ctx context.Context, tid, operator_id, extension string, members []string) error {
|
||
url := "https://open.yunxinapi.com/im/v2/team_members/actions/kick_member"
|
||
httpMethod := common.HTTP_METHOD_DELETE
|
||
header := client.generateJsonHeader()
|
||
reqBody := map[string]any{
|
||
"team_type": 1,
|
||
"operator_id": operator_id,
|
||
"team_id": tid,
|
||
"kick_account_ids": members,
|
||
"extension": extension,
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
log.InfoF("GroupMemberKick %s:"+err.Error(), operator_id)
|
||
return errors.WithStack(err)
|
||
}
|
||
log.InfoF("GroupMemberKick group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return errors.Errorf("GroupMemberKick code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// GroupMemberLeave
|
||
func (client *ImClient) GroupMemberLeave(ctx context.Context, tid, account_id, extension string, members []string) error {
|
||
url := "https://open.yunxinapi.com/im/v2/team_members/actions/leave"
|
||
httpMethod := common.HTTP_METHOD_DELETE
|
||
header := client.generateJsonHeader()
|
||
reqBody := map[string]any{
|
||
"team_type": 1,
|
||
"account_id": account_id,
|
||
"team_id": tid,
|
||
"extension": extension,
|
||
}
|
||
bodyBytes, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||
if err != nil {
|
||
log.InfoF("GroupMemberLeave %s:"+err.Error(), tid)
|
||
return errors.WithStack(err)
|
||
}
|
||
log.InfoF("GroupMemberLeave group chat resp: %s", res)
|
||
var body BaseRes[CreateChatGroupRsp]
|
||
err = json.Unmarshal([]byte(res), &body)
|
||
if err != nil {
|
||
return errors.WithStack(err)
|
||
}
|
||
if body.Code != 200 {
|
||
return errors.Errorf("GroupMemberLeave code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ================ 私有方法 ========================
|
||
func generateBodyData(parameters map[string]string) string {
|
||
sb := htools.NewStringBuilder()
|
||
parametersCount := len(parameters)
|
||
i := 0
|
||
for k, v := range parameters {
|
||
sb.Append(k + "=" + v)
|
||
if i < parametersCount-1 {
|
||
sb.Append("&")
|
||
}
|
||
i++
|
||
}
|
||
return sb.ToString()
|
||
}
|
||
|
||
func randNumber() string {
|
||
str := "0123456789"
|
||
bytes := []byte(str)
|
||
var result []byte
|
||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||
for i := 0; i < 4; i++ {
|
||
result = append(result, bytes[r.Intn(len(bytes))])
|
||
}
|
||
return string(result)
|
||
}
|