forked from tangled.org/core
this repo has no description
at master 12 kB view raw
1package db 2 3import ( 4 "context" 5 "log" 6 7 "tangled.org/core/appview/db" 8 "tangled.org/core/appview/models" 9 "tangled.org/core/appview/notify" 10 "tangled.org/core/idresolver" 11) 12 13type databaseNotifier struct { 14 db *db.DB 15 res *idresolver.Resolver 16} 17 18func NewDatabaseNotifier(database *db.DB, resolver *idresolver.Resolver) notify.Notifier { 19 return &databaseNotifier{ 20 db: database, 21 res: resolver, 22 } 23} 24 25var _ notify.Notifier = &databaseNotifier{} 26 27func (n *databaseNotifier) NewRepo(ctx context.Context, repo *models.Repo) { 28 // no-op for now 29} 30 31func (n *databaseNotifier) NewStar(ctx context.Context, star *models.Star) { 32 var err error 33 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(star.RepoAt))) 34 if err != nil { 35 log.Printf("NewStar: failed to get repos: %v", err) 36 return 37 } 38 39 // don't notify yourself 40 if repo.Did == star.StarredByDid { 41 return 42 } 43 44 // check if user wants these notifications 45 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 46 if err != nil { 47 log.Printf("NewStar: failed to get notification preferences for %s: %v", repo.Did, err) 48 return 49 } 50 if !prefs.RepoStarred { 51 return 52 } 53 54 notification := &models.Notification{ 55 RecipientDid: repo.Did, 56 ActorDid: star.StarredByDid, 57 Type: models.NotificationTypeRepoStarred, 58 EntityType: "repo", 59 EntityId: string(star.RepoAt), 60 RepoId: &repo.Id, 61 } 62 err = n.db.CreateNotification(ctx, notification) 63 if err != nil { 64 log.Printf("NewStar: failed to create notification: %v", err) 65 return 66 } 67} 68 69func (n *databaseNotifier) DeleteStar(ctx context.Context, star *models.Star) { 70 // no-op 71} 72 73func (n *databaseNotifier) NewIssue(ctx context.Context, issue *models.Issue) { 74 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(issue.RepoAt))) 75 if err != nil { 76 log.Printf("NewIssue: failed to get repos: %v", err) 77 return 78 } 79 80 if repo.Did == issue.Did { 81 return 82 } 83 84 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 85 if err != nil { 86 log.Printf("NewIssue: failed to get notification preferences for %s: %v", repo.Did, err) 87 return 88 } 89 if !prefs.IssueCreated { 90 return 91 } 92 93 notification := &models.Notification{ 94 RecipientDid: repo.Did, 95 ActorDid: issue.Did, 96 Type: models.NotificationTypeIssueCreated, 97 EntityType: "issue", 98 EntityId: string(issue.AtUri()), 99 RepoId: &repo.Id, 100 IssueId: &issue.Id, 101 } 102 103 err = n.db.CreateNotification(ctx, notification) 104 if err != nil { 105 log.Printf("NewIssue: failed to create notification: %v", err) 106 return 107 } 108} 109 110func (n *databaseNotifier) NewIssueComment(ctx context.Context, comment *models.IssueComment) { 111 issues, err := db.GetIssues(n.db, db.FilterEq("at_uri", comment.IssueAt)) 112 if err != nil { 113 log.Printf("NewIssueComment: failed to get issues: %v", err) 114 return 115 } 116 if len(issues) == 0 { 117 log.Printf("NewIssueComment: no issue found for %s", comment.IssueAt) 118 return 119 } 120 issue := issues[0] 121 122 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(issue.RepoAt))) 123 if err != nil { 124 log.Printf("NewIssueComment: failed to get repos: %v", err) 125 return 126 } 127 128 recipients := make(map[string]bool) 129 130 // notify issue author (if not the commenter) 131 if issue.Did != comment.Did { 132 prefs, err := n.db.GetNotificationPreferences(ctx, issue.Did) 133 if err == nil && prefs.IssueCommented { 134 recipients[issue.Did] = true 135 } else if err != nil { 136 log.Printf("NewIssueComment: failed to get preferences for issue author %s: %v", issue.Did, err) 137 } 138 } 139 140 // notify repo owner (if not the commenter and not already added) 141 if repo.Did != comment.Did && repo.Did != issue.Did { 142 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 143 if err == nil && prefs.IssueCommented { 144 recipients[repo.Did] = true 145 } else if err != nil { 146 log.Printf("NewIssueComment: failed to get preferences for repo owner %s: %v", repo.Did, err) 147 } 148 } 149 150 // create notifications for all recipients 151 for recipientDid := range recipients { 152 notification := &models.Notification{ 153 RecipientDid: recipientDid, 154 ActorDid: comment.Did, 155 Type: models.NotificationTypeIssueCommented, 156 EntityType: "issue", 157 EntityId: string(issue.AtUri()), 158 RepoId: &repo.Id, 159 IssueId: &issue.Id, 160 } 161 162 err = n.db.CreateNotification(ctx, notification) 163 if err != nil { 164 log.Printf("NewIssueComment: failed to create notification for %s: %v", recipientDid, err) 165 } 166 } 167} 168 169func (n *databaseNotifier) NewFollow(ctx context.Context, follow *models.Follow) { 170 prefs, err := n.db.GetNotificationPreferences(ctx, follow.SubjectDid) 171 if err != nil { 172 log.Printf("NewFollow: failed to get notification preferences for %s: %v", follow.SubjectDid, err) 173 return 174 } 175 if !prefs.Followed { 176 return 177 } 178 179 notification := &models.Notification{ 180 RecipientDid: follow.SubjectDid, 181 ActorDid: follow.UserDid, 182 Type: models.NotificationTypeFollowed, 183 EntityType: "follow", 184 EntityId: follow.UserDid, 185 } 186 187 err = n.db.CreateNotification(ctx, notification) 188 if err != nil { 189 log.Printf("NewFollow: failed to create notification: %v", err) 190 return 191 } 192} 193 194func (n *databaseNotifier) DeleteFollow(ctx context.Context, follow *models.Follow) { 195 // no-op 196} 197 198func (n *databaseNotifier) NewPull(ctx context.Context, pull *models.Pull) { 199 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(pull.RepoAt))) 200 if err != nil { 201 log.Printf("NewPull: failed to get repos: %v", err) 202 return 203 } 204 205 if repo.Did == pull.OwnerDid { 206 return 207 } 208 209 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 210 if err != nil { 211 log.Printf("NewPull: failed to get notification preferences for %s: %v", repo.Did, err) 212 return 213 } 214 if !prefs.PullCreated { 215 return 216 } 217 218 notification := &models.Notification{ 219 RecipientDid: repo.Did, 220 ActorDid: pull.OwnerDid, 221 Type: models.NotificationTypePullCreated, 222 EntityType: "pull", 223 EntityId: string(pull.RepoAt), 224 RepoId: &repo.Id, 225 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 226 } 227 228 err = n.db.CreateNotification(ctx, notification) 229 if err != nil { 230 log.Printf("NewPull: failed to create notification: %v", err) 231 return 232 } 233} 234 235func (n *databaseNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) { 236 pulls, err := db.GetPulls(n.db, 237 db.FilterEq("repo_at", comment.RepoAt), 238 db.FilterEq("pull_id", comment.PullId)) 239 if err != nil { 240 log.Printf("NewPullComment: failed to get pulls: %v", err) 241 return 242 } 243 if len(pulls) == 0 { 244 log.Printf("NewPullComment: no pull found for %s PR %d", comment.RepoAt, comment.PullId) 245 return 246 } 247 pull := pulls[0] 248 249 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", comment.RepoAt)) 250 if err != nil { 251 log.Printf("NewPullComment: failed to get repos: %v", err) 252 return 253 } 254 255 recipients := make(map[string]bool) 256 257 // notify pull request author (if not the commenter) 258 if pull.OwnerDid != comment.OwnerDid { 259 prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid) 260 if err == nil && prefs.PullCommented { 261 recipients[pull.OwnerDid] = true 262 } else if err != nil { 263 log.Printf("NewPullComment: failed to get preferences for pull author %s: %v", pull.OwnerDid, err) 264 } 265 } 266 267 // notify repo owner (if not the commenter and not already added) 268 if repo.Did != comment.OwnerDid && repo.Did != pull.OwnerDid { 269 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 270 if err == nil && prefs.PullCommented { 271 recipients[repo.Did] = true 272 } else if err != nil { 273 log.Printf("NewPullComment: failed to get preferences for repo owner %s: %v", repo.Did, err) 274 } 275 } 276 277 for recipientDid := range recipients { 278 notification := &models.Notification{ 279 RecipientDid: recipientDid, 280 ActorDid: comment.OwnerDid, 281 Type: models.NotificationTypePullCommented, 282 EntityType: "pull", 283 EntityId: comment.RepoAt, 284 RepoId: &repo.Id, 285 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 286 } 287 288 err = n.db.CreateNotification(ctx, notification) 289 if err != nil { 290 log.Printf("NewPullComment: failed to create notification for %s: %v", recipientDid, err) 291 } 292 } 293} 294 295func (n *databaseNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) { 296 // no-op 297} 298 299func (n *databaseNotifier) DeleteString(ctx context.Context, did, rkey string) { 300 // no-op 301} 302 303func (n *databaseNotifier) EditString(ctx context.Context, string *models.String) { 304 // no-op 305} 306 307func (n *databaseNotifier) NewString(ctx context.Context, string *models.String) { 308 // no-op 309} 310 311func (n *databaseNotifier) NewIssueClosed(ctx context.Context, issue *models.Issue) { 312 // Get repo details 313 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(issue.RepoAt))) 314 if err != nil { 315 log.Printf("NewIssueClosed: failed to get repos: %v", err) 316 return 317 } 318 319 // Don't notify yourself 320 if repo.Did == issue.Did { 321 return 322 } 323 324 // Check if user wants these notifications 325 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 326 if err != nil { 327 log.Printf("NewIssueClosed: failed to get notification preferences for %s: %v", repo.Did, err) 328 return 329 } 330 if !prefs.IssueClosed { 331 return 332 } 333 334 notification := &models.Notification{ 335 RecipientDid: repo.Did, 336 ActorDid: issue.Did, 337 Type: models.NotificationTypeIssueClosed, 338 EntityType: "issue", 339 EntityId: string(issue.AtUri()), 340 RepoId: &repo.Id, 341 IssueId: &issue.Id, 342 } 343 344 err = n.db.CreateNotification(ctx, notification) 345 if err != nil { 346 log.Printf("NewIssueClosed: failed to create notification: %v", err) 347 return 348 } 349} 350 351func (n *databaseNotifier) NewPullMerged(ctx context.Context, pull *models.Pull) { 352 // Get repo details 353 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(pull.RepoAt))) 354 if err != nil { 355 log.Printf("NewPullMerged: failed to get repos: %v", err) 356 return 357 } 358 359 // Don't notify yourself 360 if repo.Did == pull.OwnerDid { 361 return 362 } 363 364 // Check if user wants these notifications 365 prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid) 366 if err != nil { 367 log.Printf("NewPullMerged: failed to get notification preferences for %s: %v", pull.OwnerDid, err) 368 return 369 } 370 if !prefs.PullMerged { 371 return 372 } 373 374 notification := &models.Notification{ 375 RecipientDid: pull.OwnerDid, 376 ActorDid: repo.Did, 377 Type: models.NotificationTypePullMerged, 378 EntityType: "pull", 379 EntityId: string(pull.RepoAt), 380 RepoId: &repo.Id, 381 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 382 } 383 384 err = n.db.CreateNotification(ctx, notification) 385 if err != nil { 386 log.Printf("NewPullMerged: failed to create notification: %v", err) 387 return 388 } 389} 390 391func (n *databaseNotifier) NewPullClosed(ctx context.Context, pull *models.Pull) { 392 // Get repo details 393 repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(pull.RepoAt))) 394 if err != nil { 395 log.Printf("NewPullClosed: failed to get repos: %v", err) 396 return 397 } 398 399 // Don't notify yourself 400 if repo.Did == pull.OwnerDid { 401 return 402 } 403 404 // Check if user wants these notifications - reuse pull_merged preference for now 405 prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid) 406 if err != nil { 407 log.Printf("NewPullClosed: failed to get notification preferences for %s: %v", pull.OwnerDid, err) 408 return 409 } 410 if !prefs.PullMerged { 411 return 412 } 413 414 notification := &models.Notification{ 415 RecipientDid: pull.OwnerDid, 416 ActorDid: repo.Did, 417 Type: models.NotificationTypePullClosed, 418 EntityType: "pull", 419 EntityId: string(pull.RepoAt), 420 RepoId: &repo.Id, 421 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 422 } 423 424 err = n.db.CreateNotification(ctx, notification) 425 if err != nil { 426 log.Printf("NewPullClosed: failed to create notification: %v", err) 427 return 428 } 429}