Commit 316b492c authored by hujiebin's avatar hujiebin

feat:tengxunyun

parent 89c2baf1
......@@ -32,6 +32,9 @@ require (
github.com/sirupsen/logrus v1.7.0 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/tealeg/xlsx v1.0.5 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.479 // indirect
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
gopkg.in/ini.v1 v1.63.2 // indirect
gorm.io/driver/mysql v1.4.3 // indirect
......
......@@ -108,6 +108,16 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479 h1:3kwDb6p1J3LxmwnNgSSEheemPffo+vMewoDzKysYdig=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.479 h1:xDmo1rBmSJ7Hw3iOa6DQ/++z1d7pgsEVKrZno35zR7w=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.479/go.mod h1:3YlJ1g/Ko/iFgyBJdok+dRPTH6zRB6BBopAcFkbujPc=
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 h1:NavMw9XO2iCLv8hTKaJW2kTaGR2SdNljMABbe39yu6Q=
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0/go.mod h1:u7WiArmCTXTaQAHJwAOaLgpJ5e2xdY5/cgMEy3ubL60=
github.com/tencentyun/tls-sig-api-v2-golang v1.1.0 h1:dWbCuoTaRWvcS/RWW/8RIAvLRA4jyDNdoAuBGC5Veqk=
github.com/tencentyun/tls-sig-api-v2-golang v1.1.0/go.mod h1:D/i1nQrP1hSXxxz+SAmjaprAwH3EhYaktJG6BObWnFE=
github.com/tencentyun/tls-sig-api-v2-golang v1.3.0 h1:mW4onVqOP6MqkJtTay74Tch6NvjwQRXeCuhUC/p6YYk=
github.com/tencentyun/tls-sig-api-v2-golang v1.3.0/go.mod h1:0L1MSijyEq6a74xZ02h0qKfN8y6RcvDiNabIZWXereE=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
......
package rpc
import (
"encoding/json"
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/consul"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/hashicorp/consul/api"
"math/rand"
"net"
"net/http"
)
const (
defaultFinanceConsulName = "hiloFinance"
defaultFinanceServerScheme = "http"
defaultFinanceServerAddr = "127.0.0.1:9030" // 默认内网转发,本地回环
)
var financeServerHost = []string{defaultFinanceServerAddr}
var financeTransport *http.Transport
func init() {
financeTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
MaxIdleConnsPerHost: defaultMaxIdleConnsPerHost,
MaxIdleConns: defaultMaxIdleConns,
DialContext: (&net.Dialer{
Timeout: defaultDialTimeout,
KeepAlive: defaultKeepAliveTimeout,
}).DialContext,
IdleConnTimeout: defaultIdleConnTimeout,
ExpectContinueTimeout: defaultExpectContinueTimeout,
DisableKeepAlives: false,
}
go func() {
address := api.DefaultConfig().Address // 用consul api的default config
if err := consul.RegisterWatcher("services", nil, address, func(serviceStatus map[string]map[string][]string) {
if statusAddrs, ok := serviceStatus[defaultFinanceConsulName]; ok {
healthAddrs, _ := statusAddrs[api.HealthPassing]
l := len(healthAddrs)
if l > 0 {
mylogrus.MyLog.Infof("consul service update state:%v-%v", defaultFinanceConsulName, healthAddrs)
financeServerHost = healthAddrs
} else {
mylogrus.MyLog.Warnf("consul service update local state:%v-%v", defaultFinanceConsulName, defaultFinanceServerAddr)
financeServerHost = []string{defaultFinanceServerAddr} // 有其他问题都用默认的
}
for status := range statusAddrs {
if status == api.HealthPassing {
continue
}
mylogrus.MyLog.Warnf("consul service wrong state:%v-%v-%v", defaultFinanceConsulName, status, statusAddrs[status])
}
}
}); err != nil {
mylogrus.MyLog.Errorf("启动 consul 的watch监控失败")
}
}()
}
type CvSvip struct {
SvipLevel int `json:"svipLevel"`
Privileges []CVSvipPrivilege `json:"privileges"` // 特权
}
type CVSvipPrivilege struct {
Type int `json:"type"` // 1.专属勋章, 2.专属标识, 3.设备和IP踢出房间, 4.隐藏在线, 5.禁止跟随, 6.炫彩昵称, 7.隐藏礼物墙, 8.隐藏访客记录, 9.排行榜隐身, 10.房间防踢, 11.房间防抱下麦
CanSwitch bool `json:"canSwitch"` // 能否开关
UserSwitch bool `json:"userSwitch"` // 用户开关
}
// 获取svip等级
func GetUserSvip(model *domain.Model, userId mysql.ID) (CvSvip, error) {
svip, err := MGetUserSvip(model, []mysql.ID{userId})
if err != nil {
return CvSvip{}, nil
}
return svip[userId], nil
}
// 批量获取svip等级
// map userId->level
func MGetUserSvipLevel(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]int, error) {
res := make(map[mysql.ID]int, len(userIds))
if len(userIds) <= 0 {
return res, nil
}
level, err := MGetUserSvip(model, userIds)
if err != nil {
return res, nil
}
for userId, svip := range level {
res[userId] = svip.SvipLevel
}
return res, nil
}
// 批量获取svip
func MGetUserSvip(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]CvSvip, error) {
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data map[mysql.ID]CvSvip
}
var res = make(map[mysql.ID]CvSvip)
if len(userIds) <= 0 {
return res, nil
}
var userIdsStr []string
for _, userId := range userIds {
userIdsStr = append(userIdsStr, fmt.Sprintf("%d", userId))
}
_url := fmt.Sprintf("%v://%v/inner/svip/users", defaultFinanceServerScheme, getFinanceHost())
resp, err := HttpGet(model, _url, nil, map[string][]string{
"ids": userIdsStr,
})
if err != nil {
model.Log.Errorf("MGetUserSvip fail:%v", err)
return res, err
}
response := new(Response)
if err = json.Unmarshal(resp, response); err != nil {
model.Log.Errorf("MGetUserSvip json fail:%v", err)
return res, err
}
for userId, svip := range response.Data {
res[userId] = CvSvip{
SvipLevel: svip.SvipLevel,
Privileges: response.Data[userId].Privileges,
}
}
return res, nil
}
func getFinanceHost() string {
l := len(financeServerHost)
r := rand.Intn(l) // 随机一个
mylogrus.MyLog.Infof("getHostFinance:%v---%v", r, financeServerHost[r])
return financeServerHost[r]
}
package tencentyun
var IM_INVALID_USER = "@TLS#NOT_FOUND"
type OnlineStatusType = uint
const (
// 在线状态
IM_STATUS_OFF_LINE OnlineStatusType = 0
IM_STATUS_PUSH_ON_LINE OnlineStatusType = 1
IM_STATUS_ON_LINE OnlineStatusType = 2
)
// TIM相关常量
const (
TAG_PROFILE_IM_LEVEL = "Tag_Profile_IM_Level"
TAG_PROFILE_IM_NICK = "Tag_Profile_IM_Nick"
TAG_PROFILE_IM_IMAGE = "Tag_Profile_IM_Image"
TAG_PROFILE_IM_HILO = "Tag_Profile_Custom_Hilo"
)
package tencentyun
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/regions"
v20201229 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims/v20201229"
"golang.org/x/net/context"
"time"
)
const (
ImageModerationSecretId = "IKIDqbCXaNt97oEOHtDG3ZomUu3vXsvhDTR8"
ImageModerationSecretKey = "RdYCYeT0GFyPZS5QUHo43lCNHuFK8fut"
)
func ModerateImage(model *domain.Model, userId uint64, bizType, dataId, fileUrl string) (string, error) {
beginTime := time.Now()
credential := common.NewCredential(ImageModerationSecretId, ImageModerationSecretKey)
client, _ := v20201229.NewClient(credential, regions.Frankfurt, profile.NewClientProfile())
request := v20201229.NewImageModerationRequest()
request.BizType = &bizType
request.DataId = &dataId
request.FileUrl = &fileUrl
response, err := client.ImageModerationWithContext(context.Background(), request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
model.Log.Warnf("ModerateImage: An API error has returned: %s", err)
return "", err
}
if err != nil {
model.Log.Warnf("ModerateImage: An API error has returned: %s", err)
return "", err
}
endTime := time.Now()
model.Log.Infof("ModerateImage takes %d ms result: %s", endTime.Sub(beginTime).Milliseconds(), response.ToJsonString())
if response.Response != nil && response.Response.Label != nil && response.Response.Suggestion != nil {
rsp := *response.Response.Label
buf, err := json.Marshal(*response.Response)
if err == nil {
rsp = string(buf)
}
mr := TxModerateRecord{
UserId: userId,
DataId: dataId,
FileUrl: fileUrl,
Suggestion: *response.Response.Suggestion,
Response: rsp}
if err = model.Db.Create(&mr).Error; err != nil {
model.Log.Infof("Save TxModerateRecord err: %v", err)
}
}
return *response.Response.Suggestion, nil
}
package tencentyun
import "git.hilo.cn/hilo-common/resource/mysql"
type TxModerateRecord struct {
mysql.Entity
UserId uint64
DataId string
FileUrl string
Suggestion string
Response string
}
package tencentyun
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/utils"
"github.com/sirupsen/logrus"
"github.com/tencentyun/tls-sig-api-v2-golang/tencentyun"
"io/ioutil"
"math/rand"
"net/http"
"strconv"
"strings"
"time"
)
const (
timUrl = "https://console.tim.qq.com/v4"
overseaUrl = "https://adminapiger.im.qcloud.com/v4"
loginUrl = timUrl + "/im_open_login_svc/account_import?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
overseaLoginUrl = overseaUrl + "/im_open_login_svc/account_import?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
blackAddUrl = timUrl + "/sns/black_list_add?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
oversearBlackAddUrl = overseaUrl + "/sns/black_list_add?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
blackCancelUrl = timUrl + "/sns/black_list_delete?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
overseaBlackCancelUrl = overseaUrl + "/sns/black_list_delete?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
blackListGetUrl = timUrl + "/sns/black_list_get?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
overseaBlackListGetUrl = overseaUrl + "/sns/black_list_get?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
blackListCheck = timUrl + "/sns/black_list_check?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
overseaBlackListCheck = overseaUrl + "/sns/black_list_check?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
msgReadUrl = timUrl + "/openim/admin_set_msg_read?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
overseaMsgReadUrl = overseaUrl + "/openim/admin_set_msg_read?sdkappid={appid}&identifier={externalId}&usersig={userSin}&random={random}&contenttype=json"
basicParameters = "sdkappid={appid}&identifier=administrator&usersig={userSig}&random={random}&contenttype=json"
// 账号相关
// fixme: 哪边为准呢?
queryStateUrl = timUrl + "/openim/query_online_status?" + basicParameters
overseaQueryStateUrl = overseaUrl + "/openim/query_online_status?" + basicParameters
deleteAccountUrl = timUrl + "/im_open_login_svc/account_delete?" + basicParameters
// 用户资料
// fixme: 哪边为准呢?
getProfileUrl = timUrl + "/profile/portrait_get?" + basicParameters
overseaGetProfileUrl = overseaUrl + "/profile/portrait_get?" + basicParameters
setProfileUrl = timUrl + "/profile/portrait_set?" + basicParameters
overseaSetProfileUrl = overseaUrl + "/profile/portrait_set?" + basicParameters
// 群组相关
getAllGroupList = timUrl + "/group_open_http_svc/get_appid_group_list?" + basicParameters
overseaGetAllGroupList = overseaUrl + "/group_open_http_svc/get_appid_group_list?" + basicParameters
createGroupUrl = timUrl + "/group_open_http_svc/create_group?" + basicParameters
overseaCreateGroupUrl = overseaUrl + "/group_open_http_svc/create_group?" + basicParameters
destroyGroupUrl = timUrl + "/group_open_http_svc/destroy_group?" + basicParameters
overseaGetDestroyGroupUrl = overseaUrl + "/group_open_http_svc/destroy_group?" + basicParameters
getGroupInfoUrl = timUrl + "/group_open_http_svc/get_group_info?" + basicParameters
overseaGetGroupInfoUrl = overseaUrl + "/group_open_http_svc/get_group_info?" + basicParameters
joinGroupUrl = timUrl + "/group_open_http_svc/add_group_member?" + basicParameters
leaveGroupUrl = timUrl + "/group_open_http_svc/delete_group_member?" + basicParameters
getJoinedGroupUrl = timUrl + "/group_open_http_svc/get_joined_group_list?" + basicParameters
modifyGroupInfoUrl = timUrl + "/group_open_http_svc/modify_group_base_info?" + basicParameters
overseaModifyGroupInfoUrl = overseaUrl + "/group_open_http_svc/modify_group_base_info?" + basicParameters
getGroupMemberUrl = timUrl + "/group_open_http_svc/get_group_member_info?" + basicParameters
overseaGetGroupMemberUrl = overseaUrl + "/group_open_http_svc/get_group_member_info?" + basicParameters
sendNormalMsgUrl = timUrl + "/group_open_http_svc/send_group_msg?" + basicParameters
overseaSendNormalMsgUrl = overseaUrl + "/group_open_http_svc/send_group_msg?" + basicParameters
sendSystemMsgUrl = timUrl + "/group_open_http_svc/send_group_system_notification?" + basicParameters
overseaSendSystemMsgUrl = overseaUrl + "/group_open_http_svc/send_group_system_notification?" + basicParameters
// -------- 单聊相关 --------
c2cSendMsg = timUrl + "/openim/sendmsg?" + basicParameters // 单聊
overseaC2cSendMsg = overseaUrl + "/openim/sendmsg?" + basicParameters // 单聊
c2cBatchSendMsg = timUrl + "/openim/batchsendmsg?" + basicParameters // 群发单聊
overseaC2cBatchSendMsg = overseaUrl + "/openim/batchsendmsg?" + basicParameters // 群发单聊
c2cGetMsg = timUrl + "/openim/admin_getroammsg?" + basicParameters // 查询聊天记录
overseaC2cGetMsg = overseaUrl + "/openim/admin_getroammsg?" + basicParameters // 查询聊天记录
// -------- 设置用户属性 --------
setAttrUrl = timUrl + "/all_member_push/im_set_attr?" + basicParameters
overseaSetAttrUrl = overseaUrl + "/all_member_push/im_set_attr?" + basicParameters
// -------- 会话 --------
recentcontactdDleteMsg = timUrl + "/recentcontact/delete?" + basicParameters //删除
)
func GenSig(externalId string) (string, error) {
return tencentyun.GenSig(config.GetTencentyunAppId(), config.GetTencentyunKey(), externalId, 86400*30)
}
func getAdminSig() (string, error) {
return tencentyun.GenSig(config.GetTencentyunAppId(), config.GetTencentyunKey(), "administrator", 86400*180)
}
func GenOverseaSig(externalId string) (string, error) {
return tencentyun.GenSig(config.GetTxOverSeaAppId(), config.GetTxOverSeaAppKey(), externalId, 86400*30)
}
func getOverseaAdminSig() (string, error) {
return tencentyun.GenSig(config.GetTxOverSeaAppId(), config.GetTxOverSeaAppKey(), "administrator", 86400*180)
}
func UserRegister(externalId string, nick string, avatar string) error {
if config.AppIsRelease() {
return UserRegisterBy(externalId, nick, avatar, overseaLoginUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return UserRegisterBy(externalId, nick, avatar, loginUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
func UserRegisterBy(externalId string, nick string, avatar string, reqUrl string, getAdminSig func() (string, error), appId int) error {
type BodyStruct struct {
Identifier string
Nick string
FaceUrl string
}
type RespStruct struct {
ActionStatus string
ErrorInfo string
ErrorCode int
}
sig, err := getAdminSig()
if err != nil {
return err
}
//url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(loginUrl, "{appid}", strconv.Itoa(config.GetTencentyunAppId()), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(reqUrl, "{appid}", strconv.Itoa(appId), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
body := BodyStruct{
Identifier: externalId,
Nick: nick,
FaceUrl: avatar,
}
mylogrus.MyLog.Infof("url: %s, body: %+v", url, body)
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
respStruct := RespStruct{}
if err := json.Unmarshal(result, &respStruct); err != nil {
return err
}
mylogrus.MyLog.Infof("body: %+v, resp:%+v", body, respStruct)
if respStruct.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf("tencentyun UserRegister resp ErrorCode:%v, ErrorInfo:%v", respStruct.ErrorCode, respStruct.ErrorInfo)
}
}
//测试用
func BlackCheckList(externalId string, beBlockExternalIds []string) error {
type BodyStruct struct {
From_Account string
To_Account []string
CheckType string
}
type Item struct {
To_Account string
Relation string
ResultCode int
ResultInfo string
}
type RespStruct struct {
BlackListCheckItem []Item
Fail_Account []string
ActionStatus string
ErrorCode int
ErrorInfo string
ErrorDisplay string
}
sig, err := getOverseaAdminSig()
if err != nil {
return err
}
url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(overseaBlackListCheck,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId()), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
body := BodyStruct{
From_Account: externalId,
To_Account: beBlockExternalIds,
CheckType: "BlackCheckResult_Type_Single",
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
respStruct := RespStruct{}
if err := json.Unmarshal(result, &respStruct); err != nil {
return err
}
if respStruct.ErrorCode == 0 {
mylogrus.MyLog.Infof("tencentyun BlackCheckList resp data:%v", respStruct)
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun BlackCheckList resp data:%v, ErrorCode:%v, ErrorInfo:%v", respStruct, respStruct.ErrorCode, respStruct.ErrorInfo))
}
}
func BlackCancel(externalId string, beBlockExternalId string) error {
if config.AppIsRelease() {
return BlackCancelBy(externalId, beBlockExternalId, overseaBlackCancelUrl, func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return BlackCancelBy(externalId, beBlockExternalId, blackCancelUrl, func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
func BlackCancelBy(externalId string, beBlockExternalId string, reqUrl string, getAdminSig func() (string, error), appId int) error {
type BodyStruct struct {
From_Account string
To_Account []string
}
//保留部分,因为接口只提供了一个,没有抽象返回值,因为接口没几个。
type RespStruct struct {
ActionStatus string
ErrorInfo string
ErrorCode int
}
sig, err := getAdminSig()
if err != nil {
return err
}
//url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(blackCancelUrl, "{appid}", strconv.Itoa(config.GetTencentyunAppId()), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(reqUrl, "{appid}", strconv.Itoa(appId), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
body := BodyStruct{
From_Account: externalId,
To_Account: []string{beBlockExternalId},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
respStruct := RespStruct{}
if err := json.Unmarshal(result, &respStruct); err != nil {
return err
}
if respStruct.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun BlackAdd resp ErrorCode:%v, ErrorInfo:%v", respStruct.ErrorCode, respStruct.ErrorInfo))
}
}
//测试而已
func BlackListGet(externalId string) ([]string, error) {
type BodyStruct struct {
From_Account string
StartIndex int
MaxLimited int
LastSequence int
}
type RespItem struct {
To_Account string
AddBlackTimeStamp int
}
type RespStruct struct {
BlackListItem []RespItem
StartIndex int
CurruentSequence int
ActionStatus string
ErrorInfo string
ErrorCode int
ErrorDisplay string
}
sig, err := getOverseaAdminSig()
if err != nil {
return nil, err
}
url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(overseaBlackListGetUrl,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId()), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
body := BodyStruct{
From_Account: externalId,
StartIndex: 0,
MaxLimited: 100,
LastSequence: 0,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return nil, err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return nil, err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
respStruct := RespStruct{}
if err := json.Unmarshal(result, &respStruct); err != nil {
return nil, err
}
if respStruct.ErrorCode == 0 {
strs := []string{}
for _, r := range respStruct.BlackListItem {
strs = append(strs, r.To_Account)
}
return strs, nil
} else {
return nil, fmt.Errorf(fmt.Sprintf("tencentyun BlackListGet resp ErrorCode:%v, ErrorInfo:%v", respStruct.ErrorCode, respStruct.ErrorInfo))
}
}
func BlackAdd(externalId string, beBlockExternalId string) error {
if config.AppIsRelease() {
return BlackAddBy(externalId, beBlockExternalId, oversearBlackAddUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return BlackAddBy(externalId, beBlockExternalId, blackAddUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
func BlackAddOverSea(externalId string, beBlockExternalId string) error {
if err := BlackAddBy(externalId, beBlockExternalId, oversearBlackAddUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId()); err != nil {
return err
}
return nil
}
func BlackAddBy(externalId string, beBlockExternalId string, reqUrl string, getAdminSig func() (string, error), appId int) error {
type BodyStruct struct {
From_Account string
To_Account []string
}
type RespStruct struct {
ActionStatus string
ErrorInfo string
ErrorCode int
}
sig, err := getAdminSig()
if err != nil {
return err
}
//url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(blackAddUrl, "{appid}", strconv.Itoa(config.GetTencentyunAppId()), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(reqUrl, "{appid}", strconv.Itoa(appId), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
body := BodyStruct{
From_Account: externalId,
To_Account: []string{beBlockExternalId},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
respStruct := RespStruct{}
if err := json.Unmarshal(result, &respStruct); err != nil {
return err
}
mylogrus.MyLog.Infof("BlackAdd, rsp: %+v, req: %+v", resp, body)
if respStruct.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun BlackAdd resp ErrorCode:%v, ErrorInfo:%v", respStruct.ErrorCode, respStruct.ErrorInfo))
}
}
//两个人互相已读
func AdminSetMsgRead(externalId1 string, externalId2 string) error {
if config.AppIsRelease() {
return AdminSetMsgReadBy(externalId1, externalId2, overseaMsgReadUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return AdminSetMsgReadBy(externalId1, externalId2, msgReadUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
//两个人互相已读
func AdminSetMsgReadBy(externalId1 string, externalId2 string, reqUrl string, getAdminSig func() (string, error), appId int) error {
type BodyStruct struct {
Report_Account string
Peer_Account string
}
//保留部分,因为接口只提供了一个,没有抽象返回值,因为接口没几个。
type RespStruct struct {
ActionStatus string
ErrorInfo string
ErrorCode int
}
sig, err := getAdminSig()
if err != nil {
return err
}
//url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(msgReadUrl, "{appid}", strconv.Itoa(config.GetTencentyunAppId()), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
url := strings.Replace(strings.Replace(strings.Replace(strings.Replace(reqUrl, "{appid}", strconv.Itoa(appId), 1), "{externalId}", "administrator", 1), "{userSin}", sig, 1), "{random}", strconv.Itoa(rand.Intn(10000)), 1)
body := BodyStruct{
Report_Account: externalId1,
Peer_Account: externalId2,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
respStruct := RespStruct{}
if err := json.Unmarshal(result, &respStruct); err != nil {
return err
}
if respStruct.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun AdminSetMsgRead resp ErrorCode:%v, ErrorInfo:%v", respStruct.ErrorCode, respStruct.ErrorInfo))
}
}
// 基本的返回结构
type RespStruct struct {
ActionStatus string
ErrorCode int
ErrorInfo string
}
// 私聊发送返回结构
type C2cMsgRsp struct {
RespStruct
MsgTime int64
MsgKey string
}
func GetAllGroups() ([]string, uint, error) {
type getAllGroupReq struct {
GroupType string
}
type groupIdItem struct {
GroupId string
}
type getAllGroupRsp struct {
RespStruct
TotalCount uint
GroupIdList []groupIdItem
}
sig, err := getOverseaAdminSig()
if err != nil {
return nil, 0, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(overseaGetAllGroupList,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := getAllGroupReq{
GroupType: "ChatRoom",
}
jsonStr, err := json.Marshal(body)
if err != nil {
return nil, 0, err
}
mylogrus.MyLog.Info("GetAllGroups json: ", string(jsonStr))
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return nil, 0, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return nil, 0, err
}
response := getAllGroupRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return nil, 0, err
}
mylogrus.MyLog.Info("GetAllGroups: ", response)
if response.ErrorCode == 0 {
result := make([]string, 0)
for _, i := range response.GroupIdList {
result = append(result, i.GroupId)
}
return result, response.TotalCount, nil
} else {
return nil, 0, fmt.Errorf(fmt.Sprintf("tencentyun GetAllGroups rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
type GroupEditable struct {
Name string // 群名称(选填)
// Introduction string // 群简介(选填) NOTE:腾讯限制字节数太短,弃用
// Notification string // 群公告(选填) NOTE:腾讯限制字节数太短,弃用
// FaceUrl string // 群头像 URL(选填) NOTE:腾讯限制最长100个字节太短,弃用
// "MaxMemberNum": 500, // 最大群成员数量(选填)
// "ApplyJoinOption": "NeedPermission", // 申请加群方式(选填)
// "MuteAllMember": "On" // 设置全员禁言(选填):"On"开启,"Off"关闭
}
func CreateGroup(name string, groupId string) (string, error) {
if config.AppIsRelease() {
return CreateGroupBy(name, groupId, overseaCreateGroupUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return CreateGroupBy(name, groupId, createGroupUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
func CreateGroupBy(name string, txGroupId string, reqUrl string, getAdminSig func() (string, error), appId int) (string, error) {
logger := mylogrus.MyLog.WithField("appId", appId).WithField("txGroupId", txGroupId)
type createGroupReq struct {
Type string
GroupId *string
GroupEditable
}
type CreateGroupRsp struct {
RespStruct
GroupId string
}
sig, err := getAdminSig()
if err != nil {
return "", err
}
/* url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(createGroupUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))*/
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
// 限制字符数,避免超过腾讯的30字节限制
groupName := name
if len(name) > 7 {
groupName = name[0:7]
}
body := createGroupReq{
Type: "AVChatRoom",
GroupEditable: GroupEditable{
Name: groupName,
},
}
if len(txGroupId) > 0 {
body.GroupId = &txGroupId
}
jsonStr, err := json.Marshal(body)
if err != nil {
return "", err
}
logger.Info("CreateGroup json: ", string(jsonStr))
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return "", err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return "", err
}
response := CreateGroupRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return "", err
}
logger.Info("CreateGroup: ", response)
if response.ErrorCode == 0 {
return response.GroupId, nil
} else {
return "", fmt.Errorf(fmt.Sprintf("tencentyun CreateGroup rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func DestroyGroup(groupId string, localOnly bool) error {
err := DestroyGroupBy(groupId, destroyGroupUrl, func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
if !localOnly {
DestroyGroupBy(groupId, overseaGetDestroyGroupUrl, func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
}
return err
}
func DestroyGroupBy(txGroupId string, reqUrl string, getAdminSig func() (string, error), appId int) error {
logger := mylogrus.MyLog.WithField("appId", appId).WithField("txGroupId", txGroupId)
type BodyStruct struct {
GroupId string
}
sig, err := getAdminSig()
if err != nil {
return err
}
/* url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(destroyGroupUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))*/
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: txGroupId,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
response := RespStruct{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
logger.Info("DestroyGroup: ", response)
if response.ErrorCode == 0 || response.ErrorCode == 10010 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun DestroyGroup rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
type MemberListInfo struct {
Member_Account string // 成员 ID
Role string // 群内角色
JoinTime int // 入群时间(UTC 时间)
//MsgSeq uint
// MsgFlag string // 消息屏蔽选项
LastSendMsgTime int64 // 最后发言时间(UTC 时间)
ShutUpUntil int // 禁言截止时间(UTC 时间)
// AppMemberDefinedData": [ // 群成员自定义字段 【暂时不用】
}
type GroupBasicInfo struct {
GroupId string
Type string
Owner_Account string
CreateTime int
LastInfoTime int
LastMsgTime int
NextMsgSeq uint
MemberNum uint
MaxMemberNum uint
ShutUpAllMember string
}
type GroupInfo struct {
ErrorCode int
ErrorInfo string
Appid uint
GroupBasicInfo
// "AppDefinedData": 群组维度的自定义字段 【暂时不用】
MemberList []MemberListInfo
}
const GROUP_GET_BATCHSIZE = 50
const IM_GET_BATCHSIZE = 500
//海外国内是同步的,只要查询一个则可
// 分批查询群信息,保证不会溢出
func BatchGetGroupInfo(model *domain.Model, groupIds []string, requireMemberList bool) ([]GroupInfo, error) {
result := make([]GroupInfo, 0, len(groupIds))
for start := 0; start < len(groupIds); start += GROUP_GET_BATCHSIZE {
end := start + GROUP_GET_BATCHSIZE
if end > len(groupIds) {
end = len(groupIds)
}
mylogrus.MyLog.Info("tencentyun.BatchGetGroupInfo: ", start, ":", end)
g := groupIds[start:end]
gi, err := GetGroupInfo(model, g, requireMemberList)
if err == nil {
result = append(result, gi...)
} else {
return nil, err
}
}
return result, nil
}
// 查询群信息,有溢出可能,只适用于少量的情况
func GetGroupInfo(model *domain.Model, groupIds []string, requireMemberList bool) ([]GroupInfo, error) {
type responseFilter struct {
GroupBaseInfoFilter []string
MemberInfoFilter []string
}
type BodyStruct struct {
GroupIdList []string
ResponseFilter responseFilter
}
sig, err := getOverseaAdminSig()
if err != nil {
return nil, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(overseaGetGroupInfoUrl,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
model.Log.Info("tencentyun.GetGroupInfo: ", url)
beginTime := time.Now()
body := BodyStruct{
GroupIdList: groupIds,
ResponseFilter: responseFilter{
GroupBaseInfoFilter: []string{"Type", "CreateTime", "Owner_Account", "LastMsgTime", "NextMsgSeq", "MemberNum", "MaxMemberNum"},
},
}
if requireMemberList {
body.ResponseFilter.MemberInfoFilter = append(body.ResponseFilter.MemberInfoFilter, "Account", "JoinTime")
}
jsonStr, err := json.Marshal(body)
if err != nil {
return nil, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return nil, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return nil, err
}
type getGroupInfoRsp struct {
RespStruct
GroupInfo []GroupInfo
}
response := getGroupInfoRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return nil, err
}
endTime := time.Now()
model.Log.Info("tencentyun.GetGroupInfo takes ", endTime.Sub(beginTime).Milliseconds(), "ms")
model.Log.Info("tencentyun.GetGroupInfo: ", response)
if response.ErrorCode == 0 {
result := make([]GroupInfo, 0)
for _, i := range response.GroupInfo {
if i.Owner_Account == IM_INVALID_USER {
model.Log.Warnf("Skip Group %s with invalid owner", i.GroupId)
} else {
result = append(result, i)
}
}
return result, nil
} else {
return nil, fmt.Errorf(fmt.Sprintf("tencentyun GetGroupInfo rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
//已丢弃
func AddGroup(model *domain.Model, groupId string, members []string) (map[string]uint, error, int) {
beginTime := time.Now()
type Member struct {
Member_Account string
}
type BodyStruct struct {
GroupId string
MemberList []Member
}
sig, err := getAdminSig()
if err != nil {
return nil, err, 0
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(joinGroupUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: groupId,
MemberList: []Member{},
}
for _, i := range members {
body.MemberList = append(body.MemberList, Member{Member_Account: i})
}
jsonStr, err := json.Marshal(body)
if err != nil {
return nil, err, 0
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return nil, err, 0
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return nil, err, 0
}
type memberResult struct {
Member_Account string
Result uint
}
type addGroupRsp struct {
RespStruct
MemberList []memberResult
}
response := addGroupRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return nil, err, 0
}
endTime := time.Now()
model.Log.Info("tencentyun.AddGroup takes ", endTime.Sub(beginTime).Milliseconds(), "ms")
model.Log.Info("AddGroup: ", response)
if response.ErrorCode == 0 {
result := make(map[string]uint)
for _, i := range response.MemberList {
result[i.Member_Account] = i.Result
}
return result, nil, 0
} else {
return nil, fmt.Errorf(fmt.Sprintf("tencentyun AddGroup rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo)), response.ErrorCode
}
}
//已丢弃
func LeaveGroup(groupId string, members []string) {
type BodyStruct struct {
GroupId string
MemberToDel_Account []string
}
sig, err := getAdminSig()
if err != nil {
mylogrus.MyLog.Errorln(err)
return
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(leaveGroupUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: groupId,
MemberToDel_Account: members,
}
jsonStr, err := json.Marshal(body)
if err != nil {
mylogrus.MyLog.Errorln(err)
return
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
mylogrus.MyLog.Errorln(err)
return
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
mylogrus.MyLog.Error(err)
return
}
response := RespStruct{}
if err := json.Unmarshal(result, &response); err != nil {
mylogrus.MyLog.Errorln(err)
return
}
mylogrus.MyLog.Info("LeaveGroup: ", response)
if response.ErrorCode == 0 {
return
} else {
mylogrus.MyLog.Errorln(fmt.Errorf(fmt.Sprintf("tencentyun LeaveGroup rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo)))
return
}
}
type SelfGroupInfo struct {
JoinTime int
Role string
MsgFlag string
LastSendMsgTime int
NameCard string
}
type JoinedGroupInfo struct {
GroupBasicInfo
SelfInfo SelfGroupInfo
}
func ShutUpAllMember(groupId string, shutUp bool) error {
if config.AppIsRelease() {
return ShutUpAllMemberBy(groupId, shutUp, overseaModifyGroupInfoUrl, func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return ShutUpAllMemberBy(groupId, shutUp, modifyGroupInfoUrl, func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
func ShutUpAllMemberBy(groupId string, shutUp bool, reqUrl string, getAdminSig func() (string, error), appId int) error {
type ModifyGroupInfoReq struct {
GroupId string
MuteAllMember string
}
sig, err := getAdminSig()
if err != nil {
return err
}
/* url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(modifyGroupInfoUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))*/
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := ModifyGroupInfoReq{
GroupId: groupId,
}
if shutUp {
body.MuteAllMember = "On"
} else {
body.MuteAllMember = "Off"
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
mylogrus.MyLog.Info("ShutUpAllMember json: ", string(jsonStr))
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
response := RespStruct{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
mylogrus.MyLog.Info("ShutUpAllMember: ", response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun ShutUpAllMember rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
//丢弃
func SetGroupMaxMemberNum(groupId string, maxMemberNum uint) error {
type modifyGroupInfoReq struct {
GroupId string
MaxMemberNum uint
}
sig, err := getOverseaAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(overseaModifyGroupInfoUrl,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := modifyGroupInfoReq{
GroupId: groupId,
MaxMemberNum: maxMemberNum,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
mylogrus.MyLog.Info("SetGroupMaxMemberNum json: ", string(jsonStr))
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
response := RespStruct{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
mylogrus.MyLog.Info("SetGroupMaxMemberNum: ", response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun SetGroupMaxMemberNum rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func GetGroupMemberInfo(model *domain.Model, groupId string) (uint, []MemberListInfo, error) {
beginTime := time.Now()
type BodyStruct struct {
GroupId string
MemberInfoFilter []string
}
sig, err := getOverseaAdminSig()
if err != nil {
return 0, nil, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(overseaGetGroupMemberUrl,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: groupId,
MemberInfoFilter: []string{"Role", "LastSendMsgTime"},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return 0, nil, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return 0, nil, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return 0, nil, err
}
type getGroupMemberRsp struct {
RespStruct
MemberNum uint
MemberList []MemberListInfo
}
response := getGroupMemberRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return 0, nil, err
}
endTime := time.Now()
model.Log.Info("tencentyun.GetGroupMemberInfo takes ", endTime.Sub(beginTime).Milliseconds(), "ms")
model.Log.Debug("GetGroupMemberInfo ", groupId, " : ", response)
if response.ErrorCode == 0 {
return response.MemberNum, response.MemberList, nil
} else {
return 0, nil, fmt.Errorf(fmt.Sprintf("tencentyun GetGroupMemberInfo rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
// 海外版和国内版之间交叉发群消息
func CrossSendGroupMsg(appId int, txGroupId string, fromAccount *string, cloudCustomData string, msgType string, msgContent json.RawMessage) (uint, error) {
if appId == config.GetTencentyunAppId() {
return SendGroupMsgBy(txGroupId, fromAccount, cloudCustomData, msgType, msgContent, overseaSendNormalMsgUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else if appId == config.GetTxOverSeaAppId() {
return SendGroupMsgBy(txGroupId, fromAccount, cloudCustomData, msgType, msgContent, sendNormalMsgUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
return 0, errors.New("illegal appid")
}
func SendGroupMsgBy(txGroupId string, fromAccount *string, cloudCustomData string, msgType string, msgContent json.RawMessage,
reqUrl string, getAdminSig func() (string, error), appId int) (uint, error) {
beginTime := time.Now()
type msgBodyItem struct {
MsgType string
MsgContent json.RawMessage
}
type BodyStruct struct {
GroupId string
From_Account *string
Random uint32
ForbidCallbackControl []string
MsgBody []msgBodyItem
CloudCustomData string
}
sig, err := getAdminSig()
if err != nil {
return 0, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: txGroupId,
Random: rand.Uint32(),
ForbidCallbackControl: []string{"ForbidAfterSendMsgCallback"},
MsgBody: []msgBodyItem{{MsgType: msgType, MsgContent: msgContent}},
CloudCustomData: cloudCustomData,
}
if fromAccount != nil {
body.From_Account = fromAccount
}
mylogrus.MyLog.Infof("SendGroupMsgBy on Group %s, url:%s, body: %+v", txGroupId, url, body)
jsonStr, err := json.Marshal(body)
if err != nil {
return 0, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return 0, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return 0, err
}
type sendNormalMsgRsp struct {
RespStruct
MsgTime int64
MsgSeq uint
}
response := sendNormalMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return 0, err
}
endTime := time.Now()
mylogrus.MyLog.Infof("SendGroupMsgBy on Group %s, result: %v, takes %v ms", txGroupId, response, endTime.Sub(beginTime).Milliseconds())
if response.ErrorCode == 0 {
return response.MsgSeq, nil
} else {
return 0, fmt.Errorf(fmt.Sprintf("tencentyun SendGroupMsgBy rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func SendCustomMsg(logger *logrus.Entry, txGroupId string, fromAccount *string, content string, cloudCustomData string) (uint, error) {
if config.AppIsRelease() {
return SendCustomMsgBy(logger, txGroupId, fromAccount, content, cloudCustomData, overseaSendNormalMsgUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return SendCustomMsgBy(logger, txGroupId, fromAccount, content, cloudCustomData, sendNormalMsgUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
// 发送(自定义)群聊天消息 // fixme: 异步化
func SendCustomMsgBy(logger *logrus.Entry, txGroupId string, fromAccount *string, content string, cloudCustomData string, reqUrl string, getAdminSig func() (string, error), appId int) (uint, error) {
logger = logger.WithField("appId", appId).WithField("txGroupId", txGroupId)
logger.Infof("from %v, content: %s", fromAccount, content)
beginTime := time.Now()
type msgContentItem struct {
Data string
}
type msgBodyItem struct {
MsgType string
MsgContent msgContentItem
}
type BodyStruct struct {
GroupId string
From_Account *string
Random uint32
ForbidCallbackControl []string
MsgBody []msgBodyItem
CloudCustomData string
}
sig, err := getAdminSig()
if err != nil {
return 0, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: txGroupId,
Random: rand.Uint32(),
ForbidCallbackControl: []string{"ForbidAfterSendMsgCallback"},
MsgBody: []msgBodyItem{{MsgType: "TIMCustomElem", MsgContent: msgContentItem{Data: content}}},
CloudCustomData: cloudCustomData,
}
if fromAccount != nil {
body.From_Account = fromAccount
}
jsonStr, err := json.Marshal(body)
if err != nil {
return 0, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return 0, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return 0, err
}
type sendNormalMsgRsp struct {
RespStruct
MsgTime int64
MsgSeq uint
}
response := sendNormalMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return 0, err
}
endTime := time.Now()
logger.Infof("SendCustomMsg taskes %d ms, result: %v", endTime.Sub(beginTime).Milliseconds(), response)
if response.ErrorCode == 0 {
return response.MsgSeq, nil
} else {
return 0, fmt.Errorf(fmt.Sprintf("tencentyun SendCustomMsg rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func SendSimpleAtMsg(txGroupId string, from string, account string, onLineOnly int, content string, cloudCustomData string) (uint, error) {
if config.AppIsRelease() {
return SendSimpleAtMsgBy(txGroupId, from, account, onLineOnly, content, cloudCustomData, overseaSendNormalMsgUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return SendSimpleAtMsgBy(txGroupId, from, account, onLineOnly, content, cloudCustomData, sendNormalMsgUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
// 向群内发送形如“@tommy xxx"的消息
func SendSimpleAtMsgBy(txGroupId string, from string, account string, onLineOnly int, content string, cloudCustomData string,
reqUrl string, getAdminSig func() (string, error), appId int) (uint, error) {
mylogrus.MyLog.Infof("SendSimpleAtMsg on Group %s, from %s, %s, content: %s", txGroupId, from, account, content)
beginTime := time.Now()
type msgContentItem struct {
Text string
}
type msgBodyItem struct {
MsgType string
MsgContent msgContentItem
}
type groupAtItem struct {
GroupAtAllFlag int
GroupAt_Account string
}
type BodyStruct struct {
GroupId string
From_Account string
Random uint32
ForbidCallbackControl []string
OnlineOnlyFlag *int
MsgBody []msgBodyItem
GroupAtInfo []groupAtItem
CloudCustomData string
}
sig, err := getAdminSig()
if err != nil {
return 0, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: txGroupId,
From_Account: from,
Random: rand.Uint32(),
ForbidCallbackControl: []string{"ForbidAfterSendMsgCallback"},
MsgBody: []msgBodyItem{{MsgType: "TIMTextElem", MsgContent: msgContentItem{Text: content}}},
GroupAtInfo: []groupAtItem{{GroupAtAllFlag: 0, GroupAt_Account: account}},
CloudCustomData: cloudCustomData,
}
if onLineOnly == 1 {
body.OnlineOnlyFlag = &onLineOnly
}
jsonStr, err := json.Marshal(body)
if err != nil {
return 0, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return 0, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return 0, err
}
type sendNormalMsgRsp struct {
RespStruct
MsgTime int64
MsgSeq uint
}
response := sendNormalMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return 0, err
}
endTime := time.Now()
mylogrus.MyLog.Info("tencentyun.SendSimpleAtMsg takes ", endTime.Sub(beginTime).Milliseconds(), "ms")
mylogrus.MyLog.Infof("SendSimpleAtMsg on Group %s, result: %v", txGroupId, response)
if response.ErrorCode == 0 {
return response.MsgSeq, nil
} else {
return 0, fmt.Errorf(fmt.Sprintf("tencentyun SendSimpleAtMsg rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func SendSystemMsg(logger *logrus.Entry, groupId string, members []string, content string) error {
if config.AppIsRelease() {
return SendSystemMsgBy(logger, groupId, members, content, overseaSendSystemMsgUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return SendSystemMsgBy(logger, groupId, members, content, sendSystemMsgUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
func SendSystemMsgBy(logger *logrus.Entry, txGroupId string, members []string, content string, reqUrl string, getAdminSig func() (string, error), appId int) error {
logger = logger.WithField("appId", appId).WithField("txGroupId", txGroupId)
logger.Infof("SendSystemMsg content: %s", content)
beginTime := time.Now()
type BodyStruct struct {
GroupId string
ToMembers_Account []string
Content string
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
GroupId: txGroupId,
ToMembers_Account: members,
Content: content,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
response := RespStruct{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
endTime := time.Now()
logger.Infof("SendSystemMsg takes %dms: rsp: %+v", endTime.Sub(beginTime).Milliseconds(), response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun SendSystemMsg rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
type MsgContentItem struct {
Text string
}
type MsgBodyItem struct {
MsgContent MsgContentItem
MsgType string
}
type GroupMsgItem struct {
From_Account string
IsPlaceMsg int
MsgBody []MsgBodyItem
MsgPriority int
MsgRandom uint
MsgSeq uint
MsgTimeStamp uint
}
func QueryState(model *domain.Model, users []string, isNeedDetail bool) (map[string]string, []string, error) {
beginTime := time.Now()
type BodyStruct struct {
To_Account []string
IsNeedDetail bool
}
sig, err := getAdminSig()
if err != nil {
return nil, nil, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(queryStateUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
To_Account: users,
IsNeedDetail: isNeedDetail,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return nil, nil, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return nil, nil, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return nil, nil, err
}
type detailInfo struct {
Platform string
Status string
}
type stateInfo struct {
To_Account string
Status string
Detail []detailInfo
}
type errorInfo struct {
To_Account string
ErrorCode uint
}
type queryStateRsp struct {
RespStruct
QueryResult []stateInfo
ErrorList []errorInfo
}
response := queryStateRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return nil, nil, err
}
endTime := time.Now()
model.Log.Info("tencentyun.QueryState takes ", endTime.Sub(beginTime).Milliseconds(), "ms")
model.Log.Info("tencentyun.QueryState: ", response)
failed := make([]string, 0)
if response.ErrorCode == 0 {
result := make(map[string]string, 0)
for _, i := range response.QueryResult {
result[i.To_Account] = i.Status
}
for _, i := range response.ErrorList {
failed = append(failed, i.To_Account)
}
return result, failed, nil
} else {
return nil, failed, nil
//return nil, nil, fmt.Errorf(fmt.Sprintf("tencentyun QueryState rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func BatchQueryState(model *domain.Model, users []string) (map[string]uint, error) {
result := make(map[string]uint, 0)
for start := 0; start < len(users); start += IM_GET_BATCHSIZE {
end := start + IM_GET_BATCHSIZE
if end > len(users) {
end = len(users)
}
u := users[start:end]
s, missed, err := QueryState(model, u, false)
mylogrus.MyLog.Info("tencentyun.BatchQueryState: ", start, ":", end, ", statusMap: ", s, ", missed: ", missed)
if err == nil {
for _, i := range missed {
result[i] = IM_STATUS_OFF_LINE
}
for k, v := range s {
if v == "Offline" {
result[k] = IM_STATUS_OFF_LINE
} else if v == "PushOnline" {
result[k] = IM_STATUS_PUSH_ON_LINE
} else if v == "Online" {
result[k] = IM_STATUS_ON_LINE
}
}
} else {
return nil, err
}
}
return result, nil
}
func DeleteAccount(userId string) ([]string, error) {
type accountType struct {
UserID string
}
type BodyStruct struct {
DeleteItem []accountType
}
sig, err := getAdminSig()
if err != nil {
return nil, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(deleteAccountUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
DeleteItem: []accountType{{UserID: userId}},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return nil, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return nil, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return nil, err
}
type resultItemType struct {
ResultCode int
ResultInfo string
UserID string
}
type deleteAccountRsp struct {
RespStruct
ResultItem []resultItemType
}
response := deleteAccountRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return nil, err
}
mylogrus.MyLog.Info("DeleteAccount: ", response)
failed := make([]string, 0)
if response.ErrorCode == 0 {
for _, i := range response.ResultItem {
mylogrus.MyLog.Info("DeleteAccount ResultItem", i)
if i.ResultCode != 0 {
failed = append(failed, i.UserID)
}
}
return failed, nil
} else {
return nil, nil
//return nil, nil, fmt.Errorf(fmt.Sprintf("tencentyun QueryState rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func GetUserLevel(userId string) (uint32, error) {
type BodyStruct struct {
To_Account []string
TagList []string
}
sig, err := getAdminSig()
if err != nil {
return 0, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(getProfileUrl,
"{appid}", strconv.Itoa(config.GetTencentyunAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
To_Account: []string{userId},
TagList: []string{TAG_PROFILE_IM_LEVEL},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return 0, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return 0, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return 0, err
}
type ProfileItemType struct {
Tag string
Value uint32
}
type UserProfileItemType struct {
To_Account string
ProfileItem []ProfileItemType
ResultCode int
ResultInfo string
}
type getUserLevelRsp struct {
UserProfileItem []UserProfileItemType
RespStruct
ErrorDisplay string
}
response := getUserLevelRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return 0, err
}
mylogrus.MyLog.Info("GetUserLevel: ", response)
if response.ErrorCode == 0 {
for _, i := range response.UserProfileItem {
if i.To_Account == userId && i.ResultCode == 0 {
for _, j := range i.ProfileItem {
if j.Tag == TAG_PROFILE_IM_LEVEL {
return j.Value, nil
}
}
}
}
return 0, nil
} else {
return 0, fmt.Errorf(response.ErrorDisplay)
}
}
// fixme: 可以去掉了
func SetUserLevel(userId string, level uint32) error {
if !config.AppIsRelease() {
return SetUserLevelBy(userId, level, setProfileUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
return nil
}
func SetUserLevelBy(userId string, level uint32, reqUrl string, getAdminSig func() (string, error), appId int) error {
mylogrus.MyLog.Infof("SetUserLevel: user %s, level = %x", userId, level)
type ProfileItemType struct {
Tag string
Value uint32
}
type BodyStruct struct {
From_Account string
ProfileItem []ProfileItemType
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
From_Account: userId,
ProfileItem: []ProfileItemType{{Tag: TAG_PROFILE_IM_LEVEL, Value: level}},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
type setUserLevelRsp struct {
RespStruct
ErrorDisplay string
}
response := setUserLevelRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
mylogrus.MyLog.Info("SetUserLevel: ", response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(response.ErrorDisplay)
}
}
func GetUserHiloInfo(userId string) (string, error) {
type BodyStruct struct {
To_Account []string
TagList []string
}
sig, err := getOverseaAdminSig()
if err != nil {
return "", err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(overseaGetProfileUrl,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
To_Account: []string{userId},
TagList: []string{TAG_PROFILE_IM_HILO},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return "", err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return "", err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return "", err
}
type ProfileItemType struct {
Tag string
Value string
}
type UserProfileItemType struct {
To_Account string
ProfileItem []ProfileItemType
ResultCode int
ResultInfo string
}
type getUserLevelRsp struct {
UserProfileItem []UserProfileItemType
RespStruct
ErrorDisplay string
}
response := getUserLevelRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return "", err
}
mylogrus.MyLog.Info("GetUserHiloInfo: ", response)
if response.ErrorCode == 0 {
for _, i := range response.UserProfileItem {
if i.To_Account == userId && i.ResultCode == 0 {
for _, j := range i.ProfileItem {
if j.Tag == TAG_PROFILE_IM_HILO {
return j.Value, nil
}
}
}
}
return "", nil
} else {
return "", fmt.Errorf(response.ErrorDisplay)
}
}
func SetUserHiloInfo(userId string, value string) error {
/* err := SetUserHiloInfoBy(userId, value, overseaSetProfileUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
if err != nil {
return err
}
*/
if !config.AppIsRelease() {
return SetUserHiloInfoBy(userId, value, setProfileUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
return nil
}
func SetUserHiloInfoBy(userId string, value string, reqUrl string, getAdminSig func() (string, error), appId int) error {
mylogrus.MyLog.Infof("SetUserHiloInfo: user %s, value: %s", userId, value)
type ProfileItemType struct {
Tag string
Value string
}
type BodyStruct struct {
From_Account string
ProfileItem []ProfileItemType
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
From_Account: userId,
ProfileItem: []ProfileItemType{{Tag: TAG_PROFILE_IM_HILO, Value: value}},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
type setUserLevelRsp struct {
RespStruct
ErrorDisplay string
}
response := setUserLevelRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
mylogrus.MyLog.Info("SetUserHiloInfo: ", response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(response.ErrorDisplay)
}
}
// 重置用户信息
// 头像+昵称
func ResetUserInfo(userId, nick string) error {
if config.AppIsRelease() {
return ResetUserInfoBy(userId, nick, overseaSetProfileUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
}
return ResetUserInfoBy(userId, nick, setProfileUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
func ResetUserInfoBy(userId, nick string, reqUrl string, getAdminSig func() (string, error), appId int) error {
type ProfileItemType struct {
Tag string
Value string
}
type BodyStruct struct {
From_Account string
ProfileItem []ProfileItemType
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
From_Account: userId,
ProfileItem: []ProfileItemType{
{Tag: TAG_PROFILE_IM_NICK, Value: nick},
{Tag: TAG_PROFILE_IM_IMAGE, Value: utils.MakeFullUrl(utils.DefaultAvatarMan)},
},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
type setUserNickRsp struct {
RespStruct
ErrorDisplay string
}
response := setUserNickRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
mylogrus.MyLog.Info("SetUserNick: ", response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(response.ErrorDisplay)
}
}
func SetUserNick(userId string, nick string) error {
if config.AppIsRelease() {
return SetUserNickBy(userId, nick, overseaSetProfileUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
}
return SetUserNickBy(userId, nick, setProfileUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
func SetUserNickBy(userId string, nick string, reqUrl string, getAdminSig func() (string, error), appId int) error {
type ProfileItemType struct {
Tag string
Value string
}
type BodyStruct struct {
From_Account string
ProfileItem []ProfileItemType
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
From_Account: userId,
ProfileItem: []ProfileItemType{{Tag: TAG_PROFILE_IM_NICK, Value: nick}},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
type setUserNickRsp struct {
RespStruct
ErrorDisplay string
}
response := setUserNickRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
mylogrus.MyLog.Info("SetUserNick: ", response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(response.ErrorDisplay)
}
}
func SetUserAttr(logger *logrus.Entry, externalId string, key string, value string) error {
if config.AppIsRelease() {
return SetUserAttrBy(logger, externalId, key, value, overseaSetAttrUrl,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return SetUserAttrBy(logger, externalId, key, value, setAttrUrl,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
func SetUserAttrBy(logger *logrus.Entry, externalId string, key string, value string, reqUrl string, getAdminSig func() (string, error), appId int) error {
logger.Infof("SetUserAttrBy, externalId %s, (%s, %s)", externalId, key, value)
type userAttrElem struct {
ToAccount string `json:"To_Account"`
Attrs map[string]string `json:"Attrs"`
}
type BodyStruct struct {
UserAttrs []userAttrElem `json:"UserAttrs"`
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{UserAttrs: []userAttrElem{{ToAccount: externalId, Attrs: map[string]string{key: value}}}}
logger.Info("SetUserAttrBy, body: ", body)
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
response := RespStruct{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
logger.Info("SetUserAttrBy, rsp: ", response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf("%v", response.ErrorInfo)
}
}
func C2cSendMsg(model *domain.Model, syncOtherMachine int8, from_Account string, to_Account string, msgType string, text string) error {
if config.AppIsRelease() {
return C2cSendMsgBy(model, syncOtherMachine, from_Account, to_Account, msgType, text, overseaC2cSendMsg,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return C2cSendMsgBy(model, syncOtherMachine, from_Account, to_Account, msgType, text, c2cSendMsg,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
//服务器 单聊发消息
//1:把消息同步到 From_Account 在线终端和漫游上; 2:消息不同步至 From_Account;
func C2cSendMsgBy(model *domain.Model, syncOtherMachine int8, from_Account string, to_Account string, msgType string, text string,
reqUrl string, getAdminSig func() (string, error), appId int) error {
type MsgContentStruct struct {
Text string
}
type MsgBodyStruct struct {
MsgType string
MsgContent MsgContentStruct
}
type BodyStruct struct {
SyncOtherMachine int8
From_Account string
To_Account string
MsgRandom int64
MsgTimeStamp int64
ForbidCallbackControl []string
MsgBody []MsgBodyStruct
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
msgBodys := []MsgBodyStruct{}
msgBodys = append(msgBodys, MsgBodyStruct{
MsgType: msgType,
MsgContent: MsgContentStruct{
Text: text,
},
})
body := BodyStruct{
SyncOtherMachine: syncOtherMachine,
From_Account: from_Account,
To_Account: to_Account,
MsgRandom: time.Now().Unix(),
MsgTimeStamp: time.Now().Unix(),
ForbidCallbackControl: []string{"ForbidAfterSendMsgCallback"},
MsgBody: msgBodys,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
response := RespStruct{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
model.Log.Infof("C2cSendMsg send:%v, resp:%v ", bytes.NewBuffer(jsonStr), response)
if response.ErrorCode == 0 {
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun C2cSendMsg rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
//服务器 查询单聊消息
func C2cGetMsg(model *domain.Model, fromAccount, toAccount string, maxCnt int, minTime, maxTime int64) (int64, error) {
type BodyStruct struct {
From_Account string
To_Account string
MaxCnt int
MinTime int64
MaxTime int64
}
sig, err := getOverseaAdminSig()
if err != nil {
return 0, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(overseaC2cGetMsg,
"{appid}", strconv.Itoa(config.GetTxOverSeaAppId())),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
body := BodyStruct{
From_Account: fromAccount,
To_Account: toAccount,
MaxCnt: maxCnt,
MinTime: minTime,
MaxTime: maxTime,
}
jsonStr, err := json.Marshal(body)
if err != nil {
return 0, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return 0, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return 0, err
}
type msgContentItem struct {
Text string
}
type msgBodyItem struct {
MsgType string
MsgContent msgContentItem
}
type msgListType struct {
FromAccount string `json:"From_Account"`
ToAccount string `json:"To_Account"`
MsgSeq uint64
MsgRandom int64
MsgTimeStamp int64
MsgFlagBits uint
MsgKey string
MsgBody []msgBodyItem
CloudCustomData string
}
type c2cGetMsgRsp struct {
RespStruct
Complete int
MsgCnt uint
LastMsgTime int64
LastMsgKey string
MsgList []msgListType
}
response := c2cGetMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return 0, err
}
model.Log.Infof("C2cGetMsg send:%v, resp:%+v ", bytes.NewBuffer(jsonStr), response)
if response.ErrorCode == 0 {
return response.LastMsgTime, nil
} else {
return 0, fmt.Errorf(fmt.Sprintf("tencentyun C2cGetMsg rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func C2cSendCustomMsg(model *domain.Model, syncOtherMachine int8, fromAccount *string, toAccount string, data string, pushContent string) error {
if config.AppIsRelease() {
return C2cSendCustomMsgBy(model, syncOtherMachine, fromAccount, toAccount, data, pushContent, overseaC2cSendMsg,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return C2cSendCustomMsgBy(model, syncOtherMachine, fromAccount, toAccount, data, pushContent, c2cSendMsg,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
//服务器 单聊发消息, 自定义消息
//1:把消息同步到 From_Account 在线终端和漫游上; 2:消息不同步至 From_Account;
func C2cSendCustomMsgBy(model *domain.Model, syncOtherMachine int8, fromAccount *string, toAccount string, data string, pushContent string,
reqUrl string, getAdminSig func() (string, error), appId int) error {
type MsgContentStruct struct {
Data string
Desc string
Ext string
Sound string
}
type MsgBodyStruct struct {
MsgType string
MsgContent MsgContentStruct
}
type MsgOfflinePushInfo struct {
PushFlag int
Title string
Desc string
Ext string
}
type BodyStruct struct {
SyncOtherMachine int8
From_Account *string
To_Account string
MsgRandom int64
ForbidCallbackControl []string
MsgBody []MsgBodyStruct
OfflinePushInfo MsgOfflinePushInfo
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
msgBodys := []MsgBodyStruct{}
msgBodys = append(msgBodys, MsgBodyStruct{
MsgType: "TIMCustomElem",
MsgContent: MsgContentStruct{
Data: data,
},
})
body := BodyStruct{
SyncOtherMachine: syncOtherMachine,
To_Account: toAccount,
From_Account: fromAccount,
MsgRandom: time.Now().Unix(),
ForbidCallbackControl: []string{"ForbidAfterSendMsgCallback"},
MsgBody: msgBodys,
OfflinePushInfo: MsgOfflinePushInfo{
PushFlag: 0,
Desc: pushContent,
Ext: pushContent,
},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
type ErrorListItem struct {
To_Account string
ErrorCode int
}
type batchSendMsgRsp struct {
RespStruct
ErrorList []ErrorListItem
}
response := batchSendMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
model.Log.Infof("C2cSendCustomMsg send:%v, resp:%+v ", bytes.NewBuffer(jsonStr), response)
if response.ErrorCode == 0 {
// 存在部分错误的可能
if response.ActionStatus != "OK" {
model.Log.Infof("C2cSendCustomMsg: user %s, err: %v", fromAccount, response.ErrorList)
}
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun C2cSendCustomMsg rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
// (分批)批量发自定义单聊消息
func BatchSendCustomMsg(model *domain.Model, syncOtherMachine int8, fromAccount string, toAccount []string, data string, pushContent string) error {
for start := 0; start < len(toAccount); start += IM_GET_BATCHSIZE {
end := start + IM_GET_BATCHSIZE
if end > len(toAccount) {
end = len(toAccount)
}
toAccounts := toAccount[start:end]
model.Log.Infof("BatchSendCustomMsg, from %s, offset = %d, size = %d", fromAccount, start, len(toAccounts))
if err := c2cBatchSendCustomMsg(model, syncOtherMachine, fromAccount, toAccounts, data, pushContent); err != nil {
return err
}
}
return nil
}
func c2cBatchSendCustomMsg(model *domain.Model, syncOtherMachine int8, fromAccount string, toAccount []string, data string, pushContent string) error {
if config.AppIsRelease() {
return c2cBatchSendCustomMsgBy(model, syncOtherMachine, fromAccount, toAccount, data, pushContent, overseaC2cBatchSendMsg,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return c2cBatchSendCustomMsgBy(model, syncOtherMachine, fromAccount, toAccount, data, pushContent, c2cBatchSendMsg,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
//1:把消息同步到 From_Account 在线终端和漫游上; 2:消息不同步至 From_Account;
func c2cBatchSendCustomMsgBy(model *domain.Model, syncOtherMachine int8, fromAccount string, toAccount []string, data string, pushContent string,
reqUrl string, getAdminSig func() (string, error), appId int) error {
type MsgContentStruct struct {
Data string
Desc string
Ext string
Sound string
}
type MsgBodyStruct struct {
MsgType string
MsgContent MsgContentStruct
}
type MsgOfflinePushInfo struct {
PushFlag int
Title string
Desc string
Ext string
}
type BodyStruct struct {
SyncOtherMachine int8
From_Account string
To_Account []string
MsgRandom int64
MsgBody []MsgBodyStruct
OfflinePushInfo MsgOfflinePushInfo
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
msgBodys := []MsgBodyStruct{}
msgBodys = append(msgBodys, MsgBodyStruct{
MsgType: "TIMCustomElem",
MsgContent: MsgContentStruct{
Data: data,
},
})
body := BodyStruct{
SyncOtherMachine: syncOtherMachine,
From_Account: fromAccount,
To_Account: toAccount,
MsgRandom: time.Now().Unix(),
MsgBody: msgBodys,
OfflinePushInfo: MsgOfflinePushInfo{
PushFlag: 0,
Desc: pushContent,
Ext: pushContent,
},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
type ErrorListItem struct {
To_Account string
ErrorCode int
}
type batchSendMsgRsp struct {
RespStruct
ErrorList []ErrorListItem
}
response := batchSendMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
model.Log.Infof("C2cBatchSendMsg send:%v, resp:%v ", bytes.NewBuffer(jsonStr), response)
if response.ErrorCode == 0 {
// 存在部分错误的可能
if response.ActionStatus != "OK" {
model.Log.Infof("c2cBatchSendCustomMsg: user %d, err: %v", fromAccount, response.ErrorList)
}
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun C2cBatchSendMsg rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
func BatchSendTextMsg(model *domain.Model, syncOtherMachine int8, fromAccount string, toAccount []string, text string, pushContent string) (int, error) {
failedCount := 0
for start := 0; start < len(toAccount); start += IM_GET_BATCHSIZE {
end := start + IM_GET_BATCHSIZE
if end > len(toAccount) {
end = len(toAccount)
}
fc, err := batchSendTextMsg(model, syncOtherMachine, fromAccount, toAccount[start:end], text, pushContent)
if err != nil {
return failedCount, err
}
failedCount += fc
}
return failedCount, nil
}
func batchSendTextMsg(model *domain.Model, syncOtherMachine int8, fromAccount string, toAccount []string, text string, pushContent string) (int, error) {
if config.AppIsRelease() {
return batchSendTextMsgBy(model, syncOtherMachine, fromAccount, toAccount, text, pushContent, overseaC2cBatchSendMsg,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else {
return batchSendTextMsgBy(model, syncOtherMachine, fromAccount, toAccount, text, pushContent, c2cBatchSendMsg,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
}
// 批量发送单聊文字消息
func batchSendTextMsgBy(model *domain.Model, syncOtherMachine int8, fromAccount string, toAccount []string, text string, pushContent string,
reqUrl string, getAdminSig func() (string, error), appId int) (int, error) {
type MsgContentStruct struct {
Text string
}
type MsgBodyStruct struct {
MsgType string
MsgContent MsgContentStruct
}
type MsgOfflinePushInfo struct {
PushFlag int
Title string
Desc string
Ext string
}
type BodyStruct struct {
SyncOtherMachine int8
From_Account string
To_Account []string
MsgRandom int64
MsgBody []MsgBodyStruct
OfflinePushInfo MsgOfflinePushInfo
}
sig, err := getAdminSig()
if err != nil {
return 0, err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
msgBodys := []MsgBodyStruct{}
msgBodys = append(msgBodys, MsgBodyStruct{
MsgType: "TIMTextElem",
MsgContent: MsgContentStruct{
Text: text,
},
})
body := BodyStruct{
SyncOtherMachine: syncOtherMachine,
From_Account: fromAccount,
To_Account: toAccount,
MsgRandom: time.Now().Unix(),
MsgBody: msgBodys,
OfflinePushInfo: MsgOfflinePushInfo{
PushFlag: 0,
Desc: pushContent,
Ext: pushContent,
},
}
jsonStr, err := json.Marshal(body)
if err != nil {
return 0, err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return 0, err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return 0, err
}
type ErrorListItem struct {
To_Account string
ErrorCode int
}
type batchSendMsgRsp struct {
RespStruct
ErrorList []ErrorListItem
}
response := batchSendMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return 0, err
}
model.Log.Infof("batchSendTextMsgBy send:%v, resp:%v ", bytes.NewBuffer(jsonStr), response)
if response.ErrorCode == 0 {
// 存在部分错误的可能
if response.ActionStatus != "OK" {
model.Log.Infof("batchSendTextMsgBy: user %s, err: %v", fromAccount, response.ErrorList)
}
return len(response.ErrorList), nil
} else {
return 0, fmt.Errorf(fmt.Sprintf("tencentyun batchSendTextMsgBy ErrorInfo:%v", response.ErrorInfo))
}
}
// 海外版和国内版之间交叉发消息
func C2cCrossSendMsg(model *domain.Model, appId int, syncOtherMachine int8, from_Account string, to_Account string, msgType string, msgContent json.RawMessage) error {
if appId == config.GetTencentyunAppId() {
return C2cCrossSendMsgBy(model, syncOtherMachine, from_Account, to_Account, msgType, msgContent,
overseaC2cSendMsg,
func() (string, error) {
return getOverseaAdminSig()
}, config.GetTxOverSeaAppId())
} else if appId == config.GetTxOverSeaAppId() {
return C2cCrossSendMsgBy(model, syncOtherMachine, from_Account, to_Account, msgType, msgContent,
c2cSendMsg,
func() (string, error) {
return getAdminSig()
}, config.GetTencentyunAppId())
}
return errors.New("illegal appid")
}
func C2cCrossSendMsgBy(model *domain.Model, syncOtherMachine int8, fromAccount, toAccount string, msgType string, msgContent json.RawMessage,
reqUrl string, getAdminSig func() (string, error), appId int) error {
type MsgBodyStruct struct {
MsgType string
MsgContent json.RawMessage
}
type MsgOfflinePushInfo struct {
PushFlag int
Title string
Desc string
Ext string
}
type BodyStruct struct {
SyncOtherMachine int8
From_Account string
To_Account string
MsgRandom int64
ForbidCallbackControl []string
MsgBody []MsgBodyStruct
}
sig, err := getAdminSig()
if err != nil {
return err
}
url := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(reqUrl,
"{appid}", strconv.Itoa(appId)),
"{userSig}", sig),
"{random}", strconv.FormatUint(uint64(rand.Uint32()), 10))
msgBodys := []MsgBodyStruct{}
msgBodys = append(msgBodys, MsgBodyStruct{
MsgType: msgType,
MsgContent: msgContent,
})
body := BodyStruct{
SyncOtherMachine: syncOtherMachine,
To_Account: toAccount,
From_Account: fromAccount,
MsgRandom: time.Now().Unix(),
ForbidCallbackControl: []string{"ForbidAfterSendMsgCallback"},
MsgBody: msgBodys,
}
model.Log.Infof("C2cCrossSendMsgBy url: %+v, body:%+v", url, body)
jsonStr, err := json.Marshal(body)
if err != nil {
return err
}
rsp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return err
}
defer rsp.Body.Close()
result, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return err
}
type ErrorListItem struct {
To_Account string
ErrorCode int
}
type batchSendMsgRsp struct {
RespStruct
ErrorList []ErrorListItem
}
response := batchSendMsgRsp{}
if err := json.Unmarshal(result, &response); err != nil {
return err
}
model.Log.Infof("C2cCrossSendMsgBy send:%+v, resp:%+v ", bytes.NewBuffer(jsonStr), response)
if response.ErrorCode == 0 {
// 存在部分错误的可能
if response.ActionStatus != "OK" {
model.Log.Infof("C2cCrossSendMsgBy: user %s, err: %v", fromAccount, response.ErrorList)
}
return nil
} else {
return fmt.Errorf(fmt.Sprintf("tencentyun C2cCrossSendMsgBy rsp ErrorCode:%v, ErrorInfo:%v", response.ErrorCode, response.ErrorInfo))
}
}
const (
ImageFormatJpg = 1
ImageFormatGif = 2
ImageFormatPng = 3
ImageFormatBmp = 4
ImageFormatOther = 255
)
func GetImageFormat(format string) int {
if format == "jpg" {
return ImageFormatJpg
} else if format == "gif" {
return ImageFormatGif
} else if format == "png" {
return ImageFormatPng
} else if format == "bmp" {
return ImageFormatBmp
} else {
return ImageFormatOther
}
}
const (
ImageTypeOriginal = 1
ImageTypeLarge = 2
ImageTypeSmall = 3
)
type ImageInfo struct {
Type int
Size uint
Width uint
Height uint
URL string
Download_Flag int
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment