diff --git a/app/account.go b/app/account.go index c583b41..60bb127 100644 --- a/app/account.go +++ b/app/account.go @@ -23,6 +23,8 @@ type Account struct { TimezoneLocation *time.Location `datastore:"-,"` ExcludedRepoIds []int `datastore:",noindex"` DigestEmailAddress string + Frequency string + WeeklyDay time.Weekday } func getAccount(c appengine.Context, githubUserId int) (*Account, error) { @@ -49,6 +51,9 @@ func initAccount(account *Account) error { if len(account.TimezoneName) == 0 { account.TimezoneName = "America/Los_Angeles" } + if len(account.Frequency) == 0 { + account.Frequency = "daily" + } account.TimezoneLocation, err = time.LoadLocation(account.TimezoneName) if err != nil { return err @@ -56,18 +61,20 @@ func initAccount(account *Account) error { return nil } -func getAllAccountGithubUserIds(c appengine.Context) ([]int, error) { +func getAllAccounts(c appengine.Context) ([]Account, error) { q := datastore.NewQuery("Account") var accounts []Account _, err := q.GetAll(c, &accounts) if err != nil { return nil, err } - result := make([]int, len(accounts)) for i := range accounts { - result[i] = accounts[i].GitHubUserId + err = initAccount(&accounts[i]) + if err != nil { + return nil, err + } } - return result, nil + return accounts, nil } func (account *Account) IsRepoIdExcluded(repoId int) bool { diff --git a/app/digest.go b/app/digest.go index 170dece..29cd6ff 100644 --- a/app/digest.go +++ b/app/digest.go @@ -12,10 +12,11 @@ import ( ) const ( - CommitDisplayDateFormat = "3:04pm" - CommitDisplayDateTooltipFormat = "Monday January 2 3:04pm" - DigestDisplayDateFormat = "January 2, 2006" - DigestDisplayDayOfWeekFormat = "Monday" + CommitDisplayDateFormat = "3:04pm" + CommitDisplayDateFullFormat = "Monday January 2 3:04pm" + DigestDisplayDateFormat = "January 2, 2006" + DigestDisplayShortDateFormat = "January 2" + DigestDisplayDayOfWeekFormat = "Monday" ) type DigestCommit struct { @@ -52,12 +53,16 @@ func (commit DigestCommit) DisplayDate() string { return commit.PushDate.Format(CommitDisplayDateFormat) } +func (commit DigestCommit) WeeklyDisplayDate() string { + return commit.PushDate.Format(CommitDisplayDateFullFormat) +} + func (commit DigestCommit) DisplayDateTooltip() string { // But show the full details in a tooltip return fmt.Sprintf( "Pushed at %s\nCommited at %s", - commit.PushDate.Format(CommitDisplayDateTooltipFormat), - commit.CommitDate.Format(CommitDisplayDateTooltipFormat)) + commit.PushDate.Format(CommitDisplayDateFullFormat), + commit.CommitDate.Format(CommitDisplayDateFullFormat)) } type RepoDigest struct { @@ -76,6 +81,7 @@ type IntervalDigest struct { yearDelta int StartTime time.Time EndTime time.Time + Weekly bool RepoDigests []*RepoDigest repos []*Repo } @@ -116,15 +122,33 @@ func (digest *IntervalDigest) Description() string { } else { formattedRepoCount = fmt.Sprintf("%d repositories", repoCount) } - dayOfWeek := digest.StartTime.Format(DigestDisplayDayOfWeekFormat) - // Insert a zero-width space inside the day of the week so that Gmail's - // event detection doesn't pick it up. - dayOfWeek = fmt.Sprintf("%s\u200B%s", dayOfWeek[:1], dayOfWeek[1:]) - return fmt.Sprintf("%s was a %s. You had %s in %s that day.", - digest.StartTime.Format(DigestDisplayDateFormat), - dayOfWeek, + + if !digest.Weekly { + dayOfWeek := digest.StartTime.Format(DigestDisplayDayOfWeekFormat) + // Insert a zero-width space inside the day of the week so that Gmail's + // event detection doesn't pick it up. + dayOfWeek = fmt.Sprintf("%s\u200B%s", dayOfWeek[:1], dayOfWeek[1:]) + return fmt.Sprintf("%s was a %s. You had %s in %s that day.", + digest.StartTime.Format(DigestDisplayDateFormat), + dayOfWeek, + formattedCommitCount, + formattedRepoCount) + } + + formattedEndTime := digest.EndTime.Format(DigestDisplayDateFormat) + var formattedStartTime string + if digest.StartTime.Year() == digest.EndTime.Year() { + formattedStartTime = digest.StartTime.Format(DigestDisplayShortDateFormat) + } else { + formattedStartTime = digest.StartTime.Format(DigestDisplayDateFormat) + } + formattedStartTime = fmt.Sprintf("%s\u200B%s", formattedStartTime[:1], formattedStartTime[1:]) + formattedEndTime = fmt.Sprintf("%s\u200B%s", formattedEndTime[:1], formattedEndTime[1:]) + return fmt.Sprintf("You had %s in %s the week of %s to %s.", formattedCommitCount, - formattedRepoCount) + formattedRepoCount, + formattedStartTime, + formattedEndTime) } type Digest struct { @@ -152,7 +176,11 @@ func newDigest(c appengine.Context, githubClient *github.Client, account *Accoun if digestStartTime.Before(oldestDigestTime) { break } - digestEndTime := digestStartTime.AddDate(0, 0, 1) + daysInDigest := 1 + if account.Frequency == "weekly" { + daysInDigest = 7 + } + digestEndTime := digestStartTime.AddDate(0, 0, daysInDigest) // Only look at repos that may have activity in the digest interval. var intervalRepos []*Repo @@ -169,6 +197,7 @@ func newDigest(c appengine.Context, githubClient *github.Client, account *Accoun RepoDigests: make([]*RepoDigest, 0, len(intervalRepos)), StartTime: digestStartTime, EndTime: digestEndTime, + Weekly: account.Frequency == "weekly", }) } diff --git a/app/githop.go b/app/githop.go index 760db5a..ae8cb28 100644 --- a/app/githop.go +++ b/app/githop.go @@ -238,15 +238,23 @@ func sendDigestHandler(w http.ResponseWriter, r *http.Request) { func digestCronHandler(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) - githubUserIds, err := getAllAccountGithubUserIds(c) + accounts, err := getAllAccounts(c) if err != nil { c.Errorf("Error looking up accounts: %s", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } - for _, githubUserId := range githubUserIds { - c.Infof("Enqueing task for %d...", githubUserId) - sendDigestForAccountFunc.Call(c, githubUserId) + for _, account := range accounts { + if account.Frequency == "weekly" { + now := time.Now().In(account.TimezoneLocation) + if now.Weekday() != account.WeeklyDay { + c.Infof("Skipping %d, since it wants weekly digests on %ss and today is a %s.", + account.GitHubUserId, account.WeeklyDay, now.Weekday()) + continue + } + } + c.Infof("Enqueing task for %d...", account.GitHubUserId) + sendDigestForAccountFunc.Call(c, account.GitHubUserId) } fmt.Fprint(w, "Done") } @@ -421,6 +429,14 @@ func saveSettingsHandler(w http.ResponseWriter, r *http.Request) { return } + account.Frequency = r.FormValue("frequency") + weeklyDay, err := strconv.Atoi(r.FormValue("weekly_day")) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + account.WeeklyDay = time.Weekday(weeklyDay) + timezoneName := r.FormValue("timezone_name") _, err = time.LoadLocation(timezoneName) if err != nil { diff --git a/app/templates/settings.html b/app/templates/settings.html index 68bb842..c1307af 100644 --- a/app/templates/settings.html +++ b/app/templates/settings.html @@ -15,18 +15,43 @@