Customize forward bundle titles
This commit is contained in:
+73
-5
@@ -9439,7 +9439,7 @@ func buildForwardBundle(principal *imPrincipal, sources []struct {
|
|||||||
if len(failures) > 0 {
|
if len(failures) > 0 {
|
||||||
return nil, failures
|
return nil, failures
|
||||||
}
|
}
|
||||||
userSummaries := forwardMessageUserSummaries(principal.TenantID, sourceMessages)
|
userSummaries := forwardMessageUserSummaries(principal.TenantID, sourceMessages, forwardBundleTitleUIDs(sourceTopics)...)
|
||||||
items := make([]map[string]any, 0, len(sourceMessages))
|
items := make([]map[string]any, 0, len(sourceMessages))
|
||||||
preview := make([]map[string]any, 0, min(len(sourceMessages), 3))
|
preview := make([]map[string]any, 0, min(len(sourceMessages), 3))
|
||||||
sourceRefs := make([]map[string]any, 0, len(sourceMessages))
|
sourceRefs := make([]map[string]any, 0, len(sourceMessages))
|
||||||
@@ -9467,7 +9467,7 @@ func buildForwardBundle(principal *imPrincipal, sources []struct {
|
|||||||
bundleID := "fbundle_" + store.Store.GetUidString()
|
bundleID := "fbundle_" + store.Store.GetUidString()
|
||||||
return map[string]any{
|
return map[string]any{
|
||||||
"bundle_id": bundleID,
|
"bundle_id": bundleID,
|
||||||
"title": "聊天记录",
|
"title": forwardBundleTitle(principal.TenantID, sourceTopics, userSummaries),
|
||||||
"item_count": len(items),
|
"item_count": len(items),
|
||||||
"preview": preview,
|
"preview": preview,
|
||||||
"items": items,
|
"items": items,
|
||||||
@@ -9477,12 +9477,80 @@ func buildForwardBundle(principal *imPrincipal, sources []struct {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func forwardMessageUserSummaries(tenantID types.TenantID, messages []*types.Message) map[types.Uid]map[string]any {
|
func forwardBundleTitleUIDs(sourceTopics []string) []types.Uid {
|
||||||
if store.Users == nil || len(messages) == 0 {
|
seen := make(map[types.Uid]bool)
|
||||||
|
uids := make([]types.Uid, 0, 2)
|
||||||
|
for _, topic := range sourceTopics {
|
||||||
|
if types.GetTopicCat(topic) != types.TopicCatP2P {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
uid1, uid2, err := types.ParseP2P(topic)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, uid := range []types.Uid{uid1, uid2} {
|
||||||
|
if uid.IsZero() || seen[uid] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[uid] = true
|
||||||
|
uids = append(uids, uid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uids
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardBundleTitle(tenantID types.TenantID, sourceTopics []string, userSummaries map[types.Uid]map[string]any) string {
|
||||||
|
if len(sourceTopics) == 0 {
|
||||||
|
return "聊天记录"
|
||||||
|
}
|
||||||
|
topic := sourceTopics[0]
|
||||||
|
switch types.GetTopicCat(topic) {
|
||||||
|
case types.TopicCatP2P:
|
||||||
|
uid1, uid2, err := types.ParseP2P(topic)
|
||||||
|
if err != nil {
|
||||||
|
return "聊天记录"
|
||||||
|
}
|
||||||
|
return forwardBundleDisplayName(uid1, userSummaries) + "和" + forwardBundleDisplayName(uid2, userSummaries) + "的聊天记录"
|
||||||
|
case types.TopicCatGrp:
|
||||||
|
groupName := topic
|
||||||
|
if store.Topics != nil {
|
||||||
|
if group, err := store.Topics.Get(tenantID, topic); err == nil && group != nil {
|
||||||
|
groupName = imDisplayNameFromPublic(group.Public, topic)
|
||||||
|
} else if err != nil {
|
||||||
|
logs.Warn.Printf("im message forward: failed to load group title topic=%s: %v", topic, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(groupName, "群") {
|
||||||
|
return groupName + "的聊天记录"
|
||||||
|
}
|
||||||
|
return groupName + "群的聊天记录"
|
||||||
|
default:
|
||||||
|
return "聊天记录"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardBundleDisplayName(uid types.Uid, summaries map[types.Uid]map[string]any) string {
|
||||||
|
if summary := forwardMessageUserSummary(uid.String(), summaries); summary != nil {
|
||||||
|
if name := strings.TrimSpace(fmt.Sprint(summary["display_name"])); name != "" {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uid.UserId()
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardMessageUserSummaries(tenantID types.TenantID, messages []*types.Message, extraUIDs ...types.Uid) map[types.Uid]map[string]any {
|
||||||
|
if store.Users == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
seen := make(map[types.Uid]bool)
|
seen := make(map[types.Uid]bool)
|
||||||
uids := make([]types.Uid, 0, len(messages))
|
uids := make([]types.Uid, 0, len(messages)+len(extraUIDs))
|
||||||
|
for _, uid := range extraUIDs {
|
||||||
|
if uid.IsZero() || seen[uid] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[uid] = true
|
||||||
|
uids = append(uids, uid)
|
||||||
|
}
|
||||||
for _, msg := range messages {
|
for _, msg := range messages {
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -5439,16 +5439,20 @@ func TestServeIMMessageForwardBundleSavesForwardBundle(t *testing.T) {
|
|||||||
oldSubs := store.Subs
|
oldSubs := store.Subs
|
||||||
oldMessages := store.Messages
|
oldMessages := store.Messages
|
||||||
oldUsers := store.Users
|
oldUsers := store.Users
|
||||||
|
oldTopics := store.Topics
|
||||||
subs := mock_store.NewMockSubsPersistenceInterface(ctrl)
|
subs := mock_store.NewMockSubsPersistenceInterface(ctrl)
|
||||||
messages := mock_store.NewMockMessagesPersistenceInterface(ctrl)
|
messages := mock_store.NewMockMessagesPersistenceInterface(ctrl)
|
||||||
users := mock_store.NewMockUsersPersistenceInterface(ctrl)
|
users := mock_store.NewMockUsersPersistenceInterface(ctrl)
|
||||||
|
topics := mock_store.NewMockTopicsPersistenceInterface(ctrl)
|
||||||
store.Subs = subs
|
store.Subs = subs
|
||||||
store.Messages = messages
|
store.Messages = messages
|
||||||
store.Users = users
|
store.Users = users
|
||||||
|
store.Topics = topics
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
store.Subs = oldSubs
|
store.Subs = oldSubs
|
||||||
store.Messages = oldMessages
|
store.Messages = oldMessages
|
||||||
store.Users = oldUsers
|
store.Users = oldUsers
|
||||||
|
store.Topics = oldTopics
|
||||||
})
|
})
|
||||||
|
|
||||||
subs.EXPECT().Get(types.TenantID(7), "grpTarget", types.Uid(42), false).Return(&types.Subscription{
|
subs.EXPECT().Get(types.TenantID(7), "grpTarget", types.Uid(42), false).Return(&types.Subscription{
|
||||||
@@ -5481,6 +5485,7 @@ func TestServeIMMessageForwardBundleSavesForwardBundle(t *testing.T) {
|
|||||||
TenantID: 7,
|
TenantID: 7,
|
||||||
Public: types.KVMap{"display_name": "后端-potter", "avatar_file_id": "avatar-99"},
|
Public: types.KVMap{"display_name": "后端-potter", "avatar_file_id": "avatar-99"},
|
||||||
}}, nil)
|
}}, nil)
|
||||||
|
topics.EXPECT().Get(types.TenantID(7), "grpSource").Return(&types.Topic{Public: map[string]any{"fn": "研发群"}}, nil)
|
||||||
messages.EXPECT().Save(types.TenantID(7), gomock.Any(), gomock.Nil(), true).DoAndReturn(
|
messages.EXPECT().Save(types.TenantID(7), gomock.Any(), gomock.Nil(), true).DoAndReturn(
|
||||||
func(_ types.TenantID, msg *types.Message, _ []string, _ bool) (*types.MessageSaveResult, error) {
|
func(_ types.TenantID, msg *types.Message, _ []string, _ bool) (*types.MessageSaveResult, error) {
|
||||||
if msg.Topic != "grpTarget" || msg.Head["x-im-type"] != "forward_bundle" {
|
if msg.Topic != "grpTarget" || msg.Head["x-im-type"] != "forward_bundle" {
|
||||||
@@ -5490,6 +5495,9 @@ func TestServeIMMessageForwardBundleSavesForwardBundle(t *testing.T) {
|
|||||||
if content["bundle_id"] != "fbundle_bundle-1" || content["item_count"] != 1 {
|
if content["bundle_id"] != "fbundle_bundle-1" || content["item_count"] != 1 {
|
||||||
t.Fatalf("unexpected bundle content: %#v", content)
|
t.Fatalf("unexpected bundle content: %#v", content)
|
||||||
}
|
}
|
||||||
|
if content["title"] != "研发群的聊天记录" {
|
||||||
|
t.Fatalf("unexpected bundle title: %#v", content)
|
||||||
|
}
|
||||||
bundleItems := content["items"].([]map[string]any)
|
bundleItems := content["items"].([]map[string]any)
|
||||||
itemUser := bundleItems[0]["from_user"].(map[string]any)
|
itemUser := bundleItems[0]["from_user"].(map[string]any)
|
||||||
if itemUser["user_id"] != types.Uid(99).UserId() || itemUser["display_name"] != "后端-potter" || itemUser["avatar_file_id"] != "avatar-99" {
|
if itemUser["user_id"] != types.Uid(99).UserId() || itemUser["display_name"] != "后端-potter" || itemUser["avatar_file_id"] != "avatar-99" {
|
||||||
@@ -5521,6 +5529,33 @@ func TestServeIMMessageForwardBundleSavesForwardBundle(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestForwardBundleTitleUsesP2PUsers(t *testing.T) {
|
||||||
|
uid1 := types.Uid(42)
|
||||||
|
uid2 := types.Uid(99)
|
||||||
|
title := forwardBundleTitle(types.TenantID(7), []string{uid1.P2PName(uid2)}, map[types.Uid]map[string]any{
|
||||||
|
uid1: {"display_name": "Alice"},
|
||||||
|
uid2: {"display_name": "Bob"},
|
||||||
|
})
|
||||||
|
if title != "Alice和Bob的聊天记录" {
|
||||||
|
t.Fatalf("unexpected p2p title: %s", title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestForwardBundleTitleUsesGroupName(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
oldTopics := store.Topics
|
||||||
|
topics := mock_store.NewMockTopicsPersistenceInterface(ctrl)
|
||||||
|
store.Topics = topics
|
||||||
|
t.Cleanup(func() { store.Topics = oldTopics })
|
||||||
|
|
||||||
|
topics.EXPECT().Get(types.TenantID(7), "grpSource").Return(&types.Topic{Public: map[string]any{"fn": "项目群"}}, nil)
|
||||||
|
title := forwardBundleTitle(types.TenantID(7), []string{"grpSource"}, nil)
|
||||||
|
if title != "项目群的聊天记录" {
|
||||||
|
t.Fatalf("unexpected group title: %s", title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestServeIMSecurityURLCheck(t *testing.T) {
|
func TestServeIMSecurityURLCheck(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|||||||
Reference in New Issue
Block a user