owpengram-server/internal/rpc/messages_scheduled_ttl_test.go

232 lines
9.4 KiB
Go

package rpc
import (
"context"
"github.com/iamxvbaba/td/tg"
"go.uber.org/zap/zaptest"
"telesrv/internal/domain"
"testing"
"time"
)
func TestScheduledMessagesLifecycleUsesScheduledStore(t *testing.T) {
const (
aliceID = int64(1000000001)
bobID = int64(1000000002)
now = int64(1700001000)
)
alice := domain.User{ID: aliceID, AccessHash: 11, FirstName: "Alice"}
bob := domain.User{ID: bobID, AccessHash: 22, FirstName: "Bob"}
messages := &scheduledCaptureMessages{captureMessages: &captureMessages{}}
r := New(Config{}, Deps{
Messages: messages,
Users: mapUsersService{users: map[int64]domain.User{aliceID: alice, bobID: bob}},
}, zaptest.NewLogger(t), fixedClock{now: time.Unix(now, 0)})
ctx := WithUserID(context.Background(), aliceID)
sendReq := &tg.MessagesSendMessageRequest{
Peer: &tg.InputPeerUser{UserID: bobID, AccessHash: bob.AccessHash},
Message: "later",
RandomID: 123456,
}
sendReq.SetScheduleDate(int(now + 3600))
updates, err := r.onMessagesSendMessage(ctx, sendReq)
if err != nil {
t.Fatalf("send scheduled message: %v", err)
}
if messages.scheduleReq.OwnerUserID != aliceID || messages.scheduleReq.Peer.ID != bobID || messages.scheduleReq.ScheduleDate != int(now+3600) {
t.Fatalf("schedule req = %+v, want alice->bob at requested date", messages.scheduleReq)
}
gotUpdates := updates.(*tg.Updates).Updates
if len(gotUpdates) != 2 {
t.Fatalf("scheduled send updates = %+v, want id + new scheduled", gotUpdates)
}
newScheduled, ok := gotUpdates[1].(*tg.UpdateNewScheduledMessage)
if !ok {
t.Fatalf("scheduled update = %T, want UpdateNewScheduledMessage", gotUpdates[1])
}
scheduledMsg, ok := newScheduled.Message.(*tg.Message)
if !ok || !scheduledMsg.FromScheduled || scheduledMsg.Message != "later" || scheduledMsg.Date != int(now+3600) {
t.Fatalf("scheduled message = %#v, want from_scheduled later at schedule date", newScheduled.Message)
}
history, err := r.onMessagesGetScheduledHistory(ctx, &tg.MessagesGetScheduledHistoryRequest{
Peer: &tg.InputPeerUser{UserID: bobID, AccessHash: bob.AccessHash},
})
if err != nil {
t.Fatalf("get scheduled history: %v", err)
}
if list := history.(*tg.MessagesMessages).Messages; len(list) != 1 {
t.Fatalf("scheduled history = %+v, want one message", list)
}
editReq := &tg.MessagesEditMessageRequest{
Peer: &tg.InputPeerUser{UserID: bobID, AccessHash: bob.AccessHash},
ID: scheduledMsg.ID,
}
editReq.SetMessage("edited")
editReq.SetScheduleDate(int(now + 7200))
edited, err := r.onMessagesEditMessage(ctx, editReq)
if err != nil {
t.Fatalf("edit scheduled message: %v", err)
}
if messages.editScheduledReq.ID != scheduledMsg.ID || !messages.editScheduledReq.SetMessage || messages.editScheduledReq.Message != "edited" || messages.editScheduledReq.ScheduleDate != int(now+7200) {
t.Fatalf("edit scheduled req = %+v, want updated scheduled text/date", messages.editScheduledReq)
}
editedMessage := edited.(*tg.Updates).Updates[0].(*tg.UpdateNewScheduledMessage).Message.(*tg.Message)
if !editedMessage.FromScheduled || editedMessage.Message != "edited" || editedMessage.Date != int(now+7200) {
t.Fatalf("edited scheduled message = %#v, want edited future scheduled item", editedMessage)
}
sent, err := r.onMessagesSendScheduledMessages(ctx, &tg.MessagesSendScheduledMessagesRequest{
Peer: &tg.InputPeerUser{UserID: bobID, AccessHash: bob.AccessHash},
ID: []int{scheduledMsg.ID},
})
if err != nil {
t.Fatalf("send scheduled now: %v", err)
}
if messages.sendReq.Message != "edited" || messages.markedScheduledID != scheduledMsg.ID || messages.markedSentID == 0 {
t.Fatalf("sent scheduled state send=%+v marked scheduled=%d sent=%d", messages.sendReq, messages.markedScheduledID, messages.markedSentID)
}
var deleteUpdate *tg.UpdateDeleteScheduledMessages
for _, update := range sent.(*tg.Updates).Updates {
if v, ok := update.(*tg.UpdateDeleteScheduledMessages); ok {
deleteUpdate = v
}
}
if deleteUpdate == nil || len(deleteUpdate.Messages) != 1 || deleteUpdate.Messages[0] != scheduledMsg.ID {
t.Fatalf("send scheduled delete update = %#v, want deleted scheduled id", deleteUpdate)
}
if sentIDs, ok := deleteUpdate.GetSentMessages(); !ok || len(sentIDs) != 1 || sentIDs[0] != messages.markedSentID {
t.Fatalf("delete scheduled sent ids = %+v ok %v, want sent message id %d", sentIDs, ok, messages.markedSentID)
}
}
func TestScheduledMessageEditDateOnlyPreservesContent(t *testing.T) {
const (
aliceID = int64(1000000001)
bobID = int64(1000000002)
now = int64(1700003000)
)
media := &domain.MessageMedia{
Kind: domain.MessageMediaKindDocument,
Document: &domain.Document{ID: 910000000000000001, AccessHash: 91, DCID: 2},
}
peer := domain.Peer{Type: domain.PeerTypeUser, ID: bobID}
messages := &scheduledCaptureMessages{
captureMessages: &captureMessages{},
scheduled: []domain.ScheduledMessage{{
OwnerUserID: aliceID,
ID: 77,
Peer: peer,
Message: "",
Media: media,
ScheduleDate: int(now + 3600),
State: "pending",
}},
}
r := New(Config{}, Deps{Messages: messages}, zaptest.NewLogger(t), fixedClock{now: time.Unix(now, 0)})
ctx := WithUserID(context.Background(), aliceID)
editReq := &tg.MessagesEditMessageRequest{
Peer: &tg.InputPeerUser{UserID: bobID, AccessHash: 22},
ID: 77,
}
editReq.SetScheduleDate(int(now + 7200))
updates, err := r.onMessagesEditMessage(ctx, editReq)
if err != nil {
t.Fatalf("date-only scheduled edit: %v", err)
}
if messages.editScheduledReq.SetMessage {
t.Fatalf("edit scheduled req = %+v, want date-only edit without content overwrite", messages.editScheduledReq)
}
if messages.scheduled[0].Message != "" || messages.scheduled[0].Media != media || messages.scheduled[0].ScheduleDate != int(now+7200) {
t.Fatalf("scheduled item after date-only edit = %+v, want original content and new date", messages.scheduled[0])
}
editedMessage := updates.(*tg.Updates).Updates[0].(*tg.UpdateNewScheduledMessage).Message.(*tg.Message)
if !editedMessage.FromScheduled || editedMessage.Date != int(now+7200) {
t.Fatalf("date-only edit update = %#v, want scheduled message at new date", editedMessage)
}
}
func TestScheduledMessageEditAllowsEmptyCaptionForMedia(t *testing.T) {
const (
aliceID = int64(1000000001)
bobID = int64(1000000002)
now = int64(1700004000)
)
media := &domain.MessageMedia{
Kind: domain.MessageMediaKindDocument,
Document: &domain.Document{ID: 910000000000000002, AccessHash: 92, DCID: 2},
}
peer := domain.Peer{Type: domain.PeerTypeUser, ID: bobID}
messages := &scheduledCaptureMessages{
captureMessages: &captureMessages{},
scheduled: []domain.ScheduledMessage{{
OwnerUserID: aliceID,
ID: 78,
Peer: peer,
Message: "caption",
Media: media,
ScheduleDate: int(now + 3600),
State: "pending",
}},
}
r := New(Config{}, Deps{Messages: messages}, zaptest.NewLogger(t), fixedClock{now: time.Unix(now, 0)})
ctx := WithUserID(context.Background(), aliceID)
editReq := &tg.MessagesEditMessageRequest{
Peer: &tg.InputPeerUser{UserID: bobID, AccessHash: 22},
ID: 78,
}
editReq.SetMessage("")
editReq.SetScheduleDate(int(now + 7200))
if _, err := r.onMessagesEditMessage(ctx, editReq); err != nil {
t.Fatalf("empty-caption scheduled edit: %v", err)
}
if !messages.editScheduledReq.SetMessage || messages.editScheduledReq.Message != "" {
t.Fatalf("edit scheduled req = %+v, want explicit empty caption update", messages.editScheduledReq)
}
if messages.scheduled[0].Message != "" || messages.scheduled[0].Media != media || messages.scheduled[0].ScheduleDate != int(now+7200) {
t.Fatalf("scheduled item after empty-caption edit = %+v, want media kept and caption cleared", messages.scheduled[0])
}
}
func TestMessagesSetHistoryTTLPushesPrivatePeerBothSides(t *testing.T) {
const (
aliceID = int64(1000000001)
bobID = int64(1000000002)
now = int64(1700002000)
period = 86400
)
messages := &ttlCaptureMessages{captureMessages: &captureMessages{}}
sessions := &captureSessions{}
r := New(Config{}, Deps{Messages: messages, Sessions: sessions}, zaptest.NewLogger(t), fixedClock{now: time.Unix(now, 0)})
ctx := WithSessionID(WithUserID(context.Background(), aliceID), 77)
out, err := r.onMessagesSetHistoryTTL(ctx, &tg.MessagesSetHistoryTTLRequest{
Peer: &tg.InputPeerUser{UserID: bobID, AccessHash: 22},
Period: period,
})
if err != nil {
t.Fatalf("set private history ttl: %v", err)
}
if messages.setTTLUserID != aliceID || messages.setTTLPeer != (domain.Peer{Type: domain.PeerTypeUser, ID: bobID}) || messages.setTTLPeriod != period {
t.Fatalf("set ttl context user=%d peer=%+v period=%d", messages.setTTLUserID, messages.setTTLPeer, messages.setTTLPeriod)
}
selfUpdate := out.(*tg.Updates).Updates[0].(*tg.UpdatePeerHistoryTTL)
if peer, ok := selfUpdate.Peer.(*tg.PeerUser); !ok || peer.UserID != bobID {
t.Fatalf("self ttl peer = %#v, want bob", selfUpdate.Peer)
}
if ttl, ok := selfUpdate.GetTTLPeriod(); !ok || ttl != period {
t.Fatalf("self ttl period = %d ok %v, want %d", ttl, ok, period)
}
if got := sessions.pushedUserIDs(); len(got) != 2 || got[0] != aliceID || got[1] != bobID {
t.Fatalf("pushed users = %+v, want alice then bob", got)
}
peerUpdates := sessions.snapshot().message.(*tg.Updates)
peerUpdate := peerUpdates.Updates[0].(*tg.UpdatePeerHistoryTTL)
if peer, ok := peerUpdate.Peer.(*tg.PeerUser); !ok || peer.UserID != aliceID {
t.Fatalf("peer ttl update peer = %#v, want alice", peerUpdate.Peer)
}
}