this repo has no description
1package db 2 3import ( 4 "context" 5 "log" 6 7 "tangled.sh/tangled.sh/core/appview/db" 8 "tangled.sh/tangled.sh/core/appview/notify" 9 "tangled.sh/tangled.sh/core/idresolver" 10) 11 12type databaseNotifier struct { 13 db *db.DB 14 res *idresolver.Resolver 15} 16 17func NewDatabaseNotifier(database *db.DB, resolver *idresolver.Resolver) notify.Notifier { 18 return &databaseNotifier{ 19 db: database, 20 res: resolver, 21 } 22} 23 24var _ notify.Notifier = &databaseNotifier{} 25 26func (n *databaseNotifier) NewRepo(ctx context.Context, repo *db.Repo) { 27 // no-op for now 28} 29 30func (n *databaseNotifier) NewStar(ctx context.Context, star *db.Star) { 31 var err error 32 repos, err := db.GetRepos(n.db, 1, db.FilterEq("at_uri", string(star.RepoAt))) 33 if err != nil { 34 log.Printf("NewStar: failed to get repos: %v", err) 35 return 36 } 37 if len(repos) == 0 { 38 log.Printf("NewStar: no repo found for %s", star.RepoAt) 39 return 40 } 41 repo := repos[0] 42 43 // don't notify yourself 44 if repo.Did == star.StarredByDid { 45 return 46 } 47 48 // check if user wants these notifications 49 prefs, err := n.db.GetNotificationPreferences(ctx, repo.Did) 50 if err != nil { 51 log.Printf("NewStar: failed to get notification preferences for %s: %v", repo.Did, err) 52 return 53 } 54 if !prefs.RepoStarred { 55 return 56 } 57 58 notification := &models.Notification{ 59 RecipientDid: repo.Did, 60 ActorDid: star.StarredByDid, 61 Type: models.NotificationTypeRepoStarred, 62 EntityType: "repo", 63 EntityId: string(star.RepoAt), 64 RepoId: &repo.ID, 65 } 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 *db.Star) { 75 // no-op 76} 77 78func (n *databaseNotifier) NewIssue(ctx context.Context, issue *db.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 *db.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 *db.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 *db.Follow) { 210 // no-op 211} 212 213func (n *databaseNotifier) NewPull(ctx context.Context, pull *db.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 *db.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 *db.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 *db.String) { 329 // no-op 330} 331 332func (n *databaseNotifier) NewString(ctx context.Context, string *db.String) { 333 // no-op 334} 335 336func (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))) 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 *db.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 *db.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}