Merge lp:~sergiusens/account-polld/timestamp into lp:~ubuntu-push-hackers/account-polld/trunk

Proposed by Sergio Schvezov
Status: Merged
Approved by: Sergio Schvezov
Approved revision: 54
Merged at revision: 37
Proposed branch: lp:~sergiusens/account-polld/timestamp
Merge into: lp:~ubuntu-push-hackers/account-polld/trunk
Prerequisite: lp:~sergiusens/account-polld/token_less
Diff against target: 225 lines (+60/-16)
5 files modified
plugins/facebook/facebook.go (+12/-1)
plugins/gmail/api.go (+17/-1)
plugins/gmail/gmail.go (+3/-2)
plugins/plugins.go (+12/-8)
plugins/twitter/twitter.go (+16/-4)
To merge this branch: bzr merge lp:~sergiusens/account-polld/timestamp
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+229286@code.launchpad.net

Commit message

Use the timestamp entry for cards.

To post a comment you must log in.
54. By Sergio Schvezov

Fix misshap on epoch vs 0

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Roberto Alsina (ralsina) wrote :

Hey, looks like I need to add the timestamp to the docs. On monday.

review: Approve
55. By Sergio Schvezov

Merged token_less into timestamp.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/facebook/facebook.go'
2--- plugins/facebook/facebook.go 2014-07-29 11:45:57 +0000
3+++ plugins/facebook/facebook.go 2014-08-01 22:35:09 +0000
4@@ -21,11 +21,14 @@
5 "encoding/json"
6 "net/http"
7 "net/url"
8+ "time"
9
10 "launchpad.net/account-polld/accounts"
11 "launchpad.net/account-polld/plugins"
12 )
13
14+const facebookTime = "2006-01-02T15:04:05-0700"
15+
16 var baseUrl, _ = url.Parse("https://graph.facebook.com/v2.0/")
17
18 type fbPlugin struct {
19@@ -84,7 +87,8 @@
20 }
21 // TODO proper action needed
22 action := "https://m.facebook.com"
23- pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(n.Title, "", action, ""))
24+ epoch := toEpoch(n.UpdatedTime)
25+ pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(n.Title, "", action, "", epoch))
26 if n.UpdatedTime > latestUpdate {
27 latestUpdate = n.UpdatedTime
28 }
29@@ -101,6 +105,13 @@
30 return p.parseResponse(resp)
31 }
32
33+func toEpoch(timestamp string) int64 {
34+ if t, err := time.Parse(facebookTime, timestamp); err == nil {
35+ return t.Unix()
36+ }
37+ return time.Now().Unix()
38+}
39+
40 // The notifications response format is described here:
41 // https://developers.facebook.com/docs/graph-api/reference/v2.0/user/notifications/
42 type notificationDoc struct {
43
44=== modified file 'plugins/gmail/api.go'
45--- plugins/gmail/api.go 2014-07-22 17:28:17 +0000
46+++ plugins/gmail/api.go 2014-08-01 22:35:09 +0000
47@@ -19,11 +19,15 @@
48
49 import (
50 "fmt"
51+ "time"
52
53 "launchpad.net/account-polld/plugins"
54 )
55
56+const gmailTime = "Mon, 2 Jan 2006 15:04:05 -0700"
57+
58 type pushes map[string]plugins.PushMessage
59+type headers map[string]string
60
61 // messageList holds a response to call to Users.messages: list
62 // defined in https://developers.google.com/gmail/api/v1/reference/users/messages/list
63@@ -71,7 +75,7 @@
64 Headers []messageHeader `json:"headers"`
65 }
66
67-func (p *payload) mapHeaders() map[string]string {
68+func (p *payload) mapHeaders() headers {
69 headers := make(map[string]string)
70 for _, hdr := range p.Headers {
71 headers[hdr.Name] = hdr.Value
72@@ -79,6 +83,18 @@
73 return headers
74 }
75
76+func (hdr headers) getEpoch() int64 {
77+ timestamp, ok := hdr[hdrDATE]
78+ if !ok {
79+ return time.Now().Unix()
80+ }
81+
82+ if t, err := time.Parse(gmailTime, timestamp); err == nil {
83+ return t.Unix()
84+ }
85+ return time.Now().Unix()
86+}
87+
88 // messageHeader represents the message headers.
89 type messageHeader struct {
90 Name string `json:"name"`
91
92=== modified file 'plugins/gmail/gmail.go'
93--- plugins/gmail/gmail.go 2014-08-01 22:35:09 +0000
94+++ plugins/gmail/gmail.go 2014-08-01 22:35:09 +0000
95@@ -32,7 +32,7 @@
96 )
97
98 const (
99- APP_ID = "com.ubuntu.developer.webapps.webapp-gmail_webapp-gmail"
100+ APP_ID = "com.ubuntu.developer.webapps.webapp-gmail_webapp-gmail"
101 gmailDispatchUrl = "https://mail.google.com/mail/mu/mp/#cv/priority/^smartlabel_%s/%s"
102 )
103
104@@ -111,7 +111,8 @@
105 body := fmt.Sprintf(gettext.Gettext("%s\n%s"), hdr[hdrSUBJECT], msg.Snippet)
106 // fmt with label personal and threadId
107 action := fmt.Sprintf(gmailDispatchUrl, "personal", msg.ThreadId)
108- pushMsgMap[msg.ThreadId] = *plugins.NewStandardPushMessage(summary, body, action, "")
109+ epoch := hdr.getEpoch()
110+ pushMsgMap[msg.ThreadId] = *plugins.NewStandardPushMessage(summary, body, action, "", epoch)
111 }
112 }
113 var pushMsg []plugins.PushMessage
114
115=== modified file 'plugins/plugins.go'
116--- plugins/plugins.go 2014-08-01 22:35:09 +0000
117+++ plugins/plugins.go 2014-08-01 22:35:09 +0000
118@@ -50,22 +50,24 @@
119
120 // NewStandardPushMessage creates a base Notification with common
121 // components (members) setup.
122-func NewStandardPushMessage(summary, body, action, icon string) *PushMessage {
123- return &PushMessage{
124+func NewStandardPushMessage(summary, body, action, icon string, epoch int64) *PushMessage {
125+ pm := &PushMessage{
126 Notification: Notification{
127 Card: &Card{
128- Summary: summary,
129- Body: body,
130- Actions: []string{action},
131- Icon: icon,
132- Popup: true,
133- Persist: true,
134+ Summary: summary,
135+ Body: body,
136+ Actions: []string{action},
137+ Icon: icon,
138+ Timestamp: epoch,
139+ Popup: true,
140+ Persist: true,
141 },
142 Sound: DefaultSound(),
143 Vibrate: DefaultVibration(),
144 Tag: cmdName,
145 },
146 }
147+ return pm
148 }
149
150 // PushMessage represents a data structure to be sent over to the
151@@ -112,6 +114,8 @@
152 Icon string `json:"icon,omitempty"`
153 // Whether to show in notification centre.
154 Persist bool `json:"persist,omitempty"`
155+ // Seconds since the unix epoch, useful for persistent cards.
156+ Timestamp int64 `json:"Timestamp,omitempty"`
157 }
158
159 // Vibrate is part of a notification and represents the user haptic hints
160
161=== modified file 'plugins/twitter/twitter.go'
162--- plugins/twitter/twitter.go 2014-08-01 22:35:09 +0000
163+++ plugins/twitter/twitter.go 2014-08-01 22:35:09 +0000
164@@ -24,6 +24,7 @@
165 "net/url"
166 "sort"
167 "strings"
168+ "time"
169
170 "launchpad.net/account-polld/accounts"
171 "launchpad.net/account-polld/gettext"
172@@ -109,7 +110,8 @@
173 // TRANSLATORS: The first %s refers to the twitter user's Name, the second %s to the username.
174 summary := fmt.Sprintf(gettext.Gettext("%s. @%s"), s.User.Name, s.User.ScreenName)
175 action := fmt.Sprintf("http://mobile.twitter.com/%s/statuses/%d", s.User.ScreenName, s.Id)
176- pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, s.Text, action, s.User.Image))
177+ epoch := toEpoch(s.CreatedAt)
178+ pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, s.Text, action, s.User.Image, epoch))
179 if len(pushMsg) == maxIndividualStatuses {
180 break
181 }
182@@ -125,7 +127,8 @@
183 // TRANSLATORS: This represents a notification body with the comma separated twitter usernames
184 body := fmt.Sprintf(gettext.Gettext("From %s"), strings.Join(screennames, ", "))
185 action := "http://mobile.twitter.com/i/connect"
186- pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, body, action, ""))
187+ epoch := time.Now().Unix()
188+ pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, body, action, "", epoch))
189 }
190 return pushMsg, nil
191 }
192@@ -164,7 +167,8 @@
193 // TRANSLATORS: The first %s refers to the twitter user's Name, the second %s to the username.
194 summary := fmt.Sprintf(gettext.Gettext("%s. @%s"), m.Sender.Name, m.Sender.ScreenName)
195 action := fmt.Sprintf("http://mobile.twitter.com/%s/messages", m.Sender.ScreenName)
196- pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, m.Text, action, m.Sender.Image))
197+ epoch := toEpoch(m.CreatedAt)
198+ pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, m.Text, action, m.Sender.Image, epoch))
199 if len(pushMsg) == maxIndividualDirectMessages {
200 break
201 }
202@@ -180,7 +184,8 @@
203 // TRANSLATORS: This represents a notification body with the comma separated twitter usernames
204 body := fmt.Sprintf(gettext.Gettext("From %s"), strings.Join(senders, ", "))
205 action := "http://mobile.twitter.com/messages"
206- pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, body, action, ""))
207+ epoch := time.Now().Unix()
208+ pushMsg = append(pushMsg, *plugins.NewStandardPushMessage(summary, body, action, "", epoch))
209 }
210 return pushMsg, nil
211 }
212@@ -215,6 +220,13 @@
213 return
214 }
215
216+func toEpoch(timestamp string) int64 {
217+ if t, err := time.Parse(time.RubyDate, timestamp); err == nil {
218+ return t.Unix()
219+ }
220+ return time.Now().Unix()
221+}
222+
223 // Status format is described here:
224 // https://dev.twitter.com/docs/api/1.1/get/statuses/mentions_timeline
225 type status struct {

Subscribers

People subscribed via source and target branches