This repository has no description
1package models
2
3import (
4 "context"
5 "fmt"
6 "time"
7
8 "github.com/bluesky-social/indigo/atproto/syntax"
9 "tangled.org/core/idresolver"
10)
11
12type NotificationType string
13
14const (
15 NotificationTypeRepoStarred NotificationType = "repo_starred"
16 NotificationTypeIssueCreated NotificationType = "issue_created"
17 NotificationTypeIssueCommented NotificationType = "issue_commented"
18 NotificationTypePullCreated NotificationType = "pull_created"
19 NotificationTypePullCommented NotificationType = "pull_commented"
20 NotificationTypeFollowed NotificationType = "followed"
21 NotificationTypePullMerged NotificationType = "pull_merged"
22 NotificationTypeIssueClosed NotificationType = "issue_closed"
23 NotificationTypeIssueReopen NotificationType = "issue_reopen"
24 NotificationTypePullClosed NotificationType = "pull_closed"
25 NotificationTypePullReopen NotificationType = "pull_reopen"
26 NotificationTypeUserMentioned NotificationType = "user_mentioned"
27 NotificationTypeIssueAssigned NotificationType = "issue_assigned"
28 NotificationTypeIssueUnassigned NotificationType = "issue_unassigned"
29 NotificationTypePullAssigned NotificationType = "pull_assigned"
30 NotificationTypePullUnassigned NotificationType = "pull_unassigned"
31)
32
33var SocialNotificationTypes = []NotificationType{
34 NotificationTypeRepoStarred,
35 NotificationTypeFollowed,
36}
37
38var WorkNotificationTypes = []NotificationType{
39 NotificationTypeIssueCreated,
40 NotificationTypeIssueCommented,
41 NotificationTypeIssueClosed,
42 NotificationTypeIssueReopen,
43 NotificationTypePullCreated,
44 NotificationTypePullCommented,
45 NotificationTypePullMerged,
46 NotificationTypePullClosed,
47 NotificationTypePullReopen,
48 NotificationTypeUserMentioned,
49 NotificationTypeIssueAssigned,
50 NotificationTypeIssueUnassigned,
51 NotificationTypePullAssigned,
52 NotificationTypePullUnassigned,
53}
54
55type Notification struct {
56 ID int64
57 RecipientDid string
58 ActorDid string
59 Type NotificationType
60 EntityType string
61 EntityId string
62 Read bool
63 Emailed bool
64 Created time.Time
65
66 // foreign key references
67 RepoId *int64
68 IssueId *int64
69 PullId *int64
70}
71
72// EmailNotificationTypes are the notification types that are included in email digests.
73// Social types (repo_starred, followed) are intentionally excluded.
74var EmailNotificationTypes = []NotificationType{
75 NotificationTypeIssueCreated,
76 NotificationTypeIssueCommented,
77 NotificationTypeIssueClosed,
78 NotificationTypeIssueReopen,
79 NotificationTypePullCreated,
80 NotificationTypePullCommented,
81 NotificationTypePullMerged,
82 NotificationTypePullClosed,
83 NotificationTypePullReopen,
84 NotificationTypeUserMentioned,
85 NotificationTypeIssueAssigned,
86 NotificationTypeIssueUnassigned,
87 NotificationTypePullAssigned,
88 NotificationTypePullUnassigned,
89}
90
91// lucide icon that represents this notification
92func (n *Notification) Icon() string {
93 switch n.Type {
94 case NotificationTypeRepoStarred:
95 return "star"
96 case NotificationTypeIssueCreated:
97 return "circle-dot"
98 case NotificationTypeIssueCommented:
99 return "message-square"
100 case NotificationTypeIssueClosed:
101 return "ban"
102 case NotificationTypeIssueReopen:
103 return "circle-dot"
104 case NotificationTypePullCreated:
105 return "git-pull-request-create"
106 case NotificationTypePullCommented:
107 return "message-square"
108 case NotificationTypePullMerged:
109 return "git-merge"
110 case NotificationTypePullClosed:
111 return "git-pull-request-closed"
112 case NotificationTypePullReopen:
113 return "git-pull-request-create"
114 case NotificationTypeFollowed:
115 return "user-plus"
116 case NotificationTypeUserMentioned:
117 return "at-sign"
118 case NotificationTypeIssueAssigned, NotificationTypePullAssigned:
119 return "user-round-arrow-forward"
120 case NotificationTypeIssueUnassigned, NotificationTypePullUnassigned:
121 return "user-round-minus"
122 default:
123 return ""
124 }
125}
126
127type NotificationWithEntity struct {
128 *Notification
129 Repo *Repo
130 Issue *Issue
131 Pull *Pull
132}
133
134// URL returns the navigable path for the notification, resolving DIDs to
135// handles via the provided resolver.
136func (n *NotificationWithEntity) URL(res *idresolver.Resolver) string {
137 resolve := func(did string) string {
138 if id, err := res.ResolveIdent(context.Background(), did); err == nil && !id.Handle.IsInvalidHandle() {
139 return id.Handle.String()
140 }
141 return did
142 }
143
144 switch n.Type {
145 case NotificationTypeFollowed:
146 return "/" + resolve(n.ActorDid)
147 }
148 if n.Repo == nil {
149 return ""
150 }
151 repoHandle := resolve(n.Repo.Did)
152 slug := n.Repo.Slug()
153 switch {
154 case n.Issue != nil:
155 return fmt.Sprintf("/%s/%s/issues/%d", repoHandle, slug, n.Issue.IssueId)
156 case n.Pull != nil:
157 return fmt.Sprintf("/%s/%s/pulls/%d", repoHandle, slug, n.Pull.PullId)
158 default:
159 // repo_starred and other repo-level types
160 return fmt.Sprintf("/%s/%s", repoHandle, slug)
161 }
162}
163
164type NotificationPreferences struct {
165 ID int64
166 UserDid syntax.DID
167 RepoStarred bool
168 IssueCreated bool
169 IssueCommented bool
170 PullCreated bool
171 PullCommented bool
172 Followed bool
173 UserMentioned bool
174 PullMerged bool
175 IssueClosed bool
176 EmailNotifications bool
177}
178
179func (prefs *NotificationPreferences) ShouldNotify(t NotificationType) bool {
180 switch t {
181 case NotificationTypeRepoStarred:
182 return prefs.RepoStarred
183 case NotificationTypeIssueCreated:
184 return prefs.IssueCreated
185 case NotificationTypeIssueCommented:
186 return prefs.IssueCommented
187 case NotificationTypeIssueClosed:
188 return prefs.IssueClosed
189 case NotificationTypeIssueReopen:
190 return prefs.IssueCreated // same pref for now
191 case NotificationTypePullCreated:
192 return prefs.PullCreated
193 case NotificationTypePullCommented:
194 return prefs.PullCommented
195 case NotificationTypePullMerged:
196 return prefs.PullMerged
197 case NotificationTypePullClosed:
198 return prefs.PullMerged // same pref for now
199 case NotificationTypePullReopen:
200 return prefs.PullCreated // same pref for now
201 case NotificationTypeFollowed:
202 return prefs.Followed
203 case NotificationTypeUserMentioned,
204 NotificationTypeIssueAssigned,
205 NotificationTypeIssueUnassigned,
206 NotificationTypePullAssigned,
207 NotificationTypePullUnassigned:
208 return prefs.UserMentioned
209 default:
210 return false
211 }
212}
213
214func DefaultNotificationPreferences(user syntax.DID) *NotificationPreferences {
215 return &NotificationPreferences{
216 UserDid: user,
217 RepoStarred: true,
218 IssueCreated: true,
219 IssueCommented: true,
220 PullCreated: true,
221 PullCommented: true,
222 Followed: true,
223 UserMentioned: true,
224 PullMerged: true,
225 IssueClosed: true,
226 EmailNotifications: false,
227 }
228}