/
notifications_posts.go
177 lines (140 loc) · 5.45 KB
/
notifications_posts.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package notifications
import (
"strings"
"github.com/rs/zerolog/log"
poststypes "github.com/desmos-labs/desmos/v6/x/posts/types"
"github.com/desmos-labs/athena/types"
notificationsbuilder "github.com/desmos-labs/athena/x/notifications/builder"
)
func (m *Module) getPostNotificationData(originalPost types.Post, reply types.Post, builder notificationsbuilder.PostNotificationBuilder) types.NotificationData {
if builder == nil {
return nil
}
return builder(originalPost, reply)
}
// -------------------------------------------------------------------------------------------------------------------
// SendPostNotifications sends all the notifications to the users that are somehow involved with the given post.
// These include:
// - the author of the original post to which the post is a reply (if any)
// - the users mentioned inside the post
// - the authors of the various referenced posts (if this post is a reply/repost/quote)
func (m *Module) SendPostNotifications(height int64, subspaceID uint64, postID uint64) error {
post, err := m.postsModule.GetPost(height, subspaceID, postID)
if err != nil {
return err
}
// List of users already notified
var notifiedUsers []string
// Send post references notifications
for _, reference := range post.ReferencedPosts {
// Do nothing if the post with the same id is both the original post and the post to which has been replied
if reference.PostID == post.ConversationID {
continue
}
originalPost, err := m.postsModule.GetPost(height, subspaceID, reference.PostID)
if err != nil {
return err
}
err = m.sendPostReferenceNotification(originalPost, reference.Type, post, notifiedUsers)
if err != nil {
return err
}
notifiedUsers = append(notifiedUsers, originalPost.Author)
}
// Send conversation notification
if post.ConversationID != 0 {
conversationPost, err := m.postsModule.GetPost(height, subspaceID, post.ConversationID)
if err != nil {
return err
}
err = m.sendConversationNotification(conversationPost, post, notifiedUsers)
if err != nil {
return err
}
notifiedUsers = append(notifiedUsers, conversationPost.Author)
}
// Send mentions notification
if post.Entities != nil {
for _, mention := range post.Entities.Mentions {
err = m.sendPostMentionNotification(post, mention, notifiedUsers)
if err != nil {
return err
}
}
}
return nil
}
func (m *Module) getMentionNotificationData(post types.Post, mention poststypes.TextTag, builder notificationsbuilder.MentionNotificationBuilder) types.NotificationData {
if builder == nil {
return nil
}
return builder(post, mention)
}
func (m *Module) sendConversationNotification(originalPost types.Post, reply types.Post, notifiedUsers []string) error {
// Skip if the post author and the original author are the same
if originalPost.Author == reply.Author {
return nil
}
// Skip if the referenced post author has already been notified
if hasBeenNotified(originalPost.Author, notifiedUsers) {
return nil
}
// Get the notification data
data := m.getPostNotificationData(originalPost, reply, m.notificationsBuilder.Posts().Comment())
if data == nil {
return nil
}
log.Trace().Str("module", m.Name()).Str("recipient", originalPost.Author).
Str("notification type", "post reply").Msg("sending notification")
return m.SendAndStoreNotification(types.NewNotificationUserRecipient(originalPost.Author), data)
}
func (m *Module) sendPostReferenceNotification(originalPost types.Post, referenceType poststypes.PostReferenceType, reference types.Post, notifiedUsers []string) error {
// Skip if the referenced post and the original post authors are the same
if reference.Author == originalPost.Author {
return nil
}
// Skip if the referenced post author has already been notified
if hasBeenNotified(originalPost.Author, notifiedUsers) {
return nil
}
var data types.NotificationData
switch referenceType {
case poststypes.POST_REFERENCE_TYPE_REPLY:
data = m.getPostNotificationData(originalPost, reference, m.notificationsBuilder.Posts().Reply())
case poststypes.POST_REFERENCE_TYPE_REPOST:
data = m.getPostNotificationData(originalPost, reference, m.notificationsBuilder.Posts().Repost())
case poststypes.POST_REFERENCE_TYPE_QUOTE:
data = m.getPostNotificationData(originalPost, reference, m.notificationsBuilder.Posts().Quote())
}
if data == nil {
return nil
}
log.Trace().Str("module", m.Name()).Str("recipient", originalPost.Author).
Str("notification type", "post reference").Msg("sending notification")
return m.SendAndStoreNotification(types.NewNotificationUserRecipient(originalPost.Author), data)
}
func (m *Module) sendPostMentionNotification(post types.Post, mention poststypes.TextTag, notifiedUsers []string) error {
// Skip if the post author and the mentioned user is the same
if post.Author == mention.Tag {
return nil
}
// Skip if the mentioned user has already been notified
if hasBeenNotified(mention.Tag, notifiedUsers) {
return nil
}
data := m.getMentionNotificationData(post, mention, m.notificationsBuilder.Posts().Mention())
if data == nil {
return nil
}
log.Trace().Str("module", m.Name()).Str("recipient", mention.Tag).
Str("notification type", "post mention").Msg("sending notification")
return m.SendAndStoreNotification(types.NewNotificationUserRecipient(mention.Tag), data)
}
func hasBeenNotified(user string, notifiedUsers []string) bool {
for _, notifiedUser := range notifiedUsers {
if strings.EqualFold(user, notifiedUser) {
return true
}
}
return false
}