Permalink
Browse files

Add digest cron handler.

  • Loading branch information...
mihaip committed Jul 31, 2014
1 parent 1bc9d53 commit 649bbd8fd953994052d1e3e132629aa29c49fa80
Showing with 67 additions and 26 deletions.
  1. +1 −1 TODO
  2. +16 −0 app/account.go
  3. +3 −0 app/app.yaml
  4. +1 −1 app/digest.go
  5. +46 −24 app/githop.go
View
2 TODO
@@ -1,7 +1,7 @@
TODO
- Break up indexHandler
- Flash message when sending a single email
-- Loop over registered accounts and send them email
+- Use task queue for sending out of digests, for better parallelism and retry behavior
- Flash message and sign out when OAuth token has expired/is invalid
- Handle pagination for user repository list
- Handle pagination for user organization list
View
@@ -30,6 +30,22 @@ func getAccount(c appengine.Context, gitHubUserId int) (*Account, error) {
return account, err
}
+func getAllAccounts(c appengine.Context, accounts *[]Account) error {
+ q := datastore.NewQuery("Account")
+ _, err := q.GetAll(c, accounts)
+ if err != nil {
+ return err
+ }
+ for i, _ := range *accounts {
+ r := bytes.NewBuffer((*accounts)[i].OAuthTokenSerialized)
+ err = gob.NewDecoder(r).Decode(&(*accounts)[i].OAuthToken)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
func (account *Account) put(c appengine.Context) error {
w := new(bytes.Buffer)
err := gob.NewEncoder(w).Encode(&account.OAuthToken)
View
@@ -6,6 +6,9 @@ api_version: go1
handlers:
- url: /static
static_dir: static
+- url: /digest/cron
+ script: _go_app
+ login: admin
- url: /.*
script: _go_app
secure: always
View
@@ -56,7 +56,7 @@ func newDigest(githubClient *github.Client) (*Digest, error) {
now := time.Now()
digestStartTime := time.Date(now.Year()-1, now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
- digestEndTime := digestStartTime.AddDate(0, 0, 7)
+ digestEndTime := digestStartTime.AddDate(0, 0, 1)
// Only look at repos that may have activity in the digest interval.
var digestRepos []github.Repository
View
@@ -3,6 +3,8 @@ package githop
import (
"bytes"
"encoding/json"
+ "errors"
+ "fmt"
"html/template"
"io/ioutil"
"log"
@@ -49,6 +51,7 @@ func init() {
router = mux.NewRouter()
router.HandleFunc("/", indexHandler).Name("index")
router.HandleFunc("/digest/send", sendDigestHandler).Name("send-digest").Methods("POST")
+ router.HandleFunc("/digest/cron", digestCronHandler)
router.HandleFunc("/session/sign-in", signInHandler).Name("sign-in")
router.HandleFunc("/session/sign-out", signOutHandler).Name("sign-out")
router.HandleFunc("/github/callback", githubOAuthCallbackHandler)
@@ -82,7 +85,8 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
}
return
}
- account, err := getAccount(appengine.NewContext(r), userId)
+ c := appengine.NewContext(r)
+ account, err := getAccount(c, userId)
if account == nil {
// Can't look up the account, session cookie must be invalid, clear it.
indexUrl, _ := router.Get("sign-out").URL()
@@ -94,7 +98,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
return
}
- oauthTransport := githubOAuthTransport(r)
+ oauthTransport := githubOAuthTransport(c)
oauthTransport.Token = &account.OAuthToken
githubClient := github.NewClient(oauthTransport.Client())
@@ -124,26 +128,50 @@ func sendDigestHandler(w http.ResponseWriter, r *http.Request) {
return
}
- oauthTransport := githubOAuthTransport(r)
+ err = sendDigestForAccount(account, c)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ indexUrl, _ := router.Get("index").URL()
+ http.Redirect(w, r, indexUrl.String(), http.StatusFound)
+}
+
+func digestCronHandler(w http.ResponseWriter, r *http.Request) {
+ var accounts []Account
+ c := appengine.NewContext(r)
+ getAllAccounts(c, &accounts)
+ for _, account := range accounts {
+ c.Infof("Sending digest for %d...", account.GitHubUserId)
+ err := sendDigestForAccount(&account, c)
+ if err != nil {
+ c.Errorf(" Error: %s", err.Error())
+ } else {
+ c.Infof(" Sent!")
+ }
+ }
+ fmt.Fprint(w, "Done")
+}
+
+func sendDigestForAccount(account *Account, c appengine.Context) error {
+ oauthTransport := githubOAuthTransport(c)
oauthTransport.Token = &account.OAuthToken
githubClient := github.NewClient(oauthTransport.Client())
digest, err := newDigest(githubClient)
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
+ return err
}
var digestHtml bytes.Buffer
if err := templates.ExecuteTemplate(&digestHtml, "digest", digest); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
+ return err
}
emails, _, err := githubClient.Users.ListEmails(nil)
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
+ return err
}
var primaryVerified *string
for _, email := range emails {
@@ -154,8 +182,7 @@ func sendDigestHandler(w http.ResponseWriter, r *http.Request) {
}
}
if primaryVerified == nil {
- http.Error(w, "No verified email addresses found in GitHub account", http.StatusBadRequest)
- return
+ return errors.New("No verified email addresses found in GitHub account")
}
digestMessage := &mail.Message{
@@ -164,18 +191,14 @@ func sendDigestHandler(w http.ResponseWriter, r *http.Request) {
Subject: "GitHop Digest",
HTMLBody: digestHtml.String(),
}
- if err := mail.Send(c, digestMessage); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
-
- indexUrl, _ := router.Get("index").URL()
- http.Redirect(w, r, indexUrl.String(), http.StatusFound)
+ err = mail.Send(c, digestMessage)
+ return err
}
func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) {
code := r.FormValue("code")
- oauthTransport := githubOAuthTransport(r)
+ c := appengine.NewContext(r)
+ oauthTransport := githubOAuthTransport(c)
token, err := oauthTransport.Exchange(code)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -194,7 +217,7 @@ func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) {
GitHubUserId: *user.ID,
OAuthToken: *token,
}
- err = account.put(appengine.NewContext(r))
+ err = account.put(c)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -207,12 +230,11 @@ func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, indexUrl.String(), http.StatusFound)
}
-func githubOAuthTransport(r *http.Request) *oauth.Transport {
- appengineContext := appengine.NewContext(r)
- appengineTransport := &urlfetch.Transport{Context: appengineContext}
+func githubOAuthTransport(c appengine.Context) *oauth.Transport {
+ appengineTransport := &urlfetch.Transport{Context: c}
cachingTransport := &CachingTransport{
Transport: appengineTransport,
- Context: appengineContext,
+ Context: c,
}
return &oauth.Transport{
Config: &githubOauthConfig,

0 comments on commit 649bbd8

Please sign in to comment.