fix(messages): sync Android pinned message search
This commit is contained in:
parent
90649b5b67
commit
5401c9a364
4 changed files with 35 additions and 5 deletions
|
|
@ -97,12 +97,17 @@ func TestChannelMultiPinAndroidOpenAndJump(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ① 打开聊天:MediaDataController.loadPinnedMessages → messages.search filterPinned。
|
// ① 打开聊天:MediaDataController.loadPinnedMessages → messages.search filterPinned。
|
||||||
searchEnc := dispatch(&tg.MessagesSearchRequest{
|
androidPinnedSearch := &tg.MessagesSearchRequest{
|
||||||
Peer: peer,
|
Peer: peer,
|
||||||
Q: "",
|
Q: "",
|
||||||
Filter: &tg.InputMessagesFilterPinned{},
|
Filter: &tg.InputMessagesFilterPinned{},
|
||||||
Limit: 40,
|
Limit: 40,
|
||||||
})
|
}
|
||||||
|
// DrKLO initializes saved_reaction to an empty non-nil ArrayList and its
|
||||||
|
// serializer consequently emits flags.3 + Vector length 0 on every
|
||||||
|
// messages.search, including channel filterPinned.
|
||||||
|
androidPinnedSearch.SetSavedReaction([]tg.ReactionClass{})
|
||||||
|
searchEnc := dispatch(androidPinnedSearch)
|
||||||
channelMessages, ok := searchEnc.(*tg.MessagesChannelMessages)
|
channelMessages, ok := searchEnc.(*tg.MessagesChannelMessages)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("pinned search response = %T, want messages.channelMessages", searchEnc)
|
t.Fatalf("pinned search response = %T, want messages.channelMessages", searchEnc)
|
||||||
|
|
|
||||||
|
|
@ -804,8 +804,13 @@ func (r *Router) messageFilterFromSearchRequest(ctx context.Context, userID int6
|
||||||
filter.Peer = peer
|
filter.Peer = peer
|
||||||
}
|
}
|
||||||
savedReactions, hasSavedReactions := req.GetSavedReaction()
|
savedReactions, hasSavedReactions := req.GetSavedReaction()
|
||||||
|
// An empty optional vector carries no reaction-filtering semantics. Some TL
|
||||||
|
// clients emit flags.3 with a zero-length vector on ordinary peer searches.
|
||||||
|
// Keep the wire presence intact at the TL edge, but only apply Saved
|
||||||
|
// Messages scope and reaction validation when the vector has values.
|
||||||
|
hasSavedReactionFilter := hasSavedReactions && len(savedReactions) > 0
|
||||||
savedPeerInput, hasSavedPeer := req.GetSavedPeerID()
|
savedPeerInput, hasSavedPeer := req.GetSavedPeerID()
|
||||||
if hasSavedReactions || hasSavedPeer {
|
if hasSavedReactionFilter || hasSavedPeer {
|
||||||
if !filter.HasPeer ||
|
if !filter.HasPeer ||
|
||||||
filter.Peer != (domain.Peer{Type: domain.PeerTypeUser, ID: userID}) {
|
filter.Peer != (domain.Peer{Type: domain.PeerTypeUser, ID: userID}) {
|
||||||
return domain.MessageFilter{}, peerIDInvalidErr()
|
return domain.MessageFilter{}, peerIDInvalidErr()
|
||||||
|
|
@ -821,8 +826,8 @@ func (r *Router) messageFilterFromSearchRequest(ctx context.Context, userID int6
|
||||||
}
|
}
|
||||||
filter.SavedPeer = savedPeer
|
filter.SavedPeer = savedPeer
|
||||||
}
|
}
|
||||||
if hasSavedReactions {
|
if hasSavedReactionFilter {
|
||||||
if len(savedReactions) == 0 || len(savedReactions) > maxReactionVector {
|
if len(savedReactions) > maxReactionVector {
|
||||||
return domain.MessageFilter{}, reactionInvalidErr()
|
return domain.MessageFilter{}, reactionInvalidErr()
|
||||||
}
|
}
|
||||||
seen := make(map[string]struct{}, len(savedReactions))
|
seen := make(map[string]struct{}, len(savedReactions))
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,9 @@ func TestMessagesSearchChannelPeerReturnsSingleCopyMessages(t *testing.T) {
|
||||||
Filter: &tg.InputMessagesFilterPhotos{},
|
Filter: &tg.InputMessagesFilterPhotos{},
|
||||||
Limit: 0,
|
Limit: 0,
|
||||||
}
|
}
|
||||||
|
// Match DrKLO's ordinary messages.search wire shape: flags.3 is present
|
||||||
|
// even though the saved_reaction vector is empty.
|
||||||
|
mediaCountReq.SetSavedReaction([]tg.ReactionClass{})
|
||||||
in.Reset()
|
in.Reset()
|
||||||
if err := mediaCountReq.Encode(&in); err != nil {
|
if err := mediaCountReq.Encode(&in); err != nil {
|
||||||
t.Fatalf("encode shared media count search: %v", err)
|
t.Fatalf("encode shared media count search: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,23 @@ func TestMessageFilterFromSearchRequestParsesSavedTagsAndPeer(t *testing.T) {
|
||||||
if _, err := r.messageFilterFromSearchRequest(WithUserID(context.Background(), userID), userID, req); !tgerr.Is(err, "PEER_ID_INVALID") {
|
if _, err := r.messageFilterFromSearchRequest(WithUserID(context.Background(), userID), userID, req); !tgerr.Is(err, "PEER_ID_INVALID") {
|
||||||
t.Fatalf("non-self saved search err = %v, want PEER_ID_INVALID", err)
|
t.Fatalf("non-self saved search err = %v, want PEER_ID_INVALID", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emptyTagReq := &tg.MessagesSearchRequest{
|
||||||
|
Peer: &tg.InputPeerUser{UserID: userID + 1, AccessHash: 1},
|
||||||
|
Q: "ordinary",
|
||||||
|
Filter: &tg.InputMessagesFilterEmpty{},
|
||||||
|
Limit: 20,
|
||||||
|
}
|
||||||
|
emptyTagReq.SetSavedReaction([]tg.ReactionClass{})
|
||||||
|
ordinary, err := r.messageFilterFromSearchRequest(WithUserID(context.Background(), userID), userID, emptyTagReq)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("empty saved reaction on ordinary peer search: %v", err)
|
||||||
|
}
|
||||||
|
if !ordinary.HasPeer ||
|
||||||
|
ordinary.Peer != (domain.Peer{Type: domain.PeerTypeUser, ID: userID + 1}) ||
|
||||||
|
len(ordinary.SavedReactions) != 0 {
|
||||||
|
t.Fatalf("ordinary peer filter with empty saved reaction = %+v", ordinary)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMessagesGetDefaultTagReactionsReturnsHashableCatalog(t *testing.T) {
|
func TestMessagesGetDefaultTagReactionsReturnsHashableCatalog(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue