feat: incr sync version.

This commit is contained in:
Gordon
2024-06-24 17:48:33 +08:00
parent e8ccae6349
commit 88b8043224
308 changed files with 55952 additions and 59 deletions

View File

@@ -0,0 +1,51 @@
package module
import (
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
)
type ApiMsgSender struct {
*MetaManager
}
type SendMsgReq struct {
RecvID string `json:"recvID" binding:"required_if" message:"recvID is required if sessionType is SingleChatType or NotificationChatType"`
SendMsg
}
type SendMsg struct {
SendID string `json:"sendID" binding:"required"`
GroupID string `json:"groupID" binding:"required_if=SessionType 2|required_if=SessionType 3"`
SenderNickname string `json:"senderNickname"`
SenderFaceURL string `json:"senderFaceURL"`
SenderPlatformID int32 `json:"senderPlatformID"`
Content map[string]interface{} `json:"content" binding:"required" swaggerignore:"true"`
ContentType int32 `json:"contentType" binding:"required"`
SessionType int32 `json:"sessionType" binding:"required"`
IsOnlineOnly bool `json:"isOnlineOnly"`
NotOfflinePush bool `json:"notOfflinePush"`
OfflinePushInfo *sdkws.OfflinePushInfo `json:"offlinePushInfo"`
}
func (a *ApiMsgSender) SendMsg(sendID, recvID string, index int) error {
content := fmt.Sprintf("this is test msg user %s to user %s, index: %d", sendID, recvID, index)
text := sdk_struct.TextElem{Content: content}
req := &SendMsgReq{
RecvID: recvID,
SendMsg: SendMsg{
SendID: sendID,
SenderPlatformID: constant.WindowsPlatformID,
ContentType: constant.Text,
SessionType: constant.SingleChatType,
Content: map[string]interface{}{"content": utils.StructToJsonString(text)},
},
}
var resp msg.SendMsgResp
return a.postWithCtx(constant.SendMsgRouter, req, &resp)
}

View File

@@ -0,0 +1,18 @@
package module
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/protocol/relation"
)
type TestFriendManager struct {
*MetaManager
}
func (t *TestFriendManager) ImportFriends(ownerUserID string, friendUserIDs []string) error {
req := &relation.ImportFriendReq{
OwnerUserID: ownerUserID,
FriendUserIDs: friendUserIDs,
}
return t.postWithCtx(constant.ImportFriendListRouter, &req, nil)
}

View File

@@ -0,0 +1,75 @@
package module
import (
"context"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"time"
"github.com/openimsdk/protocol/group"
"github.com/openimsdk/protocol/sdkws"
)
type TestGroupManager struct {
*MetaManager
}
func (t *TestGroupManager) GenGroupID(prefix string) string {
return fmt.Sprintf("%s_test_group_id_%d", prefix, time.Now().UnixNano())
}
func (t *TestGroupManager) CreateGroup(groupID string, groupName string, ownerUserID string, userIDs []string) error {
const batch = 2000
var memberUserIDs []string
if len(userIDs) > batch {
memberUserIDs = userIDs[:batch]
} else {
memberUserIDs = userIDs
}
req := &group.CreateGroupReq{
MemberUserIDs: memberUserIDs,
OwnerUserID: ownerUserID,
GroupInfo: &sdkws.GroupInfo{
GroupID: groupID,
GroupName: groupName,
GroupType: constant.WorkingGroup,
CreatorUserID: ownerUserID,
},
}
resp := &group.CreateGroupResp{}
if err := t.postWithCtx(constant.CreateGroupRouter, &req, &resp); err != nil {
return err
}
if len(userIDs) > batch {
num := len(userIDs) / batch
if len(userIDs)%batch != 0 {
num++
}
for i := 1; i < num; i++ {
start := batch * i
end := batch*i + batch
if len(userIDs) < end {
end = len(userIDs)
}
req := map[string]any{
"groupID": groupID,
"invitedUserIDs": userIDs[start:end],
"reason": "test",
}
resp := struct{}{}
if err := t.postWithCtx(constant.RouterGroup+"/invite_user_to_group", req, &resp); err != nil {
return err
}
}
}
return nil
}
func (t *TestGroupManager) InviteUserToGroup(ctx context.Context, groupID string, invitedUserIDs []string) error {
req := &group.InviteUserToGroupReq{
GroupID: groupID,
InvitedUserIDs: invitedUserIDs,
}
resp := &group.InviteUserToGroupResp{}
return t.postWithCtx(constant.InviteUserToGroupRouter, &req, &resp)
}

View File

@@ -0,0 +1,140 @@
package module
import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/internal/util"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
authPB "github.com/openimsdk/protocol/auth"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/mcontext"
"io"
"net/http"
)
const (
ManagerUserID = "openIMAdmin"
)
type MetaManager struct {
managerUserID string
apiAddr string
secret string
token string
}
func NewMetaManager(apiAddr, secret, managerUserID string) *MetaManager {
return &MetaManager{
managerUserID: managerUserID,
apiAddr: apiAddr,
secret: secret,
}
}
func (m *MetaManager) NewUserManager() *TestUserManager {
return &TestUserManager{m}
}
func (m *MetaManager) NewGroupMananger() *TestGroupManager {
return &TestGroupManager{m}
}
func (m *MetaManager) NewFriendManager() *TestFriendManager {
return &TestFriendManager{m}
}
func (m *MetaManager) NewApiMsgSender() *ApiMsgSender {
return &ApiMsgSender{m}
}
func (m *MetaManager) apiPost(ctx context.Context, route string, req, resp any) (err error) {
operationID, _ := ctx.Value("operationID").(string)
if operationID == "" {
err := sdkerrs.ErrArgs.Wrap("call api operationID is empty")
return err
}
reqBody, err := json.Marshal(req)
if err != nil {
return sdkerrs.ErrSdkInternal.Wrap("json.Marshal(req) failed " + err.Error())
}
reqUrl := m.apiAddr + route
request, err := http.NewRequestWithContext(ctx, http.MethodPost, reqUrl, bytes.NewReader(reqBody))
if err != nil {
return sdkerrs.ErrSdkInternal.Wrap("sdk http.NewRequestWithContext failed " + err.Error())
}
log.ZDebug(ctx, "ApiRequest", "url", reqUrl, "body", string(reqBody))
request.ContentLength = int64(len(reqBody))
request.Header.Set("Content-Type", "application/json")
request.Header.Set("operationID", operationID)
if m.token != "" {
request.Header.Set("token", m.token)
}
response, err := new(http.Client).Do(request)
if err != nil {
return sdkerrs.ErrNetwork.Wrap("ApiPost http.Client.Do failed " + err.Error())
}
defer response.Body.Close()
respBody, err := io.ReadAll(response.Body)
if err != nil {
log.ZError(ctx, "ApiResponse", err, "type", "read body", "status", response.Status)
return sdkerrs.ErrSdkInternal.Wrap("io.ReadAll(ApiResponse) failed " + err.Error())
}
log.ZDebug(ctx, "ApiResponse", "url", reqUrl, "status", response.Status, "body", string(respBody))
var baseApi util.ApiResponse
if err := json.Unmarshal(respBody, &baseApi); err != nil {
return sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("api %s json.Unmarshal(%q, %T) failed %s", m.apiAddr, string(respBody), &baseApi, err.Error()))
}
if baseApi.ErrCode != 0 {
err := sdkerrs.New(baseApi.ErrCode, baseApi.ErrMsg, baseApi.ErrDlt)
return err
}
if resp == nil || len(baseApi.Data) == 0 || string(baseApi.Data) == "null" {
return nil
}
if err := json.Unmarshal(baseApi.Data, resp); err != nil {
return sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("json.Unmarshal(%q, %T) failed %s", string(baseApi.Data), resp, err.Error()))
}
return nil
}
func (m *MetaManager) postWithCtx(route string, req, resp any) error {
return m.apiPost(m.buildCtx(), route, req, resp)
}
func (m *MetaManager) buildCtx() context.Context {
return mcontext.NewCtx(utils.OperationIDGenerator())
}
func (m *MetaManager) getToken(userID string, platformID int32) (string, error) {
req := authPB.UserTokenReq{PlatformID: platformID, UserID: userID, Secret: m.secret}
resp := authPB.UserTokenResp{}
err := m.postWithCtx(constant.GetUsersToken, &req, &resp)
if err != nil {
return "", err
}
return resp.Token, nil
}
func (m *MetaManager) initToken() error {
token, err := m.getToken(m.managerUserID, constant.AdminPlatformID)
if err != nil {
return err
}
m.token = token
return nil
}
func (m *MetaManager) GetServerTime() (int64, error) {
req := msg.GetServerTimeReq{}
resp := msg.GetServerTimeResp{}
err := m.postWithCtx(constant.GetServerTimeRouter, &req, &resp)
if err != nil {
return 0, err
} else {
return resp.ServerTime, nil
}
}

View File

@@ -0,0 +1,183 @@
package module
import (
"context"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/internal/interaction"
"github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext"
"github.com/openimsdk/openim-sdk-core/v3/pkg/common"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"time"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/mcontext"
)
type SendMsgUser struct {
longConnMgr *interaction.LongConnMgr
userID string
pushMsgAndMaxSeqCh chan common.Cmd2Value
recvPushMsgCallback func(msg *sdkws.MsgData)
failedMessageMap map[string]error
cancelFunc context.CancelFunc
ctx context.Context
}
func (b SendMsgUser) GetUserID() string {
return b.userID
}
func WithRecvPushMsgCallback(callback func(msg *sdkws.MsgData)) func(core *SendMsgUser) {
return func(core *SendMsgUser) {
core.recvPushMsgCallback = callback
}
}
func newIMconfig(platformID int32, apiAddr, wsAddr string) sdk_struct.IMConfig {
return sdk_struct.IMConfig{
PlatformID: platformID,
ApiAddr: apiAddr,
WsAddr: wsAddr,
}
}
func newUserCtx(userID, token string, imConfig sdk_struct.IMConfig) context.Context {
return ccontext.WithInfo(context.Background(), &ccontext.GlobalConfig{
UserID: userID,
Token: token,
IMConfig: imConfig})
}
func NewUser(userID, token string, imConfig sdk_struct.IMConfig, opts ...func(core *SendMsgUser)) *SendMsgUser {
pushMsgAndMaxSeqCh := make(chan common.Cmd2Value, 1000)
ctx := newUserCtx(userID, token, imConfig)
longConnMgr := interaction.NewLongConnMgr(ctx, &ConnListner{}, nil, pushMsgAndMaxSeqCh, nil)
core := &SendMsgUser{
pushMsgAndMaxSeqCh: pushMsgAndMaxSeqCh,
longConnMgr: longConnMgr,
userID: userID,
failedMessageMap: make(map[string]error),
ctx: ctx,
}
for _, opt := range opts {
opt(core)
}
baseCtx, cancel := context.WithCancel(ctx)
core.cancelFunc = cancel
go core.recvPushMsg(baseCtx)
go core.longConnMgr.Run(baseCtx)
return core
}
func (b *SendMsgUser) Close(ctx context.Context) {
b.longConnMgr.Close(ctx)
b.cancelFunc()
}
func (b *SendMsgUser) SendMsgWithContext(userID string, index int) error {
newCtx := mcontext.SetOperationID(b.ctx, utils.OperationIDGenerator())
return b.SendSingleMsg(newCtx, userID, index)
}
func (b *SendMsgUser) SendGroupMsgWithContext(groupID string, index int) error {
newCtx := mcontext.SetOperationID(b.ctx, utils.OperationIDGenerator())
return b.SendGroupMsg(newCtx, groupID, index)
}
func (b *SendMsgUser) SendSingleMsg(ctx context.Context, userID string, index int) error {
return b.sendMsg(ctx, userID, "", index, constant.SingleChatType, fmt.Sprintf("this is test msg user %s to user %s, index: %d", b.userID, userID, index))
}
func (b *SendMsgUser) BatchSendSingleMsg(ctx context.Context, userID string, index int) error {
content := fmt.Sprintf("this is test msg user %s to user %s, index: %d", b.userID, userID, index)
err := b.sendMsg(ctx, userID, "", index, constant.SingleChatType, content)
if err != nil {
log.ZError(ctx, "send msg failed", err, "userID", userID, "index", index, "content", content)
b.failedMessageMap[content] = err
}
return nil
}
func (b *SendMsgUser) SendGroupMsg(ctx context.Context, groupID string, index int) error {
return b.sendMsg(ctx, "", groupID, index, constant.SuperGroupChatType, fmt.Sprintf("this is test msg user %s to group %s, index: %d", b.userID, groupID, index))
}
func (b *SendMsgUser) BatchSendGroupMsg(ctx context.Context, groupID string, index int) error {
content := fmt.Sprintf("this is test msg user %s to group %s, index: %d", b.userID, groupID, index)
err := b.sendMsg(ctx, "", groupID, index, constant.SuperGroupChatType, content)
if err != nil {
log.ZError(ctx, "send msg failed", err, "groupID", groupID, "index", index, "content", content)
b.failedMessageMap[content] = err
}
return nil
}
func (b *SendMsgUser) sendMsg(ctx context.Context, userID, groupID string, index int, sesstionType int32, content string) error {
var resp sdkws.UserSendMsgResp
text := sdk_struct.TextElem{Content: content}
clientMsgID := utils.GetMsgID(b.userID)
msg := &sdkws.MsgData{
SendID: b.userID,
GroupID: groupID,
RecvID: userID,
SessionType: sesstionType,
ContentType: constant.Text,
SenderNickname: b.userID,
Content: []byte(utils.StructToJsonString(text)),
CreateTime: time.Now().UnixMilli(),
SenderPlatformID: constant.AdminPlatformID,
ClientMsgID: clientMsgID,
}
now := time.Now().UnixMilli()
if err := b.longConnMgr.SendReqWaitResp(ctx, msg, constant.SendMsg, &resp); err != nil {
b.failedMessageMap[clientMsgID] = err
return err
}
if resp.SendTime-now > 1500 {
log.ZWarn(ctx, "msg recv resp is too slow", nil, "sendTime", resp.SendTime, "now", now)
}
return nil
}
func (b *SendMsgUser) recvPushMsg(ctx context.Context) {
for {
select {
case cmd := <-b.pushMsgAndMaxSeqCh:
switch cmd.Cmd {
case constant.CmdPushMsg:
pushMsgs := cmd.Value.(*sdkws.PushMessages)
for _, push := range pushMsgs.Msgs {
for _, msg := range push.Msgs {
if b.recvPushMsgCallback == nil {
b.defaultRecvPushMsgCallback(msg)
} else {
b.recvPushMsgCallback(msg)
}
}
}
}
case <-ctx.Done():
return
}
}
}
func (b *SendMsgUser) defaultRecvPushMsgCallback(msg *sdkws.MsgData) {
}
type ConnListner struct {
}
func (c *ConnListner) OnConnecting() {}
func (c *ConnListner) OnConnectSuccess() {}
func (c *ConnListner) OnConnectFailed(errCode int32, errMsg string) {
// log.ZError(context.Background(), "connect failed", nil, "errCode", errCode, "errMsg", errMsg)
}
func (c *ConnListner) OnKickedOffline() {}
func (c *ConnListner) OnUserTokenExpired() {}

View File

@@ -0,0 +1,43 @@
package module
import (
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"time"
"github.com/openimsdk/protocol/sdkws"
userPB "github.com/openimsdk/protocol/user"
)
type TestUserManager struct {
*MetaManager
}
func (t *TestUserManager) GenUserIDs(num int) (userIDs []string) {
for i := 0; i < num; i++ {
userIDs = append(userIDs, fmt.Sprintf("testv3new_%d_%d", time.Now().UnixNano(), i))
}
return userIDs
}
func (t *TestUserManager) GenUserIDsWithPrefix(num int, prefix string) (userIDs []string) {
for i := 0; i < num; i++ {
userIDs = append(userIDs, fmt.Sprintf("%s_testv3new_%d_%d", prefix, time.Now().UnixNano(), i))
}
return userIDs
}
func (t *TestUserManager) RegisterUsers(userIDs ...string) error {
var users []*sdkws.UserInfo
for _, userID := range userIDs {
users = append(users, &sdkws.UserInfo{UserID: userID, Nickname: userID})
}
return t.postWithCtx(constant.UserRegister, &userPB.UserRegisterReq{
Secret: t.secret,
Users: users,
}, nil)
}
func (t *TestUserManager) GetToken(userID string, platformID int32) (string, error) {
return t.getToken(userID, platformID)
}