diff --git a/im.go b/im.go index 40970c0..502bf4b 100644 --- a/im.go +++ b/im.go @@ -8,102 +8,108 @@ package im import ( - "github.com/dobyte/tencent-im/account" - "github.com/dobyte/tencent-im/group" - "github.com/dobyte/tencent-im/internal/core" - "github.com/dobyte/tencent-im/mute" - "github.com/dobyte/tencent-im/operation" - "github.com/dobyte/tencent-im/private" - "github.com/dobyte/tencent-im/profile" - "github.com/dobyte/tencent-im/push" - "github.com/dobyte/tencent-im/sns" + "github.com/dobyte/tencent-im/account" + "github.com/dobyte/tencent-im/group" + "github.com/dobyte/tencent-im/internal/core" + "github.com/dobyte/tencent-im/internal/sign" + "github.com/dobyte/tencent-im/mute" + "github.com/dobyte/tencent-im/operation" + "github.com/dobyte/tencent-im/private" + "github.com/dobyte/tencent-im/profile" + "github.com/dobyte/tencent-im/push" + "github.com/dobyte/tencent-im/sns" ) type Error = core.Error type ( - IM interface { - // SNS 获取关系链管理接口 - SNS() sns.API - // Mute 获取全局禁言管理接口 - Mute() mute.API - // Push 获取全员推送接口 - Push() push.API - // Group 获取群组管理接口 - Group() group.API - // Account 获取账号管理接口 - Account() account.API - // Profile 获取资料管理接口 - Profile() profile.API - // Private 获取私聊消息接口 - Private() private.API - // Operation 获取运营管理接口 - Operation() operation.API - } - - Options struct { - AppId int // 应用 SDKAppID,可在即时通信 IM 控制台 的应用卡片中获取。 - AppSecret string // 密钥信息,可在即时通信 IM 控制台 的应用详情页面中获取,具体操作请参见 获取密钥 - UserId string // 用户ID - } - - im struct { - client core.Client - appId int - appSecret string - } + IM interface { + // GetUserSig 获取UserSig签名 + GetUserSig() string + // SNS 获取关系链管理接口 + SNS() sns.API + // Mute 获取全局禁言管理接口 + Mute() mute.API + // Push 获取全员推送接口 + Push() push.API + // Group 获取群组管理接口 + Group() group.API + // Account 获取账号管理接口 + Account() account.API + // Profile 获取资料管理接口 + Profile() profile.API + // Private 获取私聊消息接口 + Private() private.API + // Operation 获取运营管理接口 + Operation() operation.API + } + + Options struct { + AppId int // 应用SDKAppID,可在即时通信 IM 控制台 的应用卡片中获取。 + AppSecret string // 密钥信息,可在即时通信 IM 控制台 的应用详情页面中获取,具体操作请参见 获取密钥 + UserId string // 用户ID + Expire int // UserSig过期时间 + } + + im struct { + opt Options + client core.Client + } ) -// NewIM create a im instance. func NewIM(opt Options) IM { - return &im{ - appId: opt.AppId, - client: core.NewClient(core.Options{ - AppId: opt.AppId, - AppSecret: opt.AppSecret, - UserId: opt.UserId, - }), - } + return &im{opt: opt, client: core.NewClient(core.Options{ + AppId: opt.AppId, + AppSecret: opt.AppSecret, + UserId: opt.UserId, + Expire: opt.Expire, + })} +} + +// GetUserSig 获取UserSig签名 +func (i *im) GetUserSig() string { + userSig, _ := sign.GenUserSig(i.opt.AppId, i.opt.AppSecret, i.opt.UserId, i.opt.Expire) + return userSig } // SNS 获取关系链管理接口 func (i *im) SNS() sns.API { - return sns.NewAPI(i.client) + return sns.NewAPI(i.client) } // Mute 获取全局禁言管理接口 func (i *im) Mute() mute.API { - return mute.NewAPI(i.client) + return mute.NewAPI(i.client) } // Push 获取全员推送接口 func (i *im) Push() push.API { - return push.NewAPI(i.client) + return push.NewAPI(i.client) } // Group 获取群组管理接口 func (i *im) Group() group.API { - return group.NewAPI(i.client) + return group.NewAPI(i.client) } // Account 获取账号管理接口 func (i *im) Account() account.API { - return account.NewAPI(i.client) + return account.NewAPI(i.client) } // Profile 获取资料管理接口 func (i *im) Profile() profile.API { - return profile.NewAPI(i.client) + return profile.NewAPI(i.client) } // Private 获取私聊消息接口 func (i *im) Private() private.API { - return private.NewAPI(i.client) + return private.NewAPI(i.client) } // Operation 获取运营管理接口 func (i *im) Operation() operation.API { - return operation.NewAPI(i.client) + return operation.NewAPI(i.client) } func (i *im) Callback() { diff --git a/im_test.go b/im_test.go index c06cdc1..9457500 100644 --- a/im_test.go +++ b/im_test.go @@ -13,7 +13,7 @@ import ( "strconv" "testing" "time" - + "github.com/dobyte/tencent-im" "github.com/dobyte/tencent-im/account" "github.com/dobyte/tencent-im/group" @@ -53,6 +53,17 @@ func NewIM() im.IM { // }) // } +// GetUserSig 获取UserSig签名 +func TestIm_GetUserSig(t *testing.T) { + tim := NewIM() + + for i := 0; i < 1000; i++ { + tim.GetUserSig() + } + + t.Log("Success") +} + // 导入单个账号 func TestIm_Account_ImportAccount(t *testing.T) { if err := NewIM().Account().ImportAccount(account.Info{ @@ -63,7 +74,7 @@ func TestIm_Account_ImportAccount(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -84,7 +95,7 @@ func TestIm_Account_ImportAccounts(t *testing.T) { t.Error(err) return } - + t.Log(failedAccounts) } @@ -95,7 +106,7 @@ func TestIm_Account_DeleteAccount(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -116,7 +127,7 @@ func TestIm_Account_DeleteAccounts(t *testing.T) { t.Error(err) return } - + t.Log(deleteResults) } @@ -137,7 +148,7 @@ func TestIm_Account_CheckAccounts(t *testing.T) { t.Error(err) return } - + t.Log(checkResults) } @@ -147,7 +158,7 @@ func TestIm_Account_KickAccount(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -158,7 +169,7 @@ func TestIm_Account_QueryAccountOnlineStatus(t *testing.T) { t.Error(err) return } - + t.Log(ret) } @@ -172,7 +183,7 @@ func TestIm_Account_QueryAccountsOnlineStatus(t *testing.T) { t.Error(err) return } - + t.Log(resp.Results) t.Log(resp.Errors) } @@ -193,13 +204,13 @@ func TestIm_Push_Push(t *testing.T) { }) message.OfflinePush().SetAndroidExtAsHuaweiIntentParam(push.HuaweiIntentParamIntent) message.OfflinePush().SetApnsBadgeMode(push.BadgeModeNormal) - + taskId, err := NewIM().Push().PushMessage(message) if err != nil { t.Error(err) return } - + t.Log(taskId) } @@ -212,7 +223,7 @@ func TestIm_Push_SetAttrNames(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -223,7 +234,7 @@ func TestIm_Push_GetAttrNames(t *testing.T) { t.Error(err) return } - + t.Log(ret) } @@ -234,7 +245,7 @@ func TestIm_Push_GetUserAttrs(t *testing.T) { t.Error(err) return } - + t.Log(ret) } @@ -250,7 +261,7 @@ func TestIm_Push_SetUserAttrs(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -263,7 +274,7 @@ func TestIm_Push_DeleteUserAttrs(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -274,7 +285,7 @@ func TestIm_Push_GetUserTags(t *testing.T) { t.Error(err) return } - + t.Log(ret) } @@ -287,7 +298,7 @@ func TestIm_Push_AddUserTags(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -300,7 +311,7 @@ func TestIm_Push_DeleteUserTags(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -311,7 +322,7 @@ func TestIm_Push_DeleteUserAllTags(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -324,12 +335,12 @@ func TestIm_Profile_SetProfile(t *testing.T) { p.SetLocation(1, 23, 27465, 92) // p.SetLocation(1, 23, 2, 92) p.SetLanguage(20) - + if err := NewIM().Profile().SetProfile(p); err != nil { t.Error(err) return } - + t.Log("Success") } @@ -348,7 +359,7 @@ func TestIm_Profile_GetProfile(t *testing.T) { t.Error(err) return } - + for _, p := range profiles { t.Log(p.GetUserId()) t.Log(p.GetNickname()) @@ -366,7 +377,7 @@ func TestIm_Operation_GetOperationData(t *testing.T) { t.Error(err) return } - + t.Log(data) } @@ -377,7 +388,7 @@ func TestIm_Operation_GetHistoryData(t *testing.T) { t.Error(err) return } - + t.Log(files) } @@ -388,7 +399,7 @@ func TestIm_Operation_GetIpList(t *testing.T) { t.Error(err) return } - + t.Log(ips) } @@ -400,7 +411,7 @@ func TestIm_Mute_SetNoSpeaking(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -411,7 +422,7 @@ func TestIm_Mute_GetNoSpeaking(t *testing.T) { t.Error(err) return } - + t.Log(privateMuteTime) t.Log(groupMuteTime) } @@ -419,7 +430,7 @@ func TestIm_Mute_GetNoSpeaking(t *testing.T) { // 添加好友 func TestIm_SNS_AddFriends(t *testing.T) { friends := make([]*sns.Friend, 0) - + var friend *sns.Friend var userIds []string var userId string @@ -431,28 +442,28 @@ func TestIm_SNS_AddFriends(t *testing.T) { friends = append(friends, friend) userIds = append(userIds, userId) } - + failUserIds, err := NewIM().Account().ImportAccounts(userIds...) if err != nil { t.Error(err) return } - + t.Log(failUserIds) - + results, err := NewIM().SNS().AddFriends("assistant", friends, true, false) if err != nil { t.Error(err) return } - + t.Log(results) } // 导入好友 func TestIm_SNS_ImportFriends(t *testing.T) { friends := make([]*sns.Friend, 0) - + var friend *sns.Friend var userIds []string var userId string @@ -470,28 +481,28 @@ func TestIm_SNS_ImportFriends(t *testing.T) { friends = append(friends, friend) userIds = append(userIds, userId) } - + failUserIds, err := NewIM().Account().ImportAccounts(userIds...) if err != nil { t.Error(err) return } - + t.Log(failUserIds) - + results, err := NewIM().SNS().ImportFriends("assistant", friends) if err != nil { t.Error(err) return } - + t.Log(results) } // 更新好友 func TestIm_SNS_UpdateFriends(t *testing.T) { friends := make([]*sns.Friend, 0) - + var friend *sns.Friend var userIds []string var userId string @@ -509,21 +520,21 @@ func TestIm_SNS_UpdateFriends(t *testing.T) { friends = append(friends, friend) userIds = append(userIds, userId) } - + failUserIds, err := NewIM().Account().ImportAccounts(userIds...) if err != nil { t.Error(err) return } - + t.Log(failUserIds) - + results, err := NewIM().SNS().UpdateFriends("assistant", friends) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -535,13 +546,13 @@ func TestIm_SNS_DeleteFriends(t *testing.T) { userId = "test" + strconv.Itoa(i) userIds = append(userIds, userId) } - + results, err := NewIM().SNS().DeleteFriends("assistant", userIds, false) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -552,7 +563,7 @@ func TestIm_SNS_DeleteAllFriends(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -564,13 +575,13 @@ func TestIm_SNS_CheckFriends(t *testing.T) { userId = "test" + strconv.Itoa(i) userIds = append(userIds, userId) } - + results, err := NewIM().SNS().CheckFriends("assistant", userIds, sns.CheckTypeSingle) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -582,7 +593,7 @@ func TestIm_SNS_GetFriends(t *testing.T) { userId = "test" + strconv.Itoa(i) userIds = append(userIds, userId) } - + friends, err := NewIM().SNS().GetFriends("assistant", userIds, []string{ sns.FriendAttrAddSource, sns.FriendAttrRemark, @@ -597,7 +608,7 @@ func TestIm_SNS_GetFriends(t *testing.T) { t.Error(err) return } - + // 第一种获取方式 for _, friend := range friends { if friend.IsValid() { @@ -611,7 +622,7 @@ func TestIm_SNS_GetFriends(t *testing.T) { fmt.Println() } } - + // 第二种获取方式 for _, friend := range friends { if err := friend.GetError(); err != nil { @@ -639,18 +650,18 @@ func TestIm_SNS_FetchFriends(t *testing.T) { standardSequence = 0 customSequence = 0 ) - + for ret == nil || !ret.IsOver { ret, err = s.FetchFriends("assistant", startIndex, standardSequence, customSequence) if err != nil { t.Error(err) return } - + startIndex = ret.NextStartIndex standardSequence = ret.StandardSequence customSequence = ret.CustomSequence - + t.Log("下一个开始点:", ret.NextStartIndex) t.Log("是否拉取完毕:", ret.IsOver) t.Log("标准排序:", ret.StandardSequence) @@ -681,13 +692,13 @@ func TestIm_SNS_AddBlacklist(t *testing.T) { userId = "test" + strconv.Itoa(i) userIds = append(userIds, userId) } - + results, err := NewIM().SNS().AddBlacklist("assistant", userIds) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -699,13 +710,13 @@ func TestIm_SNS_DeleteBlacklist(t *testing.T) { userId = "test" + strconv.Itoa(i) userIds = append(userIds, userId) } - + results, err := NewIM().SNS().DeleteBlacklist("assistant", userIds) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -719,17 +730,17 @@ func TestIm_SNS_FetchBlacklist(t *testing.T) { maxLimited = 2 standardSequence = 0 ) - + for ret == nil || !ret.IsOver { ret, err = s.FetchBlacklist("assistant", startIndex, maxLimited, standardSequence) if err != nil { t.Error(err) return } - + startIndex = ret.NextStartIndex standardSequence = ret.StandardSequence - + t.Log("下一个开始点:", startIndex) t.Log("标准排序:", standardSequence) t.Log("黑名单列表:") @@ -750,13 +761,13 @@ func TestIm_SNS_CheckBlacklist(t *testing.T) { userId = "test" + strconv.Itoa(i) userIds = append(userIds, userId) } - + results, err := NewIM().SNS().CheckBlacklist("assistant", userIds, sns.BlacklistCheckTypeSingle) if err != nil { t.Error(err) return } - + for _, result := range results { if result.ResultCode == 0 { t.Log(result.UserId) @@ -783,7 +794,7 @@ func TestIm_SNS_AddGroups(t *testing.T) { userId = "test" + strconv.Itoa(i) userIds = append(userIds, userId) } - + _, results, err := NewIM().SNS().AddGroups("assistant", []string{ "测试3", "测试4", @@ -792,7 +803,7 @@ func TestIm_SNS_AddGroups(t *testing.T) { t.Error(err) return } - + t.Log(results) } @@ -806,7 +817,7 @@ func TestIm_SNS_DeleteGroups(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -821,13 +832,13 @@ func TestIm_SNS_GetGroups(t *testing.T) { } results []sns.GroupResult ) - + lastSequence, results, err = NewIM().SNS().GetGroups("assistant", lastSequence, true, groupName) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -849,13 +860,13 @@ func TestIm_Private_SendMessage(t *testing.T) { }) message.OfflinePush().SetAndroidExtAsHuaweiIntentParam(private.HuaweiIntentParamIntent) message.OfflinePush().SetApnsBadgeMode(private.BadgeModeNormal) - + ret, err := NewIM().Private().SendMessage(message) if err != nil { t.Error(err) return } - + t.Log(ret.MsgKey) t.Log(ret.MsgTime) } @@ -868,13 +879,13 @@ func TestIm_Private_SendMessages(t *testing.T) { message.SetContent(private.MsgTextContent{ Text: "Hello world", }) - + ret, err := NewIM().Private().SendMessages(message) if err != nil { t.Error(err) return } - + t.Log(ret.MsgKey) t.Log(ret.Errors) } @@ -889,13 +900,13 @@ func TestIm_Private_ImportMessage(t *testing.T) { message.SetContent(private.MsgTextContent{ Text: "Hello world", }) - + err := NewIM().Private().ImportMessage(message) if err != nil { t.Error(err) return } - + t.Log("Success") } @@ -913,19 +924,19 @@ func TestIm_Private_FetchMessages(t *testing.T) { MaxTime: time.Now().Unix(), } ) - + for ret == nil || !ret.IsOver { ret, err = p.FetchMessages(arg) if err != nil { t.Error(err) return } - + if !ret.IsOver { arg.LastMsgKey = ret.LastMsgKey arg.MaxTime = ret.LastMsgTime } - + t.Log(ret.IsOver) t.Log(ret.LastMsgKey) t.Log(ret.LastMsgTime) @@ -955,7 +966,7 @@ func TestIm_Private_PullMessages(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -966,7 +977,7 @@ func TestIm_Private_RevokeMessage(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -977,7 +988,7 @@ func TestIm_Private_SetMessageRead(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -991,7 +1002,7 @@ func TestIm_Private_GetUnreadMessageNum(t *testing.T) { t.Error(err) return } - + t.Log(ret.Total) t.Log(ret.UnreadList) t.Log(ret.ErrorList) @@ -1007,20 +1018,20 @@ func TestIm_Group_CreateGroup(t *testing.T) { // g.SetId("test_group1") g.SetIntroduction("这是一个测试群") g.SetNotification("这是一个测试群公告") - + for i := 1; i < 10; i++ { member := group.NewMember() member.SetUserId("test" + strconv.Itoa(i)) member.SetJoinTime(time.Now()) g.AddMembers(member) } - + groupId, err := NewIM().Group().CreateGroup(g) if err != nil { t.Error(err) return } - + t.Log(groupId) } @@ -1031,7 +1042,7 @@ func TestIm_Group_DestroyGroup(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1042,7 +1053,7 @@ func TestIm_Group_GetGroup(t *testing.T) { t.Error(err) return } - + if g != nil { t.Log(g.GetId()) t.Log(g.GetName()) @@ -1061,7 +1072,7 @@ func TestIm_Group_GetGroups(t *testing.T) { t.Error(err) return } - + for _, g := range groups { if err = g.GetError(); err != nil { t.Error(err) @@ -1085,7 +1096,7 @@ func TestIm_Group_AddGroupMembers(t *testing.T) { t.Error(err) return } - + t.Log(results) } @@ -1100,7 +1111,7 @@ func TestIm_Group_DeleteGroupMembers(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1111,7 +1122,7 @@ func TestIm_Group_ChangeGroupOwner(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1125,13 +1136,13 @@ func TestIm_Group_UpdateGroup(t *testing.T) { g.SetId("test_group1") g.SetIntroduction("这是一个测试群") g.SetNotification("这是一个测试群公告") - + err := NewIM().Group().UpdateGroup(g) if err != nil { t.Error(err) return } - + t.Log("Success") } @@ -1146,7 +1157,7 @@ func TestIm_Group_GetRolesInGroup(t *testing.T) { t.Error(err) return } - + t.Log(ret) } @@ -1157,10 +1168,10 @@ func TestIm_Group_FetchGroupMembers(t *testing.T) { t.Error(err) return } - + t.Log(ret.HasMore) t.Log(ret.Total) - + for _, member := range ret.List { t.Log(member.GetUserId()) } @@ -1173,7 +1184,7 @@ func TestIm_Group_FetchGroupIds(t *testing.T) { t.Error(err) return } - + t.Log(ret.Total) t.Log(ret.Next) t.Log(ret.HasMore) @@ -1187,11 +1198,11 @@ func TestIm_Group_FetchGroups(t *testing.T) { t.Error(err) return } - + t.Log(ret.Total) t.Log(ret.Next) t.Log(ret.HasMore) - + for _, g := range ret.List { t.Log(g.GetId()) t.Log(g.GetOwner()) @@ -1205,13 +1216,13 @@ func TestIm_Group_UpdateGroupMember(t *testing.T) { member.SetRole("Admin") member.SetNameCard("这是一个测试名片信息") member.SetMsgFlag(group.MsgFlagAcceptAndNotify) - + err := NewIM().Group().UpdateMember("test_group1", member) if err != nil { t.Error(err) return } - + t.Log("Success") } @@ -1228,7 +1239,7 @@ func TestIm_Group_FetchMemberGroups(t *testing.T) { t.Error(err) return } - + t.Log(ret.Total) t.Log(ret.HasMore) t.Log(ret.List) @@ -1243,7 +1254,7 @@ func TestIm_Group_ForbidSendMessage(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1257,7 +1268,7 @@ func TestIm_Group_AllowSendMessage(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1268,7 +1279,7 @@ func TestIm_Group_GetShuttedUpMembers(t *testing.T) { t.Error(err) return } - + t.Log(shuttedUps) } @@ -1279,7 +1290,7 @@ func TestIm_Group_RevokeMessage(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1290,7 +1301,7 @@ func TestIm_Group_RevokeMessages(t *testing.T) { t.Error(err) return } - + t.Log(results) } @@ -1301,7 +1312,7 @@ func TestIm_Group_SetMemberUnreadMsgNum(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1312,7 +1323,7 @@ func TestIm_Group_RevokeMemberMessages(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1337,13 +1348,13 @@ func TestIm_Group_SendMessage(t *testing.T) { message.AtAllMembers() message.AtMembers(test2) message.ClearAtMembers() - + ret, err := NewIM().Group().SendMessage("test_group1", message) if err != nil { t.Error(err) return } - + t.Log(ret.MsgSeq) t.Log(ret.MsgTime) } @@ -1355,7 +1366,7 @@ func TestIm_Group_SendNotification(t *testing.T) { t.Error(err) return } - + t.Log("Success") } @@ -1368,13 +1379,13 @@ func TestIm_Group_ImportGroup(t *testing.T) { g.SetAvatar("http://www.baidu.com") g.SetIntroduction("这是一个测试群") g.SetNotification("这是一个测试群公告") - + groupId, err := NewIM().Group().ImportGroup(g) if err != nil { t.Error(err) return } - + t.Log(groupId) } @@ -1387,13 +1398,13 @@ func TestIm_Group_ImportMessages(t *testing.T) { message.SetContent(private.MsgTextContent{ Text: "Hello world", }) - + results, err := NewIM().Group().ImportMessages("test_group1", message) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -1408,13 +1419,13 @@ func TestIm_Group_ImportMembers(t *testing.T) { member.SetJoinTime(time.Now()) members = append(members, member) } - + results, err := NewIM().Group().ImportMembers("@TGS#25J4AWNHA", members...) if err != nil { t.Error(err) return } - + t.Log(results) } @@ -1425,6 +1436,6 @@ func TestIm_Group_FetchMessages(t *testing.T) { t.Error(err) return } - + t.Log(ret) } diff --git a/internal/core/client.go b/internal/core/client.go index d0c8823..113b465 100644 --- a/internal/core/client.go +++ b/internal/core/client.go @@ -8,140 +8,141 @@ package core import ( - "encoding/json" - "errors" - "fmt" - "math/rand" - "time" - - "github.com/dobyte/http" - - "github.com/dobyte/tencent-im/internal/enum" - "github.com/dobyte/tencent-im/internal/sign" - "github.com/dobyte/tencent-im/internal/types" + "errors" + "fmt" + "math/rand" + "time" + + "github.com/dobyte/http" + + "github.com/dobyte/tencent-im/internal/enum" + "github.com/dobyte/tencent-im/internal/sign" + "github.com/dobyte/tencent-im/internal/types" ) const ( - defaultBaseUrl = "https://console.tim.qq.com" - defaultVersion = "v4" - defaultTimeout = 5 - defaultContentType = "json" - defaultExpire = 60 + defaultBaseUrl = "https://console.tim.qq.com" + defaultVersion = "v4" + defaultContentType = "json" + defaultExpire = 3600 ) var invalidResponse = errors.New("invalid response") type Client interface { - // Get send an http request use get method. - Get(serviceName string, command string, data interface{}, resp interface{}) error - // Post send an http request use post method. - Post(serviceName string, command string, data interface{}, resp interface{}) error - // Put send an http request use put method. - Put(serviceName string, command string, data interface{}, resp interface{}) error - // Patch send an http request use patch method. - Patch(serviceName string, command string, data interface{}, resp interface{}) error - // Delete send an http request use patch method. - Delete(serviceName string, command string, data interface{}, resp interface{}) error + // Get send an http request use get method. + Get(serviceName string, command string, data interface{}, resp interface{}) error + // Post send an http request use post method. + Post(serviceName string, command string, data interface{}, resp interface{}) error + // Put send an http request use put method. + Put(serviceName string, command string, data interface{}, resp interface{}) error + // Patch send an http request use patch method. + Patch(serviceName string, command string, data interface{}, resp interface{}) error + // Delete send an http request use patch method. + Delete(serviceName string, command string, data interface{}, resp interface{}) error } type client struct { - client *http.Client - appId int - appSecret string - userId string + client *http.Client + opt Options + userSig string + userSigExpireAt int64 } type Options struct { - AppId int // 应用SDKAppID,可在即时通信 IM 控制台 的应用卡片中获取。 - AppSecret string // 密钥信息,可在即时通信 IM 控制台 的应用详情页面中获取,具体操作请参见 获取密钥 - UserId string // 用户ID + AppId int // 应用SDKAppID,可在即时通信 IM 控制台 的应用卡片中获取。 + AppSecret string // 密钥信息,可在即时通信 IM 控制台 的应用详情页面中获取,具体操作请参见 获取密钥 + UserId string // 用户ID + Expire int // UserSig过期时间 } func NewClient(opt Options) Client { - rand.Seed(time.Now().UnixNano()) - c := new(client) - c.appId = opt.AppId - c.appSecret = opt.AppSecret - c.userId = opt.UserId - c.client = http.NewClient() - c.client.SetContentType(http.ContentTypeJson) - // c.client.SetTimeout(defaultTimeout) - c.client.SetBaseUrl(defaultBaseUrl) - - return c + rand.Seed(time.Now().UnixNano()) + c := new(client) + c.opt = opt + c.client = http.NewClient() + c.client.SetContentType(http.ContentTypeJson) + c.client.SetBaseUrl(defaultBaseUrl) + + return c } // Get send an http request use get method. func (c *client) Get(serviceName string, command string, data interface{}, resp interface{}) error { - return c.request(http.MethodGet, serviceName, command, data, resp) + return c.request(http.MethodGet, serviceName, command, data, resp) } // Post send an http request use post method. func (c *client) Post(serviceName string, command string, data interface{}, resp interface{}) error { - return c.request(http.MethodPost, serviceName, command, data, resp) + return c.request(http.MethodPost, serviceName, command, data, resp) } // Put send an http request use put method. func (c *client) Put(serviceName string, command string, data interface{}, resp interface{}) error { - return c.request(http.MethodPut, serviceName, command, data, resp) + return c.request(http.MethodPut, serviceName, command, data, resp) } // Patch send an http request use patch method. func (c *client) Patch(serviceName string, command string, data interface{}, resp interface{}) error { - return c.request(http.MethodPatch, serviceName, command, data, resp) + return c.request(http.MethodPatch, serviceName, command, data, resp) } // Delete send an http request use patch method. func (c *client) Delete(serviceName string, command string, data interface{}, resp interface{}) error { - return c.request(http.MethodDelete, serviceName, command, data, resp) + return c.request(http.MethodDelete, serviceName, command, data, resp) } // request send an http request. func (c *client) request(method, serviceName, command string, data, resp interface{}) error { - res, err := c.client.Request(method, c.buildUrl(serviceName, command), data) - if err != nil { - return err - } - js, _ := json.Marshal(data) - fmt.Println(string(js)) - fmt.Println(res.ReadString()) - if err = res.Scan(resp); err != nil { - return err - } - - if r, ok := resp.(types.ActionBaseRespInterface); ok { - if r.GetActionStatus() == enum.FailActionStatus { - return NewError(r.GetErrorCode(), r.GetErrorInfo()) - } - - if r.GetErrorCode() != enum.SuccessCode { - return NewError(r.GetErrorCode(), r.GetErrorInfo()) - } - } else if r, ok := resp.(types.BaseRespInterface); ok { - if r.GetErrorCode() != enum.SuccessCode { - return NewError(r.GetErrorCode(), r.GetErrorInfo()) - } - } else { - return invalidResponse - } - - return nil + res, err := c.client.Request(method, c.buildUrl(serviceName, command), data) + if err != nil { + return err + } + + if err = res.Scan(resp); err != nil { + return err + } + + if r, ok := resp.(types.ActionBaseRespInterface); ok { + if r.GetActionStatus() == enum.FailActionStatus { + return NewError(r.GetErrorCode(), r.GetErrorInfo()) + } + + if r.GetErrorCode() != enum.SuccessCode { + return NewError(r.GetErrorCode(), r.GetErrorInfo()) + } + } else if r, ok := resp.(types.BaseRespInterface); ok { + if r.GetErrorCode() != enum.SuccessCode { + return NewError(r.GetErrorCode(), r.GetErrorInfo()) + } + } else { + return invalidResponse + } + + return nil } // buildUrl build a request url. func (c *client) buildUrl(serviceName string, command string) string { - random := rand.Int31() - userSign, _ := sign.GenUserSign(c.appId, c.appSecret, c.userId, defaultExpire) - url := fmt.Sprintf("/%s/%s/%s?sdkappid=%d&identifier=%s&usersig=%s&random=%d&contenttype=%s", - defaultVersion, - serviceName, - command, - c.appId, - c.userId, - userSign, - random, - defaultContentType, - ) - - return url + format := "/%s/%s/%s?sdkappid=%d&identifier=%s&usersig=%s&random=%d&contenttype=%s" + random := rand.Int31() + userSig := c.getUserSig() + return fmt.Sprintf(format, defaultVersion, serviceName, command, c.opt.AppId, c.opt.UserId, userSig, random, defaultContentType) } + +// getUserSig get a userSig +func (c *client) getUserSig() string { + now := time.Now() + expire := c.opt.Expire + + if expire <= 0 { + expire = defaultExpire + } + + if c.userSig == "" || c.userSigExpireAt <= now.Unix() { + c.userSig, _ = sign.GenUserSig(c.opt.AppId, c.opt.AppSecret, c.opt.UserId, expire) + c.userSigExpireAt = now.Add(time.Duration(expire) * time.Second).Unix() + } + + return c.userSig +} \ No newline at end of file diff --git a/internal/sign/sign.go b/internal/sign/sign.go index c9a8eae..f259548 100644 --- a/internal/sign/sign.go +++ b/internal/sign/sign.go @@ -18,23 +18,21 @@ import ( "time" ) -// GenUserSign gen a user sign. -func GenUserSign(sdkAppId int, key string, userid string, expire int) (string, error) { - return genSign(sdkAppId, key, userid, expire, nil) +// GenUserSig gen a user sign. +func GenUserSig(sdkAppId int, key string, userid string, expire int) (string, error) { + return genUserSig(sdkAppId, key, userid, expire, nil) } // GenPrivateMapKey gen a private map. func GenPrivateMapKey(sdkAppId int, key string, userid string, expire int, roomId uint32, privilegeMap uint32) (string, error) { var userBuf []byte = genUserBuf(userid, sdkAppId, roomId, expire, privilegeMap, 0, "") - - return genSign(sdkAppId, key, userid, expire, userBuf) + return genUserSig(sdkAppId, key, userid, expire, userBuf) } // GenPrivateMapKeyWithRoomId gen a private map with room id. func GenPrivateMapKeyWithRoomId(sdkAppId int, key string, userid string, expire int, roomId string, privilegeMap uint32) (string, error) { var userBuf []byte = genUserBuf(userid, sdkAppId, 0, expire, privilegeMap, 0, roomId) - - return genSign(sdkAppId, key, userid, expire, userBuf) + return genUserSig(sdkAppId, key, userid, expire, userBuf) } // genUserBuf gen a user buffer. @@ -148,8 +146,8 @@ func hmacSha256(sdkAppId int, key string, identifier string, currTime int64, exp return base64.StdEncoding.EncodeToString(h.Sum(nil)) } -// genSign gen a sign -func genSign(sdkAppId int, key string, identifier string, expire int, userBuf []byte) (string, error) { +// genUserSig gen a sign +func genUserSig(sdkAppId int, key string, identifier string, expire int, userBuf []byte) (string, error) { currTime := time.Now().Unix() var sigDoc map[string]interface{} sigDoc = make(map[string]interface{})