this repo has no description
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 repos, err := db.GetRepos(n.db, 1, 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 if len(repos) == 0 { 39 log.Printf("NewStar: no repo found for %s", star.RepoAt) 40 return 41 } 42 repo := repos[0] 43 44 // don't notify yourself 45 if repo.Did == star.StarredByDid { 46 return 47 } 48 49 // check if user wants these notifications 50 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 51 if err != nil { 52 log.Printf("NewStar: failed to get notification preferences for %s: %v", repo.Did, err) 53 return 54 } 55 if !prefs.RepoStarred { 56 return 57 } 58 59 notification := &models.Notification{ 60 RecipientDid: repo.Did, 61 ActorDid: star.StarredByDid, 62 Type: models.NotificationTypeRepoStarred, 63 EntityType: "repo", 64 EntityId: string(star.RepoAt), 65 RepoId: &repo.Id, 66 } 67 err = n.db.CreateNotification(ctx, notification) 68 if err != nil { 69 log.Printf("NewStar: failed to create notification: %v", err) 70 return 71 } 72} 73 74func (n *databaseNotifier) DeleteStar(ctx context.Context, star *models.Star) { 75 // no-op 76} 77 78func (n *databaseNotifier) NewIssue(ctx context.Context, issue *models.Issue) { 79 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(issue.RepoAt))) 80 if err != nil { 81 log.Printf("NewIssue: failed to get repos: %v", err) 82 return 83 } 84 if len(repos) == 0 { 85 log.Printf("NewIssue: no repo found for %s", issue.RepoAt) 86 return 87 } 88 repo := repos[0] 89 90 if repo.Did == issue.Did { 91 return 92 } 93 94 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 95 if err != nil { 96 log.Printf("NewIssue: failed to get notification preferences for %s: %v", repo.Did, err) 97 return 98 } 99 if !prefs.IssueCreated { 100 return 101 } 102 103 notification := &models.Notification{ 104 RecipientDid: repo.Did, 105 ActorDid: issue.Did, 106 Type: models.NotificationTypeIssueCreated, 107 EntityType: "issue", 108 EntityId: string(issue.AtUri()), 109 RepoId: &repo.Id, 110 IssueId: &issue.Id, 111 } 112 113 err = n.db.CreateNotification(ctx, notification) 114 if err != nil { 115 log.Printf("NewIssue: failed to create notification: %v", err) 116 return 117 } 118} 119 120func (n *databaseNotifier) NewIssueComment(ctx context.Context, comment *models.IssueComment) { 121 issues, err := db.GetIssues(n.db, db.FilterEq("at_uri", comment.IssueAt)) 122 if err != nil { 123 log.Printf("NewIssueComment: failed to get issues: %v", err) 124 return 125 } 126 if len(issues) == 0 { 127 log.Printf("NewIssueComment: no issue found for %s", comment.IssueAt) 128 return 129 } 130 issue := issues[0] 131 132 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(issue.RepoAt))) 133 if err != nil { 134 log.Printf("NewIssueComment: failed to get repos: %v", err) 135 return 136 } 137 if len(repos) == 0 { 138 log.Printf("NewIssueComment: no repo found for %s", issue.RepoAt) 139 return 140 } 141 repo := repos[0] 142 143 recipients := make(map[string]bool) 144 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) 152 } 153 } 154 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) 162 } 163 } 164 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()), 173 RepoId: &repo.Id, 174 IssueId: &issue.Id, 175 } 176 177 err = n.db.CreateNotification(ctx, notification) 178 if err != nil { 179 log.Printf("NewIssueComment: failed to create notification for %s: %v", recipientDid, err) 180 } 181 } 182} 183 184func (n *databaseNotifier) NewFollow(ctx context.Context, follow *models.Follow) { 185 prefs, err := n.db.GetNotificationPreferences(ctx, follow.SubjectDid) 186 if err != nil { 187 log.Printf("NewFollow: failed to get notification preferences for %s: %v", follow.SubjectDid, err) 188 return 189 } 190 if !prefs.Followed { 191 return 192 } 193 194 notification := &models.Notification{ 195 RecipientDid: follow.SubjectDid, 196 ActorDid: follow.UserDid, 197 Type: models.NotificationTypeFollowed, 198 EntityType: "follow", 199 EntityId: follow.UserDid, 200 } 201 202 err = n.db.CreateNotification(ctx, notification) 203 if err != nil { 204 log.Printf("NewFollow: failed to create notification: %v", err) 205 return 206 } 207} 208 209func (n *databaseNotifier) DeleteFollow(ctx context.Context, follow *models.Follow) { 210 // no-op 211} 212 213func (n *databaseNotifier) NewPull(ctx context.Context, pull *models.Pull) { 214 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(pull.RepoAt))) 215 if err != nil { 216 log.Printf("NewPull: failed to get repos: %v", err) 217 return 218 } 219 if len(repos) == 0 { 220 log.Printf("NewPull: no repo found for %s", pull.RepoAt) 221 return 222 } 223 repo := repos[0] 224 225 if repo.Did == pull.OwnerDid { 226 return 227 } 228 229 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 230 if err != nil { 231 log.Printf("NewPull: failed to get notification preferences for %s: %v", repo.Did, err) 232 return 233 } 234 if !prefs.PullCreated { 235 return 236 } 237 238 notification := &models.Notification{ 239 RecipientDid: repo.Did, 240 ActorDid: pull.OwnerDid, 241 Type: models.NotificationTypePullCreated, 242 EntityType: "pull", 243 EntityId: string(pull.RepoAt), 244 RepoId: &repo.Id, 245 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 246 } 247 248 err = n.db.CreateNotification(ctx, notification) 249 if err != nil { 250 log.Printf("NewPull: failed to create notification: %v", err) 251 return 252 } 253} 254 255func (n *databaseNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) { 256 pulls, err := db.GetPulls(n.db, 257 db.FilterEq("repo_at", comment.RepoAt), 258 db.FilterEq("pull_id", comment.PullId)) 259 if err != nil { 260 log.Printf("NewPullComment: failed to get pulls: %v", err) 261 return 262 } 263 if len(pulls) == 0 { 264 log.Printf("NewPullComment: no pull found for %s PR %d", comment.RepoAt, comment.PullId) 265 return 266 } 267 pull := pulls[0] 268 269 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", comment.RepoAt)) 270 if err != nil { 271 log.Printf("NewPullComment: failed to get repos: %v", err) 272 return 273 } 274 if len(repos) == 0 { 275 log.Printf("NewPullComment: no repo found for %s", comment.RepoAt) 276 return 277 } 278 repo := repos[0] 279 280 recipients := make(map[string]bool) 281 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) 289 } 290 } 291 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) 299 } 300 } 301 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, 309 RepoId: &repo.Id, 310 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 311 } 312 313 err = n.db.CreateNotification(ctx, notification) 314 if err != nil { 315 log.Printf("NewPullComment: failed to create notification for %s: %v", recipientDid, err) 316 } 317 } 318} 319 320func (n *databaseNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) { 321 // no-op 322} 323 324func (n *databaseNotifier) DeleteString(ctx context.Context, did, rkey string) { 325 // no-op 326} 327 328func (n *databaseNotifier) EditString(ctx context.Context, string *models.String) { 329 // no-op 330} 331 332func (n *databaseNotifier) NewString(ctx context.Context, string *models.String) { 333 // no-op 334} 335 336func (n *databaseNotifier) NewIssueClosed(ctx context.Context, issue *models.Issue) { 337 // Get repo details 338 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(issue.RepoAt))) 339 if err != nil { 340 log.Printf("NewIssueClosed: failed to get repos: %v", err) 341 return 342 } 343 if len(repos) == 0 { 344 log.Printf("NewIssueClosed: no repo found for %s", issue.RepoAt) 345 return 346 } 347 repo := repos[0] 348 349 // Don't notify yourself 350 if repo.Did == issue.Did { 351 return 352 } 353 354 // Check if user wants these notifications 355 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 356 if err != nil { 357 log.Printf("NewIssueClosed: failed to get notification preferences for %s: %v", repo.Did, err) 358 return 359 } 360 if !prefs.IssueClosed { 361 return 362 } 363 364 notification := &models.Notification{ 365 RecipientDid: repo.Did, 366 ActorDid: issue.Did, 367 Type: models.NotificationTypeIssueClosed, 368 EntityType: "issue", 369 EntityId: string(issue.AtUri()), 370 RepoId: &repo.Id, 371 IssueId: &issue.Id, 372 } 373 374 err = n.db.CreateNotification(ctx, notification) 375 if err != nil { 376 log.Printf("NewIssueClosed: failed to create notification: %v", err) 377 return 378 } 379} 380 381func (n *databaseNotifier) NewPullMerged(ctx context.Context, pull *models.Pull) { 382 // Get repo details 383 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(pull.RepoAt))) 384 if err != nil { 385 log.Printf("NewPullMerged: failed to get repos: %v", err) 386 return 387 } 388 if len(repos) == 0 { 389 log.Printf("NewPullMerged: no repo found for %s", pull.RepoAt) 390 return 391 } 392 repo := repos[0] 393 394 // Don't notify yourself 395 if repo.Did == pull.OwnerDid { 396 return 397 } 398 399 // Check if user wants these notifications 400 prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid) 401 if err != nil { 402 log.Printf("NewPullMerged: failed to get notification preferences for %s: %v", pull.OwnerDid, err) 403 return 404 } 405 if !prefs.PullMerged { 406 return 407 } 408 409 notification := &models.Notification{ 410 RecipientDid: pull.OwnerDid, 411 ActorDid: repo.Did, 412 Type: models.NotificationTypePullMerged, 413 EntityType: "pull", 414 EntityId: string(pull.RepoAt), 415 RepoId: &repo.Id, 416 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 417 } 418 419 err = n.db.CreateNotification(ctx, notification) 420 if err != nil { 421 log.Printf("NewPullMerged: failed to create notification: %v", err) 422 return 423 } 424} 425 426func (n *databaseNotifier) NewPullClosed(ctx context.Context, pull *models.Pull) { 427 // Get repo details 428 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(pull.RepoAt))) 429 if err != nil { 430 log.Printf("NewPullClosed: failed to get repos: %v", err) 431 return 432 } 433 if len(repos) == 0 { 434 log.Printf("NewPullClosed: no repo found for %s", pull.RepoAt) 435 return 436 } 437 repo := repos[0] 438 439 // Don't notify yourself 440 if repo.Did == pull.OwnerDid { 441 return 442 } 443 444 // Check if user wants these notifications - reuse pull_merged preference for now 445 prefs, err := n.db.GetNotificationPreferences(ctx, pull.OwnerDid) 446 if err != nil { 447 log.Printf("NewPullClosed: failed to get notification preferences for %s: %v", pull.OwnerDid, err) 448 return 449 } 450 if !prefs.PullMerged { 451 return 452 } 453 454 notification := &models.Notification{ 455 RecipientDid: pull.OwnerDid, 456 ActorDid: repo.Did, 457 Type: models.NotificationTypePullClosed, 458 EntityType: "pull", 459 EntityId: string(pull.RepoAt), 460 RepoId: &repo.Id, 461 PullId: func() *int64 { id := int64(pull.ID); return &id }(), 462 } 463 464 err = n.db.CreateNotification(ctx, notification) 465 if err != nil { 466 log.Printf("NewPullClosed: failed to create notification: %v", err) 467 return 468 } 469}