Compare commits
4 Commits
main
...
conv_reply
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5649c93eda | ||
|
|
e1f569d4e6 | ||
|
|
4dcb820201 | ||
|
|
7b193a06a0 |
@ -19,15 +19,19 @@ var _ backupHandler[models.Conversationable, models.Postable] = &conversationsBa
|
|||||||
type conversationsBackupHandler struct {
|
type conversationsBackupHandler struct {
|
||||||
ac api.Conversations
|
ac api.Conversations
|
||||||
protectedResource string
|
protectedResource string
|
||||||
|
// SMTP address for the group
|
||||||
|
resourceEmail string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConversationBackupHandler(
|
func NewConversationBackupHandler(
|
||||||
protectedResource string,
|
protectedResource string,
|
||||||
ac api.Conversations,
|
ac api.Conversations,
|
||||||
|
email string,
|
||||||
) conversationsBackupHandler {
|
) conversationsBackupHandler {
|
||||||
return conversationsBackupHandler{
|
return conversationsBackupHandler{
|
||||||
ac: ac,
|
ac: ac,
|
||||||
protectedResource: protectedResource,
|
protectedResource: protectedResource,
|
||||||
|
resourceEmail: email,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,13 +124,17 @@ func (bh conversationsBackupHandler) getItem(
|
|||||||
containerIDs path.Elements, // expects: [conversationID, threadID]
|
containerIDs path.Elements, // expects: [conversationID, threadID]
|
||||||
postID string,
|
postID string,
|
||||||
) (models.Postable, *details.GroupsInfo, error) {
|
) (models.Postable, *details.GroupsInfo, error) {
|
||||||
|
cc := api.CallConfig{
|
||||||
|
Expand: []string{"inReplyTo"},
|
||||||
|
}
|
||||||
|
|
||||||
return bh.ac.GetConversationPost(
|
return bh.ac.GetConversationPost(
|
||||||
ctx,
|
ctx,
|
||||||
groupID,
|
groupID,
|
||||||
containerIDs[0],
|
containerIDs[0],
|
||||||
containerIDs[1],
|
containerIDs[1],
|
||||||
postID,
|
postID,
|
||||||
api.CallConfig{})
|
cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
//lint:ignore U1000 false linter issue due to generics
|
//lint:ignore U1000 false linter issue due to generics
|
||||||
@ -134,6 +142,13 @@ func (bh conversationsBackupHandler) augmentItemInfo(
|
|||||||
dgi *details.GroupsInfo,
|
dgi *details.GroupsInfo,
|
||||||
c models.Conversationable,
|
c models.Conversationable,
|
||||||
) {
|
) {
|
||||||
|
// Posts are always sent to the group email address, along with additional
|
||||||
|
// recipients if any. Currently we don't have a way to get the unique
|
||||||
|
// recipient list for individual posts due to graph api limitations.
|
||||||
|
//
|
||||||
|
// Store the group mail address so that we can use it to populate the 'To'
|
||||||
|
// field during Post -> EML exports.
|
||||||
|
dgi.Post.Recipients = []string{bh.resourceEmail}
|
||||||
dgi.Post.Topic = ptr.Val(c.GetTopic())
|
dgi.Post.Topic = ptr.Val(c.GetTopic())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package groups
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/alcionai/clues"
|
"github.com/alcionai/clues"
|
||||||
"github.com/kopia/kopia/repo/manifest"
|
"github.com/kopia/kopia/repo/manifest"
|
||||||
@ -319,10 +320,17 @@ func backupConversations(
|
|||||||
counter *count.Bus,
|
counter *count.Bus,
|
||||||
errs *fault.Bus,
|
errs *fault.Bus,
|
||||||
) ([]data.BackupCollection, error) {
|
) ([]data.BackupCollection, error) {
|
||||||
|
groupEmail := strings.Clone(ptr.Val(bc.group.GetMail()))
|
||||||
|
// This is unlikely, but if it does happen in the wild, we should investigate it.
|
||||||
|
if len(groupEmail) == 0 {
|
||||||
|
return nil, clues.New("group has no mail address")
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bh = groups.NewConversationBackupHandler(
|
bh = groups.NewConversationBackupHandler(
|
||||||
bc.producerConfig.ProtectedResource.ID(),
|
bc.producerConfig.ProtectedResource.ID(),
|
||||||
bc.apiCli.Conversations())
|
bc.apiCli.Conversations(),
|
||||||
|
groupEmail)
|
||||||
colls []data.BackupCollection
|
colls []data.BackupCollection
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -61,11 +61,13 @@ type GroupsInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ConversationPostInfo struct {
|
type ConversationPostInfo struct {
|
||||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||||
Creator string `json:"creator,omitempty"`
|
Creator string `json:"creator,omitempty"`
|
||||||
Preview string `json:"preview,omitempty"`
|
Preview string `json:"preview,omitempty"`
|
||||||
Size int64 `json:"size,omitempty"`
|
Recipients []string `json:"recipients,omitempty"`
|
||||||
Topic string `json:"topic,omitempty"`
|
InReplyTo string `json:"inReplyTo,omitempty"`
|
||||||
|
Size int64 `json:"size,omitempty"`
|
||||||
|
Topic string `json:"topic,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelMessageInfo struct {
|
type ChannelMessageInfo struct {
|
||||||
|
|||||||
@ -69,8 +69,25 @@ func (c Conversations) GetConversationPost(
|
|||||||
preview = "malformed or unparseable content body: " + preview
|
preview = "malformed or unparseable content body: " + preview
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var inReplyToID string
|
||||||
|
|
||||||
|
prevPost := post.GetInReplyTo()
|
||||||
|
if prevPost != nil {
|
||||||
|
inReplyToID = ptr.Val(prevPost.GetId())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set prev post to nil to avoid storing it again in the backup. Storage is unnecessary
|
||||||
|
// since this is a read only property and graph doesn't support POSTing it. This is
|
||||||
|
// also safe to do since we do a full enumeration every time, so post and all its
|
||||||
|
// ancestors are guaranteed to exist.
|
||||||
|
//
|
||||||
|
// All we need to persist here is the prev post ID here so that we can build the
|
||||||
|
// reply tree during restore operation and restore posts top to bottom using
|
||||||
|
// POST /groups/{id}/conversations/{id}/threads/{id}/posts/{id}/reply
|
||||||
|
post.SetInReplyTo(nil)
|
||||||
|
|
||||||
if !ptr.Val(post.GetHasAttachments()) && !HasAttachments(post.GetBody()) {
|
if !ptr.Val(post.GetHasAttachments()) && !HasAttachments(post.GetBody()) {
|
||||||
return post, conversationPostInfo(post, contentLen, preview), nil
|
return post, conversationPostInfo(post, contentLen, preview, inReplyToID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments, totalSize, err := c.getAttachments(
|
attachments, totalSize, err := c.getAttachments(
|
||||||
@ -95,7 +112,9 @@ func (c Conversations) GetConversationPost(
|
|||||||
|
|
||||||
post.SetAttachments(attachments)
|
post.SetAttachments(attachments)
|
||||||
|
|
||||||
return post, conversationPostInfo(post, contentLen, preview), graph.Stack(ctx, err).OrNil()
|
return post,
|
||||||
|
conversationPostInfo(post, contentLen, preview, inReplyToID),
|
||||||
|
graph.Stack(ctx, err).OrNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -105,7 +124,7 @@ func (c Conversations) GetConversationPost(
|
|||||||
func conversationPostInfo(
|
func conversationPostInfo(
|
||||||
post models.Postable,
|
post models.Postable,
|
||||||
size int64,
|
size int64,
|
||||||
preview string,
|
preview, inReplyToID string,
|
||||||
) *details.GroupsInfo {
|
) *details.GroupsInfo {
|
||||||
if post == nil {
|
if post == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -120,6 +139,7 @@ func conversationPostInfo(
|
|||||||
CreatedAt: ptr.Val(post.GetCreatedDateTime()),
|
CreatedAt: ptr.Val(post.GetCreatedDateTime()),
|
||||||
Creator: sender,
|
Creator: sender,
|
||||||
Preview: preview,
|
Preview: preview,
|
||||||
|
InReplyTo: inReplyToID,
|
||||||
Size: size,
|
Size: size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -109,7 +109,7 @@ func (suite *ConversationsAPIUnitSuite) TestConversationPostInfo() {
|
|||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
post, expected := test.postAndInfo()
|
post, expected := test.postAndInfo()
|
||||||
result := conversationPostInfo(post, 0, "")
|
result := conversationPostInfo(post, 0, "", "")
|
||||||
|
|
||||||
assert.Equal(t, expected, result)
|
assert.Equal(t, expected, result)
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user