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 } }