add boilerplate chats api calls
standard graph api boilerplate.
This commit is contained in:
parent
0a6355eeb1
commit
c999a3072f
89
src/pkg/services/m365/api/teamdChats_test.go
Normal file
89
src/pkg/services/m365/api/teamdChats_test.go
Normal file
@ -0,0 +1,89 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||
)
|
||||
|
||||
type ChatsAPIUnitSuite struct {
|
||||
tester.Suite
|
||||
}
|
||||
|
||||
func TestChatsAPIUnitSuite(t *testing.T) {
|
||||
suite.Run(t, &ChatsAPIUnitSuite{Suite: tester.NewUnitSuite(t)})
|
||||
}
|
||||
|
||||
func (suite *ChatsAPIUnitSuite) TestChatsInfo() {
|
||||
start := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
chatAndExpected func() (models.Chatable, *details.TeamsChatsInfo)
|
||||
}{
|
||||
{
|
||||
name: "Empty chat",
|
||||
chatAndExpected: func() (models.Chatable, *details.TeamsChatsInfo) {
|
||||
chat := models.NewChat()
|
||||
|
||||
i := &details.TeamsChatsInfo{
|
||||
ItemType: details.TeamsChat,
|
||||
Chat: details.ChatInfo{},
|
||||
}
|
||||
|
||||
return chat, i
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "All fields",
|
||||
chatAndExpected: func() (models.Chatable, *details.TeamsChatsInfo) {
|
||||
now := time.Now()
|
||||
then := now.Add(1 * time.Hour)
|
||||
|
||||
chat := models.NewChat()
|
||||
chat.SetTopic(ptr.To("Hello world"))
|
||||
chat.SetCreatedDateTime(&now)
|
||||
chat.SetLastUpdatedDateTime(&then)
|
||||
|
||||
i := &details.TeamsChatsInfo{
|
||||
ItemType: details.TeamsChat,
|
||||
Chat: details.ChatInfo{
|
||||
Name: "Hello world",
|
||||
},
|
||||
}
|
||||
|
||||
return chat, i
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
suite.Run(test.name, func() {
|
||||
t := suite.T()
|
||||
chat, expected := test.chatAndExpected()
|
||||
result := TeamsChatInfo(chat)
|
||||
|
||||
assert.Equal(t, expected.Chat.Name, result.Chat.Name)
|
||||
|
||||
expectLastUpdated := chat.GetLastUpdatedDateTime()
|
||||
if expectLastUpdated != nil {
|
||||
assert.Equal(t, ptr.Val(expectLastUpdated), result.Modified)
|
||||
} else {
|
||||
assert.True(t, result.Modified.After(start))
|
||||
}
|
||||
|
||||
expectCreated := chat.GetCreatedDateTime()
|
||||
if expectCreated != nil {
|
||||
assert.Equal(t, ptr.Val(expectCreated), result.Chat.CreatedAt)
|
||||
} else {
|
||||
assert.True(t, result.Chat.CreatedAt.After(start))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
74
src/pkg/services/m365/api/teamsChats.go
Normal file
74
src/pkg/services/m365/api/teamsChats.go
Normal file
@ -0,0 +1,74 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/chats"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// controller
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func (c Client) Chats() Chats {
|
||||
return Chats{c}
|
||||
}
|
||||
|
||||
// Chats is an interface-compliant provider of the client.
|
||||
type Chats struct {
|
||||
Client
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Chats
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func (c Chats) GetChatByID(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
cc CallConfig,
|
||||
) (models.Chatable, *details.TeamsChatsInfo, error) {
|
||||
config := &chats.ChatItemRequestBuilderGetRequestConfiguration{
|
||||
QueryParameters: &chats.ChatItemRequestBuilderGetQueryParameters{},
|
||||
}
|
||||
|
||||
if len(cc.Select) > 0 {
|
||||
config.QueryParameters.Select = cc.Select
|
||||
}
|
||||
|
||||
if len(cc.Expand) > 0 {
|
||||
config.QueryParameters.Expand = cc.Expand
|
||||
}
|
||||
|
||||
resp, err := c.Stable.
|
||||
Client().
|
||||
Chats().
|
||||
ByChatId(chatID).
|
||||
Get(ctx, config)
|
||||
if err != nil {
|
||||
return nil, nil, graph.Stack(ctx, err)
|
||||
}
|
||||
|
||||
return resp, TeamsChatInfo(resp), nil
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func TeamsChatInfo(chat models.Chatable) *details.TeamsChatsInfo {
|
||||
return &details.TeamsChatsInfo{
|
||||
ItemType: details.TeamsChat,
|
||||
Modified: ptr.OrNow(chat.GetLastUpdatedDateTime()),
|
||||
|
||||
Chat: details.ChatInfo{
|
||||
CreatedAt: ptr.OrNow(chat.GetCreatedDateTime()),
|
||||
Name: ptr.Val(chat.GetTopic()),
|
||||
},
|
||||
}
|
||||
}
|
||||
172
src/pkg/services/m365/api/teamsChats_pager.go
Normal file
172
src/pkg/services/m365/api/teamsChats_pager.go
Normal file
@ -0,0 +1,172 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/chats"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/users"
|
||||
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api/pagers"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// chat message pager
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// delta queries are not supported
|
||||
var _ pagers.NonDeltaHandler[models.ChatMessageable] = &chatMessagePageCtrl{}
|
||||
|
||||
type chatMessagePageCtrl struct {
|
||||
chatID string
|
||||
gs graph.Servicer
|
||||
builder *chats.ItemMessagesRequestBuilder
|
||||
options *chats.ItemMessagesRequestBuilderGetRequestConfiguration
|
||||
}
|
||||
|
||||
func (p *chatMessagePageCtrl) SetNextLink(nextLink string) {
|
||||
p.builder = chats.NewItemMessagesRequestBuilder(nextLink, p.gs.Adapter())
|
||||
}
|
||||
|
||||
func (p *chatMessagePageCtrl) GetPage(
|
||||
ctx context.Context,
|
||||
) (pagers.NextLinkValuer[models.ChatMessageable], error) {
|
||||
resp, err := p.builder.Get(ctx, p.options)
|
||||
return resp, graph.Stack(ctx, err).OrNil()
|
||||
}
|
||||
|
||||
func (p *chatMessagePageCtrl) ValidModTimes() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c Chats) NewChatMessagePager(
|
||||
chatID string,
|
||||
cc CallConfig,
|
||||
) *chatMessagePageCtrl {
|
||||
builder := c.Stable.
|
||||
Client().
|
||||
Chats().
|
||||
ByChatId(chatID).
|
||||
Messages()
|
||||
|
||||
options := &chats.ItemMessagesRequestBuilderGetRequestConfiguration{
|
||||
QueryParameters: &chats.ItemMessagesRequestBuilderGetQueryParameters{},
|
||||
Headers: newPreferHeaders(preferPageSize(maxNonDeltaPageSize)),
|
||||
}
|
||||
|
||||
if len(cc.Select) > 0 {
|
||||
options.QueryParameters.Select = cc.Select
|
||||
}
|
||||
|
||||
if len(cc.Expand) > 0 {
|
||||
options.QueryParameters.Expand = cc.Expand
|
||||
}
|
||||
|
||||
return &chatMessagePageCtrl{
|
||||
chatID: chatID,
|
||||
builder: builder,
|
||||
gs: c.Stable,
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// GetChatMessages fetches a delta of all messages in the chat.
|
||||
func (c Chats) GetChatMessages(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
cc CallConfig,
|
||||
) ([]models.ChatMessageable, error) {
|
||||
ctx = clues.Add(ctx, "chat_id", chatID)
|
||||
pager := c.NewChatMessagePager(chatID, cc)
|
||||
items, err := pagers.BatchEnumerateItems[models.ChatMessageable](ctx, pager)
|
||||
|
||||
return items, graph.Stack(ctx, err).OrNil()
|
||||
}
|
||||
|
||||
// GetChatMessageIDs fetches a delta of all messages in the chat.
|
||||
// returns two maps: addedItems, deletedItems
|
||||
func (c Chats) GetChatMessageIDs(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
cc CallConfig,
|
||||
) (pagers.AddedAndRemoved, error) {
|
||||
aar, err := pagers.GetAddedAndRemovedItemIDs[models.ChatMessageable](
|
||||
ctx,
|
||||
c.NewChatMessagePager(chatID, CallConfig{}),
|
||||
nil,
|
||||
"",
|
||||
false, // delta queries are not supported
|
||||
0,
|
||||
pagers.AddedAndRemovedByDeletedDateTime[models.ChatMessageable],
|
||||
IsNotSystemMessage)
|
||||
|
||||
return aar, clues.Stack(err).OrNil()
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// chat pager
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
var _ pagers.NonDeltaHandler[models.Chatable] = &chatPageCtrl{}
|
||||
|
||||
type chatPageCtrl struct {
|
||||
gs graph.Servicer
|
||||
builder *users.ItemChatsRequestBuilder
|
||||
options *users.ItemChatsRequestBuilderGetRequestConfiguration
|
||||
}
|
||||
|
||||
func (p *chatPageCtrl) SetNextLink(nextLink string) {
|
||||
p.builder = users.NewItemChatsRequestBuilder(nextLink, p.gs.Adapter())
|
||||
}
|
||||
|
||||
func (p *chatPageCtrl) GetPage(
|
||||
ctx context.Context,
|
||||
) (pagers.NextLinkValuer[models.Chatable], error) {
|
||||
resp, err := p.builder.Get(ctx, p.options)
|
||||
return resp, graph.Stack(ctx, err).OrNil()
|
||||
}
|
||||
|
||||
func (p *chatPageCtrl) ValidModTimes() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c Chats) NewChatPager(
|
||||
userID string,
|
||||
cc CallConfig,
|
||||
) *chatPageCtrl {
|
||||
options := &users.ItemChatsRequestBuilderGetRequestConfiguration{
|
||||
QueryParameters: &users.ItemChatsRequestBuilderGetQueryParameters{},
|
||||
Headers: newPreferHeaders(preferPageSize(maxNonDeltaPageSize)),
|
||||
}
|
||||
|
||||
if len(cc.Select) > 0 {
|
||||
options.QueryParameters.Select = cc.Select
|
||||
}
|
||||
|
||||
if len(cc.Expand) > 0 {
|
||||
options.QueryParameters.Expand = cc.Expand
|
||||
}
|
||||
|
||||
res := &chatPageCtrl{
|
||||
gs: c.Stable,
|
||||
options: options,
|
||||
builder: c.Stable.
|
||||
Client().
|
||||
Users().
|
||||
ByUserId(userID).
|
||||
Chats(),
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// GetChats fetches all chats in the team.
|
||||
func (c Chats) GetChats(
|
||||
ctx context.Context,
|
||||
userID string,
|
||||
cc CallConfig,
|
||||
) ([]models.Chatable, error) {
|
||||
return pagers.BatchEnumerateItems[models.Chatable](ctx, c.NewChatPager(userID, cc))
|
||||
}
|
||||
128
src/pkg/services/m365/api/teamsChats_pager_test.go
Normal file
128
src/pkg/services/m365/api/teamsChats_pager_test.go
Normal file
@ -0,0 +1,128 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/internal/tester/tconfig"
|
||||
)
|
||||
|
||||
type ChatsPagerIntgSuite struct {
|
||||
tester.Suite
|
||||
its intgTesterSetup
|
||||
}
|
||||
|
||||
func TestChatsPagerIntgSuite(t *testing.T) {
|
||||
suite.Run(t, &ChatsPagerIntgSuite{
|
||||
Suite: tester.NewIntegrationSuite(
|
||||
t,
|
||||
[][]string{tconfig.M365AcctCredEnvs}),
|
||||
})
|
||||
}
|
||||
|
||||
func (suite *ChatsPagerIntgSuite) SetupSuite() {
|
||||
suite.its = newIntegrationTesterSetup(suite.T())
|
||||
}
|
||||
|
||||
func (suite *ChatsPagerIntgSuite) TestEnumerateChats() {
|
||||
var (
|
||||
t = suite.T()
|
||||
ac = suite.its.ac.Chats()
|
||||
)
|
||||
|
||||
ctx, flush := tester.NewContext(t)
|
||||
defer flush()
|
||||
|
||||
cc := CallConfig{
|
||||
Expand: []string{"lastMessagePreview"},
|
||||
}
|
||||
|
||||
chats, err := ac.GetChats(ctx, suite.its.user.id, cc)
|
||||
require.NoError(t, err, clues.ToCore(err))
|
||||
require.NotEmpty(t, chats)
|
||||
|
||||
for _, chat := range chats {
|
||||
chatID := ptr.Val(chat.GetId())
|
||||
|
||||
suite.Run("chat_"+chatID, func() {
|
||||
testGetChatByID(suite.T(), ac, chatID)
|
||||
})
|
||||
|
||||
suite.Run("chat_messages_"+chatID, func() {
|
||||
testEnumerateChatMessages(
|
||||
suite.T(),
|
||||
ac,
|
||||
chatID,
|
||||
chat.GetLastMessagePreview())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testGetChatByID(
|
||||
t *testing.T,
|
||||
ac Chats,
|
||||
chatID string,
|
||||
) {
|
||||
ctx, flush := tester.NewContext(t)
|
||||
defer flush()
|
||||
|
||||
cc := CallConfig{}
|
||||
|
||||
chat, _, err := ac.GetChatByID(ctx, chatID, cc)
|
||||
require.NoError(t, err, clues.ToCore(err))
|
||||
require.NotNil(t, chat)
|
||||
}
|
||||
|
||||
var attachmentHtmlRegexp = regexp.MustCompile("<attachment id=\"[a-zA-Z0-9].*\"></attachment>")
|
||||
|
||||
func testEnumerateChatMessages(
|
||||
t *testing.T,
|
||||
ac Chats,
|
||||
chatID string,
|
||||
lastMessagePreview models.ChatMessageInfoable,
|
||||
) {
|
||||
ctx, flush := tester.NewContext(t)
|
||||
defer flush()
|
||||
|
||||
cc := CallConfig{}
|
||||
|
||||
messages, err := ac.GetChatMessages(ctx, chatID, cc)
|
||||
require.NoError(t, err, clues.ToCore(err))
|
||||
|
||||
var lastID string
|
||||
if lastMessagePreview != nil {
|
||||
lastID = ptr.Val(lastMessagePreview.GetId())
|
||||
}
|
||||
|
||||
for _, msg := range messages {
|
||||
msgID := ptr.Val(msg.GetId())
|
||||
|
||||
assert.Equal(
|
||||
t,
|
||||
chatID,
|
||||
ptr.Val(msg.GetChatId()),
|
||||
"message:",
|
||||
msgID)
|
||||
|
||||
if msgID == lastID {
|
||||
previewContent := ptr.Val(lastMessagePreview.GetBody().GetContent())
|
||||
msgContent := ptr.Val(msg.GetBody().GetContent())
|
||||
|
||||
previewContent = replaceAttachmentMarkup(previewContent, nil)
|
||||
msgContent = replaceAttachmentMarkup(msgContent, nil)
|
||||
|
||||
assert.Equal(
|
||||
t,
|
||||
previewContent,
|
||||
msgContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user