-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsender.go
117 lines (94 loc) · 2.79 KB
/
sender.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package chat
import (
"context"
"errors"
"time"
"github.com/mr-tron/base58"
"google.golang.org/protobuf/proto"
chatpb "github.com/code-payments/code-protobuf-api/generated/go/chat/v1"
"github.com/code-payments/code-server/pkg/code/common"
code_data "github.com/code-payments/code-server/pkg/code/data"
"github.com/code-payments/code-server/pkg/code/data/chat"
)
// SendChatMessage sends a chat message to a receiving owner account.
//
// Note: This function is not responsible for push notifications. This method
// might be called within the context of a DB transaction, which might have
// unrelated failures. A hint as to whether a push should be sent is provided.
func SendChatMessage(
ctx context.Context,
data code_data.Provider,
chatTitle string,
chatType chat.ChatType,
isVerifiedChat bool,
receiver *common.Account,
protoMessage *chatpb.ChatMessage,
isSilentMessage bool,
) (canPushMessage bool, err error) {
chatId := chat.GetChatId(chatTitle, receiver.PublicKey().ToBase58(), isVerifiedChat)
if protoMessage.Cursor != nil {
// Let the utilities and GetMessages RPC handle cursors
return false, errors.New("cursor must not be set")
}
if err := protoMessage.Validate(); err != nil {
return false, err
}
messageId := protoMessage.MessageId.Value
ts := protoMessage.Ts
// Clear out extracted metadata as a space optimization
cloned := proto.Clone(protoMessage).(*chatpb.ChatMessage)
cloned.MessageId = nil
cloned.Ts = nil
cloned.Cursor = nil
marshalled, err := proto.Marshal(cloned)
if err != nil {
return false, err
}
canPersistMessage := true
canPushMessage = !isSilentMessage
existingChatRecord, err := data.GetChatById(ctx, chatId)
switch err {
case nil:
canPersistMessage = !existingChatRecord.IsUnsubscribed
canPushMessage = canPushMessage && canPersistMessage && !existingChatRecord.IsMuted
case chat.ErrChatNotFound:
chatRecord := &chat.Chat{
ChatId: chatId,
ChatType: chatType,
ChatTitle: chatTitle,
IsVerified: isVerifiedChat,
CodeUser: receiver.PublicKey().ToBase58(),
ReadPointer: nil,
IsMuted: false,
IsUnsubscribed: false,
CreatedAt: time.Now(),
}
err = data.PutChat(ctx, chatRecord)
if err != nil && err != chat.ErrChatAlreadyExists {
return false, err
}
default:
return false, err
}
if canPersistMessage {
messageRecord := &chat.Message{
ChatId: chatId,
MessageId: base58.Encode(messageId),
Data: marshalled,
IsSilent: isSilentMessage,
ContentLength: uint8(len(protoMessage.Content)),
Timestamp: ts.AsTime(),
}
err = data.PutChatMessage(ctx, messageRecord)
if err != nil {
return false, err
}
}
if canPushMessage {
err = data.AddToBadgeCount(ctx, receiver.PublicKey().ToBase58(), 1)
if err != nil {
return false, err
}
}
return canPushMessage, nil
}