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

@ -37,7 +37,7 @@ func TestSendPrivateMediaSurvivesUpdateEvent(t *testing.T) {
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", ids)
})
messages := NewMessageStore(pool, WithMessageAllocators(&perUserCounterAllocator{}, &perUserCounterAllocator{}))
messages := NewMessageStore(pool, WithMessageAllocators(&perUserCounterAllocator{}))
media := &domain.MessageMedia{
Kind: domain.MessageMediaKindDocument,
@ -97,6 +97,225 @@ func TestSendPrivateMediaSurvivesUpdateEvent(t *testing.T) {
}
}
func TestEditPrivateTodoMediaByParticipantPostgres(t *testing.T) {
pool := testPool(t)
ctx := context.Background()
suffix := randomSuffix(t)
users := NewUserStore(pool)
sender, err := users.Create(ctx, domain.User{AccessHash: 65, Phone: "+1998" + suffix + "05", FirstName: "TodoSender"})
if err != nil {
t.Fatalf("create sender: %v", err)
}
recipient, err := users.Create(ctx, domain.User{AccessHash: 66, Phone: "+1998" + suffix + "06", FirstName: "TodoRecipient"})
if err != nil {
t.Fatalf("create recipient: %v", err)
}
ids := []int64{sender.ID, recipient.ID}
t.Cleanup(func() {
_, _ = pool.Exec(ctx, "DELETE FROM dispatch_outbox WHERE target_user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM user_update_events WHERE user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM message_boxes WHERE owner_user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM private_messages WHERE sender_user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM dialogs WHERE user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", ids)
})
messages := NewMessageStore(pool, WithMessageAllocators(&perUserCounterAllocator{}))
base := &domain.MessageMedia{
Kind: domain.MessageMediaKindTodo,
Todo: &domain.MessageTodo{
Title: "shared todo",
OthersCanComplete: true,
Items: []domain.MessageTodoItem{{ID: 1, Title: "one"}},
},
}
sent, err := messages.SendPrivateText(ctx, domain.SendPrivateTextRequest{
SenderUserID: sender.ID,
RecipientUserID: recipient.ID,
RandomID: time.Now().UnixNano(),
Message: "",
Media: base,
Date: int(time.Now().Unix()),
})
if err != nil {
t.Fatalf("send private todo: %v", err)
}
updated := &domain.MessageMedia{
Kind: domain.MessageMediaKindTodo,
Todo: &domain.MessageTodo{
Title: base.Todo.Title,
OthersCanComplete: true,
Items: append([]domain.MessageTodoItem(nil), base.Todo.Items...),
Completions: []domain.MessageTodoCompletion{{ID: 1, CompletedBy: recipient.ID, Date: 1700000700}},
},
}
edited, err := messages.EditMessage(ctx, domain.EditMessageRequest{
OwnerUserID: recipient.ID,
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: sender.ID},
ID: sent.RecipientMessage.ID,
Message: "",
Media: updated,
EditDate: 1700000700,
AllowTodoParticipantMutation: true,
})
if err != nil {
t.Fatalf("participant edit todo media: %v", err)
}
if len(edited.Edited) != 2 {
t.Fatalf("edited boxes = %d, want sender and recipient", len(edited.Edited))
}
senderView, err := messages.GetByIDs(ctx, sender.ID, []int{sent.SenderMessage.ID})
if err != nil {
t.Fatalf("sender get by ids: %v", err)
}
if len(senderView.Messages) != 1 || senderView.Messages[0].Media == nil || senderView.Messages[0].Media.Todo == nil {
t.Fatalf("sender todo media = %+v, want todo", senderView.Messages)
}
got := senderView.Messages[0].Media.Todo.Completions
if len(got) != 1 || got[0].ID != 1 || got[0].CompletedBy != recipient.ID {
t.Fatalf("sender completions = %+v, want recipient completed item", got)
}
}
func TestEditChannelTodoMediaByParticipantPostgres(t *testing.T) {
pool := testPool(t)
ctx := context.Background()
suffix := randomSuffix(t)
users := NewUserStore(pool)
owner, err := users.Create(ctx, domain.User{AccessHash: 67, Phone: "+1998" + suffix + "07", FirstName: "TodoChannelOwner"})
if err != nil {
t.Fatalf("create owner: %v", err)
}
member, err := users.Create(ctx, domain.User{AccessHash: 68, Phone: "+1998" + suffix + "08", FirstName: "TodoChannelMember"})
if err != nil {
t.Fatalf("create member: %v", err)
}
var channelID int64
t.Cleanup(func() {
if channelID != 0 {
_, _ = pool.Exec(ctx, "DELETE FROM channels WHERE id = $1", channelID)
}
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", []int64{owner.ID, member.ID})
})
channels := NewChannelStore(pool)
created, err := channels.CreateChannel(ctx, domain.CreateChannelRequest{
CreatorUserID: owner.ID,
Title: "Todo Channel " + suffix,
Megagroup: true,
MemberUserIDs: []int64{member.ID},
Date: 1700000710,
})
if err != nil {
t.Fatalf("create channel: %v", err)
}
channelID = created.Channel.ID
base := &domain.MessageMedia{
Kind: domain.MessageMediaKindTodo,
Todo: &domain.MessageTodo{
Title: "group todo",
OthersCanAppend: true,
OthersCanComplete: true,
Items: []domain.MessageTodoItem{{ID: 1, Title: "one"}, {ID: 2, Title: "two"}},
},
}
sent, err := channels.SendChannelMessage(ctx, domain.SendChannelMessageRequest{
UserID: owner.ID,
ChannelID: channelID,
RandomID: time.Now().UnixNano(),
Media: base,
Date: 1700000711,
})
if err != nil {
t.Fatalf("send channel todo: %v", err)
}
updated := &domain.MessageMedia{
Kind: domain.MessageMediaKindTodo,
Todo: &domain.MessageTodo{
Title: base.Todo.Title,
OthersCanAppend: true,
OthersCanComplete: true,
Items: append([]domain.MessageTodoItem(nil), base.Todo.Items...),
Completions: []domain.MessageTodoCompletion{{ID: 1, CompletedBy: member.ID, Date: 1700000712}},
},
}
edited, err := channels.EditChannelMessage(ctx, domain.EditChannelMessageRequest{
UserID: member.ID,
ChannelID: channelID,
ID: sent.Message.ID,
Media: updated,
AllowTodoParticipantMutation: true,
TodoServiceAction: &domain.ChannelMessageAction{
Type: domain.ChannelActionTodoCompletions,
Completed: []int{1},
},
EditDate: 1700000712,
})
if err != nil {
t.Fatalf("participant edit channel todo media: %v", err)
}
if edited.Event.Pts != sent.Event.Pts+1 || edited.ServiceEvent.Pts != edited.Event.Pts+1 {
t.Fatalf("todo channel pts edit=%d service=%d after send=%d, want two contiguous pts", edited.Event.Pts, edited.ServiceEvent.Pts, sent.Event.Pts)
}
if edited.ServiceMessage.Action == nil || edited.ServiceMessage.Action.Type != domain.ChannelActionTodoCompletions {
t.Fatalf("service action = %+v, want todo completions", edited.ServiceMessage.Action)
}
if edited.ServiceMessage.ReplyTo == nil || edited.ServiceMessage.ReplyTo.MessageID != sent.Message.ID {
t.Fatalf("service reply = %+v, want original message %d", edited.ServiceMessage.ReplyTo, sent.Message.ID)
}
history, err := channels.GetChannelMessages(ctx, member.ID, channelID, []int{sent.Message.ID, edited.ServiceMessage.ID})
if err != nil {
t.Fatalf("get channel todo messages: %v", err)
}
if len(history.Messages) != 2 {
t.Fatalf("history messages = %d, want original + service", len(history.Messages))
}
var foundOriginal, foundService bool
for _, msg := range history.Messages {
switch msg.ID {
case sent.Message.ID:
foundOriginal = true
if msg.Media == nil || msg.Media.Todo == nil || len(msg.Media.Todo.Completions) != 1 || msg.Media.Todo.Completions[0].CompletedBy != member.ID {
t.Fatalf("stored todo media = %+v, want member completion", msg.Media)
}
case edited.ServiceMessage.ID:
foundService = true
if msg.Action == nil || msg.Action.Type != domain.ChannelActionTodoCompletions {
t.Fatalf("stored service action = %+v, want todo completions", msg.Action)
}
}
}
if !foundOriginal || !foundService {
t.Fatalf("history = %+v, missing original=%v service=%v", history.Messages, foundOriginal, foundService)
}
diff, err := channels.ListChannelDifference(ctx, domain.ChannelDifferenceRequest{
UserID: member.ID,
ChannelID: channelID,
Pts: sent.Event.Pts,
Limit: 10,
})
if err != nil {
t.Fatalf("list channel difference: %v", err)
}
if diff.Pts != edited.ServiceEvent.Pts {
t.Fatalf("diff pts = %d, want service pts %d", diff.Pts, edited.ServiceEvent.Pts)
}
if len(diff.OtherUpdates) != 1 || diff.OtherUpdates[0].Type != domain.ChannelUpdateEditMessage || diff.OtherUpdates[0].Pts != edited.Event.Pts {
t.Fatalf("diff other updates = %+v, want edit event", diff.OtherUpdates)
}
if len(diff.NewMessages) != 1 || diff.NewMessages[0].ID != edited.ServiceMessage.ID || diff.NewMessages[0].Action == nil {
t.Fatalf("diff new messages = %+v, want todo service message", diff.NewMessages)
}
}
func TestSendChannelMediaSurvivesDifference(t *testing.T) {
pool := testPool(t)
ctx := context.Background()