chore: refresh gramsrv public release

This commit is contained in:
A 2026-06-30 14:37:43 +08:00
parent 75cebe8dbf
commit 70b6820474
1274 changed files with 378751 additions and 59919 deletions

View file

@ -0,0 +1,176 @@
package rpc
import (
"context"
"fmt"
"github.com/gotd/td/clock"
"github.com/gotd/td/tg"
"go.uber.org/zap/zaptest"
appchannels "telesrv/internal/app/channels"
appusers "telesrv/internal/app/users"
"telesrv/internal/domain"
"telesrv/internal/store/memory"
"testing"
)
func TestLegacyChannelSettingsRPC(t *testing.T) {
ctx := context.Background()
userStore := memory.NewUserStore()
owner, _ := userStore.Create(ctx, domain.User{AccessHash: 81, Phone: "15550002181", FirstName: "Owner"})
friend, _ := userStore.Create(ctx, domain.User{AccessHash: 82, Phone: "15550002182", FirstName: "Friend"})
channelStore := memory.NewChannelStore()
r := New(Config{}, Deps{
Users: appusers.NewService(userStore),
Channels: appchannels.NewService(channelStore),
}, zaptest.NewLogger(t), clock.System)
created, err := r.onMessagesCreateChat(WithUserID(ctx, owner.ID), &tg.MessagesCreateChatRequest{
Users: []tg.InputUserClass{&tg.InputUser{UserID: friend.ID, AccessHash: friend.AccessHash}},
Title: "Legacy Settings Group",
})
if err != nil {
t.Fatalf("create chat: %v", err)
}
channel := created.Updates.(*tg.Updates).Chats[0].(*tg.Channel)
peer := &tg.InputPeerChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash}
themeUpdates, err := r.onMessagesSetChatTheme(WithUserID(ctx, owner.ID), &tg.MessagesSetChatThemeRequest{Peer: peer})
if err != nil {
t.Fatalf("set chat theme channel peer: %v", err)
}
if len(themeUpdates.(*tg.Updates).Chats) != 1 {
t.Fatalf("set chat theme updates = %+v, want channel context", themeUpdates)
}
privateTheme, err := r.onMessagesSetChatTheme(WithUserID(ctx, owner.ID), &tg.MessagesSetChatThemeRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Theme: &tg.InputChatThemeEmpty{},
})
if err != nil {
t.Fatalf("set chat theme private peer: %v", err)
}
if len(privateTheme.(*tg.Updates).Updates) != 0 {
t.Fatalf("private set chat theme updates = %+v, want empty compat ack", privateTheme)
}
reactionUpdates, err := r.onMessagesSetChatAvailableReactions(WithUserID(ctx, owner.ID), &tg.MessagesSetChatAvailableReactionsRequest{
Peer: peer,
AvailableReactions: &tg.ChatReactionsSome{Reactions: []tg.ReactionClass{&tg.ReactionEmoji{Emoticon: "\U0001f44d"}}},
ReactionsLimit: 8,
})
if err != nil {
t.Fatalf("set available reactions: %v", err)
}
if len(reactionUpdates.(*tg.Updates).Chats) != 1 {
t.Fatalf("set reactions updates = %+v, want channel state update", reactionUpdates)
}
full, err := r.onChannelsGetFullChannel(WithUserID(ctx, owner.ID), &tg.InputChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash})
if err != nil {
t.Fatalf("get full channel after reactions: %v", err)
}
fullChannel := full.FullChat.(*tg.ChannelFull)
reactions, ok := fullChannel.GetAvailableReactions()
if !ok {
t.Fatalf("full channel reactions missing after set")
}
some, ok := reactions.(*tg.ChatReactionsSome)
if !ok || len(some.Reactions) != 1 {
t.Fatalf("full channel reactions = %#v, want one explicit reaction", reactions)
}
if fullChannel.ReactionsLimit != 8 {
t.Fatalf("full channel reactions limit = %d, want 8", fullChannel.ReactionsLimit)
}
if _, err := r.onMessagesSetChatAvailableReactions(WithUserID(ctx, owner.ID), &tg.MessagesSetChatAvailableReactionsRequest{
Peer: peer,
AvailableReactions: &tg.ChatReactionsSome{Reactions: make([]tg.ReactionClass, domain.MaxChannelReactionTypes+1)},
}); err == nil {
t.Fatalf("set too many reactions err = nil, want limit error")
}
noForwards, err := r.onMessagesToggleNoForwards(WithUserID(ctx, owner.ID), &tg.MessagesToggleNoForwardsRequest{
Peer: peer,
Enabled: true,
})
if err != nil {
t.Fatalf("toggle noforwards: %v", err)
}
if got := noForwards.(*tg.Updates).Chats[0].(*tg.Channel); !got.Noforwards {
t.Fatalf("noforwards channel = %+v, want enabled", got)
}
sent, err := r.onMessagesSendMessage(WithUserID(ctx, owner.ID), &tg.MessagesSendMessageRequest{
Peer: peer,
Message: "protected content",
RandomID: 8181,
})
if err != nil {
t.Fatalf("send protected message: %v", err)
}
msg := sent.(*tg.Updates).Updates[1].(*tg.UpdateNewChannelMessage).Message.(*tg.Message)
if !msg.Noforwards {
t.Fatalf("protected channel message = %+v, want noforwards inherited", msg)
}
}
// TestBroadcastChannelAcceptsFullReactionCatalog 复现并锁定真机 bug:广播频道开启
// reactions 时,DrKLO 把「启用全部标准 reaction」发成显式 chatReactionsSome 列表
// (megagroup 走 chatReactionsAll),列表长度等于 getAvailableReactions 目录大小
// (当前 ~74)。此前 MaxChannelReactionItems=64 把它误判成 LIMIT_INVALID。修复后
// 任何不超过 MaxChannelReactionTypes 的列表都必须被接受。
func TestBroadcastChannelAcceptsFullReactionCatalog(t *testing.T) {
ctx := context.Background()
userStore := memory.NewUserStore()
owner, _ := userStore.Create(ctx, domain.User{AccessHash: 91, Phone: "15550002191", FirstName: "Owner"})
channelStore := memory.NewChannelStore()
r := New(Config{}, Deps{
Users: appusers.NewService(userStore),
Channels: appchannels.NewService(channelStore),
}, zaptest.NewLogger(t), clock.System)
created, err := r.onChannelsCreateChannel(WithUserID(ctx, owner.ID), &tg.ChannelsCreateChannelRequest{
Title: "Broadcast Reactions",
Broadcast: true,
})
if err != nil {
t.Fatalf("create broadcast channel: %v", err)
}
channel := created.(*tg.Updates).Chats[0].(*tg.Channel)
if channel.Megagroup {
t.Fatalf("created channel = %+v, want broadcast (not megagroup)", channel)
}
peer := &tg.InputPeerChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash}
// 用一个明显超过旧上限(64)的目录大小,证明修复生效。每个 emoticon 取互不相同
// 的合法短串即可(验证只关心非空且 rune 数 <= MaxChannelReactionEmoticonLength)。
const catalogSize = 74
if catalogSize <= 64 || catalogSize > domain.MaxChannelReactionTypes {
t.Fatalf("test catalog size %d must exceed the old 64 cap and stay within %d",
catalogSize, domain.MaxChannelReactionTypes)
}
reactions := make([]tg.ReactionClass, 0, catalogSize)
for i := 0; i < catalogSize; i++ {
reactions = append(reactions, &tg.ReactionEmoji{Emoticon: fmt.Sprintf("r%02d", i)})
}
updates, err := r.onMessagesSetChatAvailableReactions(WithUserID(ctx, owner.ID), &tg.MessagesSetChatAvailableReactionsRequest{
Peer: peer,
AvailableReactions: &tg.ChatReactionsSome{Reactions: reactions},
ReactionsLimit: 11,
})
if err != nil {
t.Fatalf("set full-catalog reactions on broadcast channel: %v", err)
}
if len(updates.(*tg.Updates).Chats) != 1 {
t.Fatalf("set reactions updates = %+v, want channel state update", updates)
}
full, err := r.onChannelsGetFullChannel(WithUserID(ctx, owner.ID), &tg.InputChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash})
if err != nil {
t.Fatalf("get full channel after reactions: %v", err)
}
fullChannel := full.FullChat.(*tg.ChannelFull)
stored, ok := fullChannel.GetAvailableReactions()
if !ok {
t.Fatalf("full channel reactions missing after set")
}
some, ok := stored.(*tg.ChatReactionsSome)
if !ok || len(some.Reactions) != catalogSize {
t.Fatalf("full channel reactions = %#v, want %d explicit reactions", stored, catalogSize)
}
}