Add setting for which email address the digest will be sent to.

This commit is contained in:
Mihai Parparita 2014-09-01 22:17:09 -07:00
parent 1cb55cfe6a
commit 69fcc91dc7
4 changed files with 90 additions and 25 deletions

View file

@ -3,12 +3,14 @@ package githop
import ( import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"errors"
"time" "time"
"appengine" "appengine"
"appengine/datastore" "appengine/datastore"
"code.google.com/p/goauth2/oauth" "code.google.com/p/goauth2/oauth"
"github.com/google/go-github/github"
) )
type Account struct { type Account struct {
@ -20,6 +22,7 @@ type Account struct {
TimezoneName string `datastore:",noindex"` TimezoneName string `datastore:",noindex"`
TimezoneLocation *time.Location `datastore:"-,"` TimezoneLocation *time.Location `datastore:"-,"`
ExcludedRepoIds []int `datastore:",noindex"` ExcludedRepoIds []int `datastore:",noindex"`
DigestEmailAddress string
} }
func getAccount(c appengine.Context, githubUserId int) (*Account, error) { func getAccount(c appengine.Context, githubUserId int) (*Account, error) {
@ -76,7 +79,7 @@ func (account *Account) IsRepoIdExcluded(repoId int) bool {
return false return false
} }
func (account *Account) put(c appengine.Context) error { func (account *Account) Put(c appengine.Context) error {
w := new(bytes.Buffer) w := new(bytes.Buffer)
err := gob.NewEncoder(w).Encode(&account.OAuthToken) err := gob.NewEncoder(w).Encode(&account.OAuthToken)
if err != nil { if err != nil {
@ -87,3 +90,31 @@ func (account *Account) put(c appengine.Context) error {
_, err = datastore.Put(c, key, account) _, err = datastore.Put(c, key, account)
return err return err
} }
func (account *Account) GetDigestEmailAddress(githubClient *github.Client) (string, error) {
if len(account.DigestEmailAddress) > 0 {
return account.DigestEmailAddress, nil
}
emails, _, err := githubClient.Users.ListEmails(nil)
if err != nil {
return "", err
}
// Prefer the primary, verified email
for _, email := range emails {
if email.Primary != nil && *email.Primary &&
email.Verified != nil && *email.Verified {
return *email.Email, nil
}
}
// Then the first verified email
for _, email := range emails {
if email.Verified != nil && *email.Verified {
return *email.Email, nil
}
}
// Then just the first email
for _, email := range emails {
return *email.Email, nil
}
return "", errors.New("No email addresses found in GitHub account")
}

View file

@ -3,7 +3,6 @@ package githop
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"html/template" "html/template"
"io/ioutil" "io/ioutil"
@ -293,25 +292,14 @@ func sendDigestForAccount(account *Account, c appengine.Context) (bool, error) {
return false, err return false, err
} }
emails, _, err := githubClient.Users.ListEmails(nil) emailAddress, err := account.GetDigestEmailAddress(githubClient)
if err != nil { if err != nil {
return false, err return false, err
} }
var primaryVerified *string
for _, email := range emails {
if email.Primary != nil && *email.Primary &&
email.Verified != nil && *email.Verified {
primaryVerified = email.Email
break
}
}
if primaryVerified == nil {
return false, errors.New("No verified email addresses found in GitHub account")
}
digestMessage := &mail.Message{ digestMessage := &mail.Message{
Sender: "GitHop <mihai.parparita@gmail.com>", Sender: "GitHop <mihai.parparita@gmail.com>",
To: []string{*primaryVerified}, To: []string{emailAddress},
Subject: "GitHop Digest", Subject: "GitHop Digest",
HTMLBody: digestHtml.String(), HTMLBody: digestHtml.String(),
} }
@ -341,7 +329,7 @@ func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) {
GitHubUserId: *user.ID, GitHubUserId: *user.ID,
OAuthToken: *token, OAuthToken: *token,
} }
err = account.put(c) err = account.Put(c)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -380,11 +368,28 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
emails, _, err := githubClient.Users.ListEmails(nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
emailAddresses := make([]string, len(emails))
for i := range emails {
emailAddresses[i] = *emails[i].Email
}
accountEmailAddress, err := account.GetDigestEmailAddress(githubClient)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
var data = map[string]interface{}{ var data = map[string]interface{}{
"Account": account, "Account": account,
"User": user, "User": user,
"Timezones": timezones, "Timezones": timezones,
"Repos": repos, "Repos": repos,
"EmailAddresses": emailAddresses,
"AccountEmailAddress": accountEmailAddress,
} }
if err := templates["settings"].Execute(w, data); err != nil { if err := templates["settings"].Execute(w, data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
@ -433,7 +438,9 @@ func saveSettingsHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
err = account.put(c) account.DigestEmailAddress = r.FormValue("email_address")
err = account.Put(c)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return

View file

@ -12,6 +12,15 @@ a {
display: inline; display: inline;
} }
.setting {
margin: 1em 0;
}
.setting .explanation {
color: #999;
margin: 0;
}
.repos h2 { .repos h2 {
font-size: 32px; font-size: 32px;
font-weight: bold; font-weight: bold;

View file

@ -15,21 +15,39 @@
<form method="POST" action="{{routeUrl "save-settings"}}"> <form method="POST" action="{{routeUrl "save-settings"}}">
<p> <div class="setting">
<label> <label>
Timezone for digest day boundaries: Timezone:
<select name="timezone_name"> <select name="timezone_name">
{{$accountTimezoneName := .Account.TimezoneName}} {{$accountTimezoneName := .Account.TimezoneName}}
{{range .Timezones}} {{range .Timezones}}
{{if .LocationName}} {{if .LocationName}}
<option value={{.LocationName}} {{if eq .LocationName $accountTimezoneName}}selected{{end}}>{{.LocationName}} (GMT {{.DisplayUTCOffset}})</option> <option value="{{.LocationName}}" {{if eq .LocationName $accountTimezoneName}}selected{{end}}>{{.LocationName}} (GMT {{.DisplayUTCOffset}})</option>
{{else}} {{else}}
<option disabled></option> <option disabled></option>
{{end}} {{end}}
{{end}} {{end}}
</select> </select>
<div class="explanation">
Used for determining day boundaries and timestamps in emails.
</div>
</label> </label>
</p> </div>
<div class="setting">
<label>
Email address:
<select name="email_address">
{{$accountEmailAddress := .AccountEmailAddress}}
{{range .EmailAddresses}}
<option value="{{.}}" {{if eq . $accountEmailAddress}}selected{{end}}>{{.}}</option>
{{end}}
</select>
</label>
<div class="explanation">
Where your digest will be sent to.
</div>
</div>
<p> <p>
You have {{len .Repos.AllRepos}} repositories. Select which you would like to include in your digest: You have {{len .Repos.AllRepos}} repositories. Select which you would like to include in your digest: