Don't 500 on channel sends with an unresolvable @mention

A channel post containing an @token that is not a syntactically valid
username (too short, leading digit, etc.) made messages.sendMessage return
500 INTERNAL_SERVER_ERROR: mentionedUserIDsFromMessage turned every
ResolveUsername error into internalErr().

Skip tokens that fail with ErrUsernameInvalid / ErrUsernameNotOccupied
instead, matching real Telegram (the message sends, the client renders the
mention and only fails to open it on tap). Only unexpected storage errors
still abort. Same fix applied to the bot send path.
This commit is contained in:
Astra 2026-09-08 11:42:03 +01:00
parent 2cfc7a0539
commit 80e99e8781
3 changed files with 52 additions and 2 deletions

View file

@ -640,6 +640,39 @@ func TestChannelUnreadMentionsRPCUsesMentionState(t *testing.T) {
}
}
// A channel post containing an @token that is not a syntactically valid
// username (too short, leading digit, etc.) must still send. Real Telegram
// renders it as a mention and only fails when the reader taps it; it never
// rejects the send. Regression for a 500 INTERNAL_SERVER_ERROR.
func TestChannelSendMessageWithUnresolvableMentionSucceeds(t *testing.T) {
ctx := context.Background()
userStore := memory.NewUserStore()
owner, _ := userStore.Create(ctx, domain.User{AccessHash: 9201, Phone: "15550009201", FirstName: "Owner", Username: "owner_badmention"})
channelStore := memory.NewChannelStore()
channelService := appchannels.NewService(channelStore)
r := New(Config{}, Deps{
Users: appusers.NewService(userStore),
Channels: channelService,
}, zaptest.NewLogger(t), clock.System)
created, err := channelService.CreateMegagroupFromCreateChat(ctx, owner.ID, domain.CreateChannelRequest{
Title: "Bad Mention",
Date: 1700009201,
})
if err != nil {
t.Fatalf("create megagroup: %v", err)
}
peer := &tg.InputPeerChannel{ChannelID: created.Channel.ID, AccessHash: created.Channel.AccessHash}
for i, text := range []string{"look at @zio", "hi @2cool and @_x"} {
if _, err := r.onMessagesSendMessage(WithUserID(ctx, owner.ID), &tg.MessagesSendMessageRequest{
Peer: peer,
Message: text,
RandomID: int64(9202001 + i),
}); err != nil {
t.Fatalf("send %q: unexpected error %v", text, err)
}
}
}
func TestChannelDifferenceIncludesExtraForwardSourceChannel(t *testing.T) {
channel := domain.Channel{ID: 2000000100, AccessHash: 9010, Title: "Megagroup", Megagroup: true, Date: 1700000000, Pts: 3}
source := domain.Channel{ID: 2000000101, AccessHash: 9011, Title: "Source", Broadcast: true, Date: 1700000000}