···
7
+
"tangled.sh/tangled.sh/core/appview/db"
8
+
"tangled.sh/tangled.sh/core/appview/notify"
9
+
"tangled.sh/tangled.sh/core/idresolver"
12
+
type databaseNotifier struct {
14
+
res *idresolver.Resolver
17
+
func NewDatabaseNotifier(database *db.DB, resolver *idresolver.Resolver) notify.Notifier {
18
+
return &databaseNotifier{
24
+
var _ notify.Notifier = &databaseNotifier{}
26
+
func (n *databaseNotifier) NewRepo(ctx context.Context, repo *db.Repo) {
30
+
func (n *databaseNotifier) NewStar(ctx context.Context, star *db.Star) {
32
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(star.RepoAt)))
34
+
log.Printf("NewStar: failed to get repos: %v", err)
37
+
if len(repos) == 0 {
38
+
log.Printf("NewStar: no repo found for %s", star.RepoAt)
43
+
// don't notify yourself
44
+
if repo.Did == star.StarredByDid {
48
+
// check if user wants these notifications
49
+
prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did)
51
+
log.Printf("NewStar: failed to get notification preferences for %s: %v", repo.Did, err)
54
+
if !prefs.RepoStarred {
58
+
notification := &models.Notification{
59
+
RecipientDid: repo.Did,
60
+
ActorDid: star.StarredByDid,
61
+
Type: models.NotificationTypeRepoStarred,
63
+
EntityId: string(star.RepoAt),
67
+
err = n.db.CreateNotification(ctx, notification)
69
+
log.Printf("NewStar: failed to create notification: %v", err)
74
+
func (n *databaseNotifier) DeleteStar(ctx context.Context, star *db.Star) {
78
+
func (n *databaseNotifier) NewIssue(ctx context.Context, issue *db.Issue) {
79
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(issue.RepoAt)))
81
+
log.Printf("NewIssue: failed to get repos: %v", err)
84
+
if len(repos) == 0 {
85
+
log.Printf("NewIssue: no repo found for %s", issue.RepoAt)
90
+
if repo.Did == issue.Did {
94
+
prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did)
96
+
log.Printf("NewIssue: failed to get notification preferences for %s: %v", repo.Did, err)
99
+
if !prefs.IssueCreated {
103
+
notification := &models.Notification{
104
+
RecipientDid: repo.Did,
105
+
ActorDid: issue.Did,
106
+
Type: models.NotificationTypeIssueCreated,
107
+
EntityType: "issue",
108
+
EntityId: string(issue.AtUri()),
110
+
IssueId: &issue.Id,
113
+
err = n.db.CreateNotification(ctx, notification)
115
+
log.Printf("NewIssue: failed to create notification: %v", err)
120
+
func (n *databaseNotifier) NewIssueComment(ctx context.Context, comment *db.IssueComment) {
121
+
issues, err := db.GetIssues(n.db, db.FilterEq("at_uri", comment.IssueAt))
123
+
log.Printf("NewIssueComment: failed to get issues: %v", err)
126
+
if len(issues) == 0 {
127
+
log.Printf("NewIssueComment: no issue found for %s", comment.IssueAt)
132
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(issue.RepoAt)))
134
+
log.Printf("NewIssueComment: failed to get repos: %v", err)
137
+
if len(repos) == 0 {
138
+
log.Printf("NewIssueComment: no repo found for %s", issue.RepoAt)
143
+
recipients := make(map[string]bool)
145
+
// notify issue author (if not the commenter)
146
+
if issue.Did != comment.Did {
147
+
prefs, err := n.db.GetNotificationPreferences(ctx, issue.Did)
148
+
if err == nil && prefs.IssueCommented {
149
+
recipients[issue.Did] = true
150
+
} else if err != nil {
151
+
log.Printf("NewIssueComment: failed to get preferences for issue author %s: %v", issue.Did, err)
155
+
// notify repo owner (if not the commenter and not already added)
156
+
if repo.Did != comment.Did && repo.Did != issue.Did {
157
+
prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did)
158
+
if err == nil && prefs.IssueCommented {
159
+
recipients[repo.Did] = true
160
+
} else if err != nil {
161
+
log.Printf("NewIssueComment: failed to get preferences for repo owner %s: %v", repo.Did, err)
165
+
// create notifications for all recipients
166
+
for recipientDid := range recipients {
167
+
notification := &models.Notification{
168
+
RecipientDid: recipientDid,
169
+
ActorDid: comment.Did,
170
+
Type: models.NotificationTypeIssueCommented,
171
+
EntityType: "issue",
172
+
EntityId: string(issue.AtUri()),
174
+
IssueId: &issue.Id,
177
+
err = n.db.CreateNotification(ctx, notification)
179
+
log.Printf("NewIssueComment: failed to create notification for %s: %v", recipientDid, err)
184
+
func (n *databaseNotifier) NewFollow(ctx context.Context, follow *db.Follow) {
185
+
prefs, err := n.db.GetNotificationPreferences(ctx, follow.SubjectDid)
187
+
log.Printf("NewFollow: failed to get notification preferences for %s: %v", follow.SubjectDid, err)
190
+
if !prefs.Followed {
194
+
notification := &models.Notification{
195
+
RecipientDid: follow.SubjectDid,
196
+
ActorDid: follow.UserDid,
197
+
Type: models.NotificationTypeFollowed,
198
+
EntityType: "follow",
199
+
EntityId: follow.UserDid,
202
+
err = n.db.CreateNotification(ctx, notification)
204
+
log.Printf("NewFollow: failed to create notification: %v", err)
209
+
func (n *databaseNotifier) DeleteFollow(ctx context.Context, follow *db.Follow) {
213
+
func (n *databaseNotifier) NewPull(ctx context.Context, pull *db.Pull) {
214
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(pull.RepoAt)))
216
+
log.Printf("NewPull: failed to get repos: %v", err)
219
+
if len(repos) == 0 {
220
+
log.Printf("NewPull: no repo found for %s", pull.RepoAt)
225
+
if repo.Did == pull.OwnerDid {
229
+
prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did)
231
+
log.Printf("NewPull: failed to get notification preferences for %s: %v", repo.Did, err)
234
+
if !prefs.PullCreated {
238
+
notification := &models.Notification{
239
+
RecipientDid: repo.Did,
240
+
ActorDid: pull.OwnerDid,
241
+
Type: models.NotificationTypePullCreated,
242
+
EntityType: "pull",
243
+
EntityId: string(pull.RepoAt),
245
+
PullId: func() *int64 { id := int64(pull.ID); return &id }(),
248
+
err = n.db.CreateNotification(ctx, notification)
250
+
log.Printf("NewPull: failed to create notification: %v", err)
255
+
func (n *databaseNotifier) NewPullComment(ctx context.Context, comment *db.PullComment) {
256
+
pulls, err := db.GetPulls(n.db,
257
+
db.FilterEq("repo_at", comment.RepoAt),
258
+
db.FilterEq("pull_id", comment.PullId))
260
+
log.Printf("NewPullComment: failed to get pulls: %v", err)
263
+
if len(pulls) == 0 {
264
+
log.Printf("NewPullComment: no pull found for %s PR %d", comment.RepoAt, comment.PullId)
269
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", comment.RepoAt))
271
+
log.Printf("NewPullComment: failed to get repos: %v", err)
274
+
if len(repos) == 0 {
275
+
log.Printf("NewPullComment: no repo found for %s", comment.RepoAt)
280
+
recipients := make(map[string]bool)
282
+
// notify pull request author (if not the commenter)
283
+
if pull.OwnerDid != comment.OwnerDid {
284
+
prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid)
285
+
if err == nil && prefs.PullCommented {
286
+
recipients[pull.OwnerDid] = true
287
+
} else if err != nil {
288
+
log.Printf("NewPullComment: failed to get preferences for pull author %s: %v", pull.OwnerDid, err)
292
+
// notify repo owner (if not the commenter and not already added)
293
+
if repo.Did != comment.OwnerDid && repo.Did != pull.OwnerDid {
294
+
prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did)
295
+
if err == nil && prefs.PullCommented {
296
+
recipients[repo.Did] = true
297
+
} else if err != nil {
298
+
log.Printf("NewPullComment: failed to get preferences for repo owner %s: %v", repo.Did, err)
302
+
for recipientDid := range recipients {
303
+
notification := &models.Notification{
304
+
RecipientDid: recipientDid,
305
+
ActorDid: comment.OwnerDid,
306
+
Type: models.NotificationTypePullCommented,
307
+
EntityType: "pull",
308
+
EntityId: comment.RepoAt,
310
+
PullId: func() *int64 { id := int64(pull.ID); return &id }(),
313
+
err = n.db.CreateNotification(ctx, notification)
315
+
log.Printf("NewPullComment: failed to create notification for %s: %v", recipientDid, err)
320
+
func (n *databaseNotifier) UpdateProfile(ctx context.Context, profile *db.Profile) {
324
+
func (n *databaseNotifier) DeleteString(ctx context.Context, did, rkey string) {
328
+
func (n *databaseNotifier) EditString(ctx context.Context, string *db.String) {
332
+
func (n *databaseNotifier) NewString(ctx context.Context, string *db.String) {
336
+
func (n *databaseNotifier) NewIssueClosed(ctx context.Context, issue *db.Issue) {
337
+
// Get repo details
338
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(issue.RepoAt)))
340
+
log.Printf("NewIssueClosed: failed to get repos: %v", err)
343
+
if len(repos) == 0 {
344
+
log.Printf("NewIssueClosed: no repo found for %s", issue.RepoAt)
349
+
// Don't notify yourself
350
+
if repo.Did == issue.Did {
354
+
// Check if user wants these notifications
355
+
prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did)
357
+
log.Printf("NewIssueClosed: failed to get notification preferences for %s: %v", repo.Did, err)
360
+
if !prefs.IssueClosed {
364
+
notification := &models.Notification{
365
+
RecipientDid: repo.Did,
366
+
ActorDid: issue.Did,
367
+
Type: models.NotificationTypeIssueClosed,
368
+
EntityType: "issue",
369
+
EntityId: string(issue.AtUri()),
371
+
IssueId: &issue.Id,
374
+
err = n.db.CreateNotification(ctx, notification)
376
+
log.Printf("NewIssueClosed: failed to create notification: %v", err)
381
+
func (n *databaseNotifier) NewPullMerged(ctx context.Context, pull *db.Pull) {
382
+
// Get repo details
383
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(pull.RepoAt)))
385
+
log.Printf("NewPullMerged: failed to get repos: %v", err)
388
+
if len(repos) == 0 {
389
+
log.Printf("NewPullMerged: no repo found for %s", pull.RepoAt)
394
+
// Don't notify yourself
395
+
if repo.Did == pull.OwnerDid {
399
+
// Check if user wants these notifications
400
+
prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid)
402
+
log.Printf("NewPullMerged: failed to get notification preferences for %s: %v", pull.OwnerDid, err)
405
+
if !prefs.PullMerged {
409
+
notification := &models.Notification{
410
+
RecipientDid: pull.OwnerDid,
411
+
ActorDid: repo.Did,
412
+
Type: models.NotificationTypePullMerged,
413
+
EntityType: "pull",
414
+
EntityId: string(pull.RepoAt),
416
+
PullId: func() *int64 { id := int64(pull.ID); return &id }(),
419
+
err = n.db.CreateNotification(ctx, notification)
421
+
log.Printf("NewPullMerged: failed to create notification: %v", err)
426
+
func (n *databaseNotifier) NewPullClosed(ctx context.Context, pull *db.Pull) {
427
+
// Get repo details
428
+
repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(pull.RepoAt)))
430
+
log.Printf("NewPullClosed: failed to get repos: %v", err)
433
+
if len(repos) == 0 {
434
+
log.Printf("NewPullClosed: no repo found for %s", pull.RepoAt)
439
+
// Don't notify yourself
440
+
if repo.Did == pull.OwnerDid {
444
+
// Check if user wants these notifications - reuse pull_merged preference for now
445
+
prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid)
447
+
log.Printf("NewPullClosed: failed to get notification preferences for %s: %v", pull.OwnerDid, err)
450
+
if !prefs.PullMerged {
454
+
notification := &models.Notification{
455
+
RecipientDid: pull.OwnerDid,
456
+
ActorDid: repo.Did,
457
+
Type: models.NotificationTypePullClosed,
458
+
EntityType: "pull",
459
+
EntityId: string(pull.RepoAt),
461
+
PullId: func() *int64 { id := int64(pull.ID); return &id }(),
464
+
err = n.db.CreateNotification(ctx, notification)
466
+
log.Printf("NewPullClosed: failed to create notification: %v", err)