package telegram import ( "context" "testing" "time" "git.yeij.top/AskaEth/Cyrene_v2/internal/channel/adapter" ) func TestToUnifiedMessage_PrivateText(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) u := telegramUpdate{ UpdateID: 1, Message: &telegramMessage{ MessageID: 42, From: &telegramUser{ID: 100, FirstName: "Alice", Username: "alice"}, Chat: telegramChat{ID: 200, Type: "private"}, Date: 1700000000, Text: "hello world", }, } msg, ok := a.toUnifiedMessage(u) if !ok { t.Fatal("expected ok") } if msg.Platform != "telegram" { t.Errorf("Platform = %q, want telegram", msg.Platform) } if msg.ChannelType != adapter.ChannelDirect { t.Errorf("ChannelType = %q, want direct", msg.ChannelType) } if msg.ChannelID != "200" { t.Errorf("ChannelID = %q, want 200", msg.ChannelID) } if msg.SenderID != "100" { t.Errorf("SenderID = %q, want 100", msg.SenderID) } if msg.SenderName != "Alice" { t.Errorf("SenderName = %q, want Alice", msg.SenderName) } if msg.Content != "hello world" || msg.ContentType != adapter.ContentText { t.Errorf("content = %q/%q, want hello world/text", msg.Content, msg.ContentType) } if msg.Sender.UserID != "100" || msg.Sender.DisplayName != "Alice" { t.Errorf("Sender actor = %+v", msg.Sender) } if msg.Sender.IsGroupChat() { t.Error("private message should not be a group actor") } wantTS := time.Unix(1700000000, 0) if !msg.Timestamp.Equal(wantTS) { t.Errorf("Timestamp = %v, want %v", msg.Timestamp, wantTS) } } func TestToUnifiedMessage_Group(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) u := telegramUpdate{ UpdateID: 2, Message: &telegramMessage{ MessageID: 7, From: &telegramUser{ID: 300, FirstName: "Bob"}, Chat: telegramChat{ID: -1000, Type: "supergroup", Title: "Team Chat"}, Date: 1700000001, Text: "ping", }, } msg, ok := a.toUnifiedMessage(u) if !ok { t.Fatal("expected ok") } if msg.ChannelType != adapter.ChannelGroup { t.Errorf("ChannelType = %q, want group", msg.ChannelType) } if msg.GroupID != "-1000" || msg.GroupName != "Team Chat" { t.Errorf("group = %q/%q, want -1000/Team Chat", msg.GroupID, msg.GroupName) } if !msg.Sender.IsGroupChat() { t.Error("Sender should be a group actor") } if msg.Sender.GroupID != "-1000" { t.Errorf("Sender.GroupID = %q, want -1000", msg.Sender.GroupID) } } func TestToUnifiedMessage_ImageFileID(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) u := telegramUpdate{ UpdateID: 3, Message: &telegramMessage{ MessageID: 9, From: &telegramUser{ID: 400, FirstName: "Cara"}, Chat: telegramChat{ID: 500, Type: "private"}, Date: 1700000002, Caption: "look at this", Photo: []telegramPhotoSize{{FileID: "photo-small", FileSize: 100}, {FileID: "photo-big", FileSize: 2000}}, }, } msg, ok := a.toUnifiedMessage(u) if !ok { t.Fatal("expected ok") } if msg.ContentType != adapter.ContentImage { t.Errorf("ContentType = %q, want image", msg.ContentType) } if msg.Content != "look at this" { t.Errorf("Content = %q, want caption", msg.Content) } if len(msg.Media) != 1 { t.Fatalf("media length = %d, want 1", len(msg.Media)) } m := msg.Media[0] if m.Kind != adapter.MediaImage || m.URL != "photo-big" || m.Size != 2000 { t.Errorf("media = %+v, want image/photo-big/2000", m) } } func TestToUnifiedMessage_VoiceFileID(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) u := telegramUpdate{ UpdateID: 4, Message: &telegramMessage{ MessageID: 10, From: &telegramUser{ID: 600, FirstName: "Dan"}, Chat: telegramChat{ID: 700, Type: "private"}, Date: 1700000003, Voice: &telegramAudio{FileID: "voice-id", FileSize: 5000, MIMEType: "audio/ogg"}, }, } msg, ok := a.toUnifiedMessage(u) if !ok { t.Fatal("expected ok") } if msg.ContentType != adapter.ContentVoice { t.Errorf("ContentType = %q, want voice", msg.ContentType) } if len(msg.Media) != 1 || msg.Media[0].Kind != adapter.MediaVoice || msg.Media[0].URL != "voice-id" { t.Errorf("media = %+v, want voice/voice-id", msg.Media) } } func TestToUnifiedMessage_DocumentFileID(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) u := telegramUpdate{ UpdateID: 5, Message: &telegramMessage{ MessageID: 11, From: &telegramUser{ID: 800, FirstName: "Eve"}, Chat: telegramChat{ID: 900, Type: "private"}, Date: 1700000004, Document: &telegramDocument{FileID: "doc-id", FileSize: 9000, FileName: "report.pdf", MIMEType: "application/pdf"}, }, } msg, ok := a.toUnifiedMessage(u) if !ok { t.Fatal("expected ok") } if msg.ContentType != adapter.ContentFile { t.Errorf("ContentType = %q, want file", msg.ContentType) } m := msg.Media[0] if m.Kind != adapter.MediaFile || m.URL != "doc-id" || m.Name != "report.pdf" { t.Errorf("media = %+v, want file/doc-id/report.pdf", m) } } func TestToUnifiedMessage_ReplyAndThread(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) u := telegramUpdate{ UpdateID: 6, Message: &telegramMessage{ MessageID: 20, From: &telegramUser{ID: 1000, FirstName: "Finn"}, Chat: telegramChat{ID: -2000, Type: "group", Title: "Thread Group"}, Date: 1700000005, Text: "a reply", MessageThreadID: 33, ReplyToMessage: &telegramMessage{MessageID: 19, Text: "original"}, }, } msg, ok := a.toUnifiedMessage(u) if !ok { t.Fatal("expected ok") } if msg.ThreadID != "33" { t.Errorf("ThreadID = %q, want 33", msg.ThreadID) } if msg.ReplyToID != "19" || msg.ReplyToText != "original" { t.Errorf("reply = %q/%q, want 19/original", msg.ReplyToID, msg.ReplyToText) } } func TestToUnifiedMessage_NoMessage(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) u := telegramUpdate{UpdateID: 7} if _, ok := a.toUnifiedMessage(u); ok { t.Fatal("expected ok=false for non-message update") } } func TestListChannels_FromConversations(t *testing.T) { t.Parallel() a := New(Config{BotToken: "x"}) a.toUnifiedMessage(telegramUpdate{ UpdateID: 8, Message: &telegramMessage{ MessageID: 1, From: &telegramUser{ID: 1, FirstName: "Ada"}, Chat: telegramChat{ID: 10, Type: "private"}, Text: "hi", }, }) a.toUnifiedMessage(telegramUpdate{ UpdateID: 9, Message: &telegramMessage{ MessageID: 2, From: &telegramUser{ID: 2, FirstName: "Bob"}, Chat: telegramChat{ID: -20, Type: "group", Title: "Gang"}, Text: "yo", }, }) got, err := a.ListChannels(context.Background()) if err != nil { t.Fatalf("ListChannels: %v", err) } if len(got) != 2 { t.Fatalf("channels length = %d, want 2: %+v", len(got), got) } // Sort puts -20 (group) before 10 (private) as strings. if got[0].ChannelID != "-20" || got[0].ChannelType != adapter.ChannelGroup || got[0].GroupName != "Gang" { t.Errorf("channels[0] = %+v, want group -20", got[0]) } if got[1].ChannelID != "10" || got[1].ChannelType != adapter.ChannelDirect || got[1].ChannelName != "Ada" { t.Errorf("channels[1] = %+v, want direct 10", got[1]) } }