hyapp-server/pkg/tencentim/rest_client_real_test.go
2026-06-17 23:13:08 +08:00

166 lines
5.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tencentim
import (
"context"
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"testing"
"time"
)
func TestRealTencentIMCreateSendAndDestroyGroup(t *testing.T) {
if os.Getenv("TENCENT_IM_REAL_TEST") != "1" {
t.Skip("set TENCENT_IM_REAL_TEST=1 and Tencent IM env vars to run the real REST smoke test")
}
cfg := realRESTConfigFromEnv(t)
client, err := NewRESTClient(cfg)
if err != nil {
t.Fatalf("NewRESTClient failed: %v", err)
}
nowMS := time.Now().UTC().UnixMilli()
groupID := fmt.Sprintf("hy_codex_bc_r_%d", nowMS)
eventID := fmt.Sprintf("codex_real_im_%d", nowMS)
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
// 真实 IM 测试必须使用临时 GroupID避免污染业务全局/区域播报群。
if err := client.EnsureGroup(ctx, GroupSpec{
GroupID: groupID,
Name: "codex real im smoke",
Type: DefaultGroupType,
ApplyJoinOption: "FreeAccess",
}); err != nil {
t.Fatalf("real Tencent IM create group failed: %v", err)
}
t.Cleanup(func() {
cleanupCtx, cleanupCancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cleanupCancel()
if err := client.DestroyGroup(cleanupCtx, groupID); err != nil {
t.Errorf("real Tencent IM destroy group cleanup failed: %v", err)
}
})
memberUserID := nowMS % 9_000_000_000
if err := realImportAccount(ctx, client, memberUserID); err != nil {
t.Fatalf("real Tencent IM account import failed: %v", err)
}
c2cEventID := fmt.Sprintf("codex_real_im_c2c_%d", nowMS)
c2cPayload, err := json.Marshal(map[string]any{
"event_id": c2cEventID,
"event_type": "codex_real_im_c2c_probe",
"sent_at_ms": nowMS,
})
if err != nil {
t.Fatalf("marshal c2c smoke payload failed: %v", err)
}
if err := client.PublishUserCustomMessage(ctx, CustomUserMessage{
ToAccount: strconv.FormatInt(memberUserID, 10),
EventID: c2cEventID,
Desc: "codex_real_im_c2c_probe",
Ext: "im_c2c_smoke",
PayloadJSON: c2cPayload,
}); err != nil {
t.Fatalf("real Tencent IM send C2C custom message failed: %v", err)
}
if err := realAddGroupMember(ctx, client, groupID, memberUserID); err != nil {
t.Fatalf("real Tencent IM add group member failed: %v", err)
}
payload, err := json.Marshal(map[string]any{
"event_id": eventID,
"broadcast_type": "codex_real_im_smoke",
"scope": "region",
"app_code": "codex",
"region_id": 210,
"sent_at_ms": nowMS,
"action": map[string]any{
"type": "enter_room",
"room_id": "codex-room-smoke",
},
})
if err != nil {
t.Fatalf("marshal smoke payload failed: %v", err)
}
// 真正向腾讯云 IM REST 发送 TIMCustomElem成功只表示腾讯服务端接受消息不代表有客户端在线展示。
if err := client.PublishGroupCustomMessage(ctx, CustomGroupMessage{
GroupID: groupID,
EventID: eventID,
Desc: "codex_real_im_smoke",
Ext: "im_broadcast",
PayloadJSON: payload,
}); err != nil {
t.Fatalf("real Tencent IM send group custom message failed: %v", err)
}
if err := client.DeleteGroupMember(ctx, groupID, memberUserID); err != nil {
t.Fatalf("real Tencent IM delete group member failed: %v", err)
}
t.Logf("real Tencent IM smoke passed: sdk_app_id=%d group_id=%s group_event_id=%s c2c_event_id=%s removed_user_id=%d", cfg.SDKAppID, groupID, eventID, c2cEventID, memberUserID)
}
func realImportAccount(ctx context.Context, client *RESTClient, userID int64) error {
return client.ImportAccount(ctx, AccountProfile{
UserID: userID,
Nick: "codex-im-smoke",
})
}
func realAddGroupMember(ctx context.Context, client *RESTClient, groupID string, userID int64) error {
var response restResponse
if err := client.post(ctx, "v4/group_open_http_svc/add_group_member", map[string]any{
"GroupId": groupID,
"Silence": 1,
"MemberList": []map[string]any{
{"Member_Account": strconv.FormatInt(userID, 10)},
},
}, &response); err != nil {
return err
}
return response.err()
}
func realRESTConfigFromEnv(t *testing.T) RESTConfig {
t.Helper()
sdkAppID, err := strconv.ParseInt(requiredEnv(t, "TENCENT_IM_SDK_APP_ID"), 10, 64)
if err != nil || sdkAppID <= 0 {
t.Fatalf("TENCENT_IM_SDK_APP_ID is invalid")
}
endpoint := strings.TrimSpace(os.Getenv("TENCENT_IM_ENDPOINT"))
if endpoint == "" {
endpoint = DefaultEndpoint
}
adminUserSigTTL := time.Hour
if rawTTL := strings.TrimSpace(os.Getenv("TENCENT_IM_ADMIN_USERSIG_TTL")); rawTTL != "" {
parsed, err := time.ParseDuration(rawTTL)
if err != nil || parsed <= 0 {
t.Fatalf("TENCENT_IM_ADMIN_USERSIG_TTL is invalid")
}
adminUserSigTTL = parsed
}
return RESTConfig{
SDKAppID: sdkAppID,
SecretKey: requiredEnv(t, "TENCENT_IM_SECRET_KEY"),
AdminIdentifier: requiredEnv(t, "TENCENT_IM_ADMIN_IDENTIFIER"),
AdminUserSigTTL: adminUserSigTTL,
Endpoint: endpoint,
GroupType: DefaultGroupType,
}
}
func requiredEnv(t *testing.T, key string) string {
t.Helper()
value := strings.TrimSpace(os.Getenv(key))
if value == "" {
t.Fatalf("%s is required for real Tencent IM smoke test", key)
}
return value
}