-
Notifications
You must be signed in to change notification settings - Fork 0
/
notifications.go
128 lines (110 loc) · 3.84 KB
/
notifications.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package fs
import (
"context"
"fmt"
"strings"
"time"
"github.com/shurcooL/issues"
"github.com/shurcooL/notifications"
"github.com/shurcooL/users"
)
// threadType is the notifications thread type for this service.
const threadType = "issues"
// ThreadType returns the notifications thread type for this service.
func (service) ThreadType(issues.RepoSpec) string { return threadType }
// subscribe subscribes user and anyone mentioned in body to the issue.
func (s service) subscribe(ctx context.Context, repo issues.RepoSpec, issueID uint64, user users.UserSpec, body string) error {
if s.notifications == nil {
return nil
}
subscribers := []users.UserSpec{user}
// TODO: Find mentioned users in body.
/*mentions, err := mentions(ctx, body)
if err != nil {
return err
}
subscribers = append(subscribers, mentions...)*/
return s.notifications.Subscribe(ctx, notifications.RepoSpec(repo), threadType, issueID, subscribers)
}
// markRead marks the specified issue as read for current user.
func (s service) markRead(ctx context.Context, repo issues.RepoSpec, issueID uint64) error {
if s.notifications == nil {
return nil
}
return s.notifications.MarkRead(ctx, notifications.RepoSpec(repo), threadType, issueID)
}
// notify notifies all subscribed users of an update that shows up in their Notification Center.
func (s service) notify(ctx context.Context, repo issues.RepoSpec, issueID uint64, fragment string, actor users.UserSpec, time time.Time) error {
if s.notifications == nil {
return nil
}
// TODO, THINK: Is this the best place/time?
// Get issue from storage for to populate notification fields.
var issue issue
err := jsonDecodeFile(ctx, s.fs, issueCommentPath(repo, issueID, 0), &issue)
if err != nil {
return err
}
nr := notifications.NotificationRequest{
Title: issue.Title,
Icon: notificationIcon(issue.State),
Color: notificationColor(issue.State),
Actor: actor,
UpdatedAt: time,
HTMLURL: htmlURL(repo.URI, issueID, fragment),
}
return s.notifications.Notify(ctx, notifications.RepoSpec(repo), threadType, issueID, nr)
}
// TODO, THINK: Where should the logic to come up with the URL live?
// It's kinda related to the router/URL scheme of issuesapp...
func htmlURL(repoURI string, issueID uint64, fragment string) string {
var htmlURL string
// TODO: Find a good way to factor out this logic and provide it to issues/fs in a reasonable way.
switch {
default:
htmlURL = fmt.Sprintf("https://%s/issues/%v", repoURI, issueID)
case repoURI == "dmitri.shuralyov.com/blog":
htmlURL = fmt.Sprintf("https://dmitri.shuralyov.com/blog/%v", issueID)
case repoURI == "dmitri.shuralyov.com/idiomatic-go":
htmlURL = fmt.Sprintf("https://dmitri.shuralyov.com/idiomatic-go/entries/%v", issueID)
case strings.HasPrefix(repoURI, "github.com/shurcooL/"):
htmlURL = fmt.Sprintf("https://dmitri.shuralyov.com/issues/%s/%v", repoURI, issueID)
}
if fragment != "" {
htmlURL += "#" + fragment
}
return htmlURL
}
// TODO: This is display/presentation logic; try to factor it out of the backend service implementation.
// (Have it be provided to the service, maybe? Or another way.)
func notificationIcon(state issues.State) notifications.OcticonID {
switch state {
case issues.OpenState:
return "issue-opened"
case issues.ClosedState:
return "issue-closed"
default:
return ""
}
}
/* TODO
func (e event) Octicon() string {
switch e.Event.Type {
case issues.Reopened:
return "octicon-primitive-dot"
case issues.Closed:
return "octicon-circle-slash"
default:
return "octicon-primitive-dot"
}
}*/
func notificationColor(state issues.State) notifications.RGB {
switch state {
case issues.OpenState: // Open.
return notifications.RGB{R: 0x6c, G: 0xc6, B: 0x44}
case issues.ClosedState: // Closed.
return notifications.RGB{R: 0xbd, G: 0x2c, B: 0x00}
default:
return notifications.RGB{}
}
}