add chats boilerplate to details
This commit is contained in:
parent
eefce75f1d
commit
07997b0987
120
src/pkg/backup/details/chats.go
Normal file
120
src/pkg/backup/details/chats.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package details
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/alcionai/clues"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/pkg/dttm"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewChatsLocationIDer builds a LocationIDer for the chats.
|
||||||
|
func NewChatsLocationIDer(
|
||||||
|
category path.CategoryType,
|
||||||
|
escapedFolders ...string,
|
||||||
|
) (uniqueLoc, error) {
|
||||||
|
if err := path.ValidateServiceAndCategory(path.TeamsChatsService, category); err != nil {
|
||||||
|
return uniqueLoc{}, clues.Wrap(err, "making chats LocationIDer")
|
||||||
|
}
|
||||||
|
|
||||||
|
pb := path.Builder{}.Append(category.String()).Append(escapedFolders...)
|
||||||
|
|
||||||
|
return uniqueLoc{
|
||||||
|
pb: pb,
|
||||||
|
prefixElems: 1,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TeamsChatsInfo describes a chat within teams chats.
|
||||||
|
type TeamsChatsInfo struct {
|
||||||
|
ItemType ItemType `json:"itemType,omitempty"`
|
||||||
|
Modified time.Time `json:"modified,omitempty"`
|
||||||
|
ParentPath string `json:"parentPath,omitempty"`
|
||||||
|
|
||||||
|
Chat ChatInfo `json:"chat,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChatInfo struct {
|
||||||
|
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||||
|
HasExternalMembers bool `json:"hasExternalMemebers,omitempty"`
|
||||||
|
LastMessageAt time.Time `json:"lastMessageAt,omitempty"`
|
||||||
|
LastMessagePreview string `json:"preview,omitempty"`
|
||||||
|
Members []string `json:"members,omitempty"`
|
||||||
|
MessageCount int `json:"size,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Headers returns the human-readable names of properties in a ChatsInfo
|
||||||
|
// for printing out to a terminal in a columnar display.
|
||||||
|
func (i TeamsChatsInfo) Headers() []string {
|
||||||
|
switch i.ItemType {
|
||||||
|
case TeamsChat:
|
||||||
|
return []string{"Name", "Last message", "Last message at", "Message count", "Created", "Members"}
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns the values matching the Headers list for printing
|
||||||
|
// out to a terminal in a columnar display.
|
||||||
|
func (i TeamsChatsInfo) Values() []string {
|
||||||
|
switch i.ItemType {
|
||||||
|
case TeamsChat:
|
||||||
|
members := ""
|
||||||
|
icmLen := len(i.Chat.Members)
|
||||||
|
|
||||||
|
if icmLen > 0 {
|
||||||
|
members = i.Chat.Members[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if icmLen > 1 {
|
||||||
|
members = fmt.Sprintf("%s, and %d more", members, icmLen-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{
|
||||||
|
i.Chat.Name,
|
||||||
|
i.Chat.LastMessagePreview,
|
||||||
|
dttm.FormatToTabularDisplay(i.Chat.LastMessageAt),
|
||||||
|
strconv.Itoa(i.Chat.MessageCount),
|
||||||
|
dttm.FormatToTabularDisplay(i.Chat.CreatedAt),
|
||||||
|
members,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *TeamsChatsInfo) UpdateParentPath(newLocPath *path.Builder) {
|
||||||
|
i.ParentPath = newLocPath.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *TeamsChatsInfo) uniqueLocation(baseLoc *path.Builder) (*uniqueLoc, error) {
|
||||||
|
var category path.CategoryType
|
||||||
|
|
||||||
|
switch i.ItemType {
|
||||||
|
case TeamsChat:
|
||||||
|
category = path.ChatsCategory
|
||||||
|
}
|
||||||
|
|
||||||
|
loc, err := NewChatsLocationIDer(category, baseLoc.Elements()...)
|
||||||
|
|
||||||
|
return &loc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *TeamsChatsInfo) updateFolder(f *FolderInfo) error {
|
||||||
|
// Use a switch instead of a rather large if-statement. Just make sure it's an
|
||||||
|
// Exchange type. If it's not return an error.
|
||||||
|
switch i.ItemType {
|
||||||
|
case TeamsChat:
|
||||||
|
default:
|
||||||
|
return clues.New("unsupported non-Chats ItemType").
|
||||||
|
With("item_type", i.ItemType)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.DataType = i.ItemType
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
71
src/pkg/backup/details/chats_test.go
Normal file
71
src/pkg/backup/details/chats_test.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package details_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||||
|
"github.com/alcionai/corso/src/pkg/dttm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ChatsUnitSuite struct {
|
||||||
|
tester.Suite
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChatsUnitSuite(t *testing.T) {
|
||||||
|
suite.Run(t, &ChatsUnitSuite{Suite: tester.NewUnitSuite(t)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ChatsUnitSuite) TestChatsPrintable() {
|
||||||
|
now := time.Now()
|
||||||
|
then := now.Add(time.Minute)
|
||||||
|
|
||||||
|
table := []struct {
|
||||||
|
name string
|
||||||
|
info details.TeamsChatsInfo
|
||||||
|
expectHs []string
|
||||||
|
expectVs []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "channel message",
|
||||||
|
info: details.TeamsChatsInfo{
|
||||||
|
ItemType: details.TeamsChat,
|
||||||
|
ParentPath: "parentpath",
|
||||||
|
Chat: details.ChatInfo{
|
||||||
|
CreatedAt: now,
|
||||||
|
HasExternalMembers: true,
|
||||||
|
LastMessageAt: then,
|
||||||
|
LastMessagePreview: "last message preview",
|
||||||
|
Members: []string{"foo@bar.baz", "fnords@smarf.zoomba"},
|
||||||
|
MessageCount: 42,
|
||||||
|
Name: "chat name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectHs: []string{"Name", "Last message", "Last message at", "Message count", "Created", "Members"},
|
||||||
|
expectVs: []string{
|
||||||
|
"chat name",
|
||||||
|
"last message preview",
|
||||||
|
dttm.FormatToTabularDisplay(then),
|
||||||
|
"42",
|
||||||
|
dttm.FormatToTabularDisplay(now),
|
||||||
|
"foo@bar.baz, and 1 more",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range table {
|
||||||
|
suite.Run(test.name, func() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
hs := test.info.Headers()
|
||||||
|
vs := test.info.Values()
|
||||||
|
|
||||||
|
assert.Equal(t, len(hs), len(vs))
|
||||||
|
assert.Equal(t, test.expectHs, hs)
|
||||||
|
assert.Equal(t, test.expectVs, vs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -78,7 +78,7 @@ type ChannelMessageInfo struct {
|
|||||||
Subject string `json:"subject,omitempty"`
|
Subject string `json:"subject,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Headers returns the human-readable names of properties in a SharePointInfo
|
// Headers returns the human-readable names of properties in a gropusInfo
|
||||||
// for printing out to a terminal in a columnar display.
|
// for printing out to a terminal in a columnar display.
|
||||||
func (i GroupsInfo) Headers() []string {
|
func (i GroupsInfo) Headers() []string {
|
||||||
switch i.ItemType {
|
switch i.ItemType {
|
||||||
|
|||||||
@ -41,6 +41,9 @@ const (
|
|||||||
// Groups/Teams(40x)
|
// Groups/Teams(40x)
|
||||||
GroupsChannelMessage ItemType = 401
|
GroupsChannelMessage ItemType = 401
|
||||||
GroupsConversationPost ItemType = 402
|
GroupsConversationPost ItemType = 402
|
||||||
|
|
||||||
|
// Teams Chat
|
||||||
|
TeamsChat ItemType = 501
|
||||||
)
|
)
|
||||||
|
|
||||||
func UpdateItem(item *ItemInfo, newLocPath *path.Builder) {
|
func UpdateItem(item *ItemInfo, newLocPath *path.Builder) {
|
||||||
@ -73,6 +76,7 @@ type ItemInfo struct {
|
|||||||
SharePoint *SharePointInfo `json:"sharePoint,omitempty"`
|
SharePoint *SharePointInfo `json:"sharePoint,omitempty"`
|
||||||
OneDrive *OneDriveInfo `json:"oneDrive,omitempty"`
|
OneDrive *OneDriveInfo `json:"oneDrive,omitempty"`
|
||||||
Groups *GroupsInfo `json:"groups,omitempty"`
|
Groups *GroupsInfo `json:"groups,omitempty"`
|
||||||
|
TeamsChats *TeamsChatsInfo `json:"teamsChats,omitempty"`
|
||||||
// Optional item extension data
|
// Optional item extension data
|
||||||
Extension *ExtensionData `json:"extension,omitempty"`
|
Extension *ExtensionData `json:"extension,omitempty"`
|
||||||
}
|
}
|
||||||
@ -99,6 +103,9 @@ func (i ItemInfo) infoType() ItemType {
|
|||||||
|
|
||||||
case i.Groups != nil:
|
case i.Groups != nil:
|
||||||
return i.Groups.ItemType
|
return i.Groups.ItemType
|
||||||
|
|
||||||
|
case i.TeamsChats != nil:
|
||||||
|
return i.TeamsChats.ItemType
|
||||||
}
|
}
|
||||||
|
|
||||||
return UnknownType
|
return UnknownType
|
||||||
@ -120,6 +127,9 @@ func (i ItemInfo) size() int64 {
|
|||||||
|
|
||||||
case i.Folder != nil:
|
case i.Folder != nil:
|
||||||
return i.Folder.Size
|
return i.Folder.Size
|
||||||
|
|
||||||
|
case i.TeamsChats != nil:
|
||||||
|
return int64(i.TeamsChats.Chat.MessageCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@ -141,6 +151,9 @@ func (i ItemInfo) Modified() time.Time {
|
|||||||
|
|
||||||
case i.Folder != nil:
|
case i.Folder != nil:
|
||||||
return i.Folder.Modified
|
return i.Folder.Modified
|
||||||
|
|
||||||
|
case i.TeamsChats != nil:
|
||||||
|
return i.TeamsChats.Modified
|
||||||
}
|
}
|
||||||
|
|
||||||
return time.Time{}
|
return time.Time{}
|
||||||
@ -160,6 +173,9 @@ func (i ItemInfo) uniqueLocation(baseLoc *path.Builder) (*uniqueLoc, error) {
|
|||||||
case i.Groups != nil:
|
case i.Groups != nil:
|
||||||
return i.Groups.uniqueLocation(baseLoc)
|
return i.Groups.uniqueLocation(baseLoc)
|
||||||
|
|
||||||
|
case i.TeamsChats != nil:
|
||||||
|
return i.TeamsChats.uniqueLocation(baseLoc)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, clues.New("unsupported type")
|
return nil, clues.New("unsupported type")
|
||||||
}
|
}
|
||||||
@ -179,6 +195,9 @@ func (i ItemInfo) updateFolder(f *FolderInfo) error {
|
|||||||
case i.Groups != nil:
|
case i.Groups != nil:
|
||||||
return i.Groups.updateFolder(f)
|
return i.Groups.updateFolder(f)
|
||||||
|
|
||||||
|
case i.TeamsChats != nil:
|
||||||
|
return i.TeamsChats.updateFolder(f)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return clues.New("unsupported type")
|
return clues.New("unsupported type")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,12 +71,21 @@ func (suite *ItemInfoUnitSuite) TestItemInfo_IsDriveItem() {
|
|||||||
{
|
{
|
||||||
name: "exchange anything",
|
name: "exchange anything",
|
||||||
ii: ItemInfo{
|
ii: ItemInfo{
|
||||||
Groups: &GroupsInfo{
|
Exchange: &ExchangeInfo{
|
||||||
ItemType: ExchangeMail,
|
ItemType: ExchangeMail,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expect: assert.False,
|
expect: assert.False,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "teams chat",
|
||||||
|
ii: ItemInfo{
|
||||||
|
TeamsChats: &TeamsChatsInfo{
|
||||||
|
ItemType: TeamsChat,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expect: assert.False,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user