Skip to content

Commit

Permalink
Show the dates of events in messages
Browse files Browse the repository at this point in the history
Also send to webhook destination for new notifications

Signed-off-by: Charlie Egan <charlieegan3@users.noreply.github.com>
  • Loading branch information
charlieegan3 committed Jun 28, 2022
1 parent 6b9c6cd commit 0d13807
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 56 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
GO_TEST_ARGS := ""
FILE_PATTERN := 'html\|plush\|go\|sql\|Makefile'

test:
go test ./... $(GO_TEST_ARGS)

test_watch:
find . | grep $(FILE_PATTERN) | entr bash -c 'clear; make test'
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Current functionality:
* Download contact data
* Generate vCard file for one or more contacts
* Sync the contacts to carddav server
* Send notifications about birthdays and special events

Example config file:

Expand All @@ -19,12 +20,21 @@ airtable:
key: xxxxxxxxxxxxxxxxx
base: xxxxxxxxxxxxxxxxx
table: xxxxxxxxxxxxxxxxx
view: xxxxxx
view: Active
vcard:
use_v3: true
photo:
size: 100
dropbox:
path: /contacts.vcard
token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
carddav:
serverURL: https://example.com/dav/addressbooks/user/user@example.com/Default
user: user@example.com
serverURL: https://carddav.fastmail.com/dav/addressbooks/user/xxxxxxxxxxxxxxxxxxxxxxxxx/Default
user: xxxxxxxxxxxxxxxxxxxxxxxxx
password: xxxxxxxxxxxxxxxx
pushover:
user_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
app_token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
webhook:
endpoint: https://hooks.zapier.com/hooks/catch/xxxxxxxxxxxxxx
```
22 changes: 19 additions & 3 deletions cmd/day.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"github.com/charlieegan3/airtable-contacts/pkg/webhook"
"log"
"time"

Expand Down Expand Up @@ -31,17 +32,32 @@ var dayCmd = &cobra.Command{
}

// set the notification period
periodStart := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.UTC)
alert, title, message, err := specialdays.Generate(records, periodStart, 1)
periodStart := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day()-1, 0, 0, 0, 0, time.UTC)
alert, title, message, err := specialdays.Generate(records, periodStart, 1, true)
if err != nil {
log.Fatalf("failed to generate alert message: %s", err)
}

// send the alert if needed
if alert {
// notify via pushover
pushoverRecipient := psh.NewRecipient(viper.GetString("pushover.user_key"))
pushoverApp := psh.New(viper.GetString("pushover.app_token"))
pushover.Notify(pushoverApp, pushoverRecipient, title, message)
err := pushover.Notify(pushoverApp, pushoverRecipient, title, message)
if err != nil {
log.Fatalf("failed to send notification via pushover")
}

// notify via webhook
err = webhook.Send(
viper.GetString("webhook.endpoint"),
title,
message,
"https://airtable.com",
)
if err != nil {
log.Fatalf("failed to send notification via webhook")
}
}
},
}
Expand Down
54 changes: 48 additions & 6 deletions cmd/week.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"fmt"
"github.com/charlieegan3/airtable-contacts/pkg/webhook"
"log"
"time"

Expand Down Expand Up @@ -32,7 +33,7 @@ var weekCmd = &cobra.Command{

// set the notification period
periodStart := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.UTC)
alert, title, message, err := specialdays.Generate(records, periodStart, 14)
alert, title, message, err := specialdays.Generate(records, periodStart, 14, false)
if err != nil {
log.Fatalf("failed to generate alert message: %s", err)
}
Expand All @@ -41,12 +42,53 @@ var weekCmd = &cobra.Command{
pushoverRecipient := psh.NewRecipient(viper.GetString("pushover.user_key"))
pushoverApp := psh.New(viper.GetString("pushover.app_token"))
if alert {
err = pushover.Notify(pushoverApp, pushoverRecipient, fmt.Sprintf("Weekly Summary (%s)", title), message)
title := fmt.Sprintf("Weekly Summary (%s)", title)

// notify on pushover
err := pushover.Notify(
pushoverApp,
pushoverRecipient,
title,
message,
)
if err != nil {
log.Fatalf("failed to send message: %s", err)
}

// notify via webhook
err = webhook.Send(
viper.GetString("webhook.endpoint"),
title,
message,
"https://airtable.com",
)
if err != nil {
log.Fatalf("failed to send notification via webhook")
}
} else {
err = pushover.Notify(pushoverApp, pushoverRecipient, "No Events", "There are no events in the next two weeks")
}
if err != nil {
log.Fatalf("failed to send message: %s", err)
title := "Weekly Summary (No Events)"
body := "There are no events in the next two weeks"
// notify on pushover
err = pushover.Notify(
pushoverApp,
pushoverRecipient,
title,
body,
)
if err != nil {
log.Fatalf("failed to send message: %s", err)
}

// notify via webhook
err = webhook.Send(
viper.GetString("webhook.endpoint"),
title,
body,
"https://airtable.com",
)
if err != nil {
log.Fatalf("failed to send notification via webhook")
}
}
},
}
Expand Down
84 changes: 52 additions & 32 deletions pkg/specialdays/specialdays.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/charlieegan3/special-days/pkg/motheringsunday"
)

func Generate(contacts []map[string]interface{}, checkDate time.Time, period int) (bool, string, string, error) {
func Generate(contacts []map[string]interface{}, checkDate time.Time, period int, today bool) (bool, string, string, error) {
// likely invalid call, just return nothing
if period == 0 {
return false, "", "", nil
Expand All @@ -20,6 +20,7 @@ func Generate(contacts []map[string]interface{}, checkDate time.Time, period int
periodEnd := checkDate.Add(time.Duration(period) * time.Hour * 24).Add(-1 * time.Second)

contactsWithBirthdays := []string{}
birthdayMessages := []string{}
contactsWithSpecialDays := []string{}
specialDayMessages := []string{}

Expand All @@ -32,21 +33,34 @@ func Generate(contacts []map[string]interface{}, checkDate time.Time, period int
return false, "", "", fmt.Errorf("failed to parse birthday value for: %v", contact)
}

birthdayThisYear := time.Date(time.Now().UTC().Year(), birthday.Month(), birthday.Day(), 0, 0, 0, 0, time.UTC)

if dateInPeriod(periodStart, periodEnd, birthdayThisYear) {
contactsWithBirthdays = append(contactsWithBirthdays, contact["Display Name"].(string))
// calculate the birthday date for the year of the period start
birthdayInYearForPeriod := time.Date(
periodStart.Year(),
birthday.Month(),
birthday.Day(),
0, 0, 0, 0,
time.UTC,
)

if dateInPeriod(periodStart, periodEnd, birthdayInYearForPeriod) {
name := contact["Display Name"].(string)
contactsWithBirthdays = append(contactsWithBirthdays, name)
message := fmt.Sprintf("%s has a birthday", name)
if !today {
message = fmt.Sprintf("%s on %s", message, birthday.Format("January 02"))
}
birthdayMessages = append(birthdayMessages, message)
}
}

// list names for special days
jsonSpecialDaysValue, ok := contact["JSON Special Days"].(string)
if ok {
decoder := json.NewDecoder(strings.NewReader(jsonSpecialDaysValue))
days := []struct {
var days []struct {
Label string `json:"label"`
Date string `json:"date"`
}{}
}
err := decoder.Decode(&days)
if err != nil {
return false, "", "", fmt.Errorf("failed to parse JSON Special Days value for: %v", contact)
Expand All @@ -70,64 +84,64 @@ func Generate(contacts []map[string]interface{}, checkDate time.Time, period int
}
}

dateThisYear := time.Date(time.Now().UTC().Year(), date.Month(), date.Day(), 0, 0, 0, 0, time.UTC)
dateThisPeriod := time.Date(periodStart.Year(), date.Month(), date.Day(), 0, 0, 0, 0, time.UTC)

if dateInPeriod(periodStart, periodEnd, dateThisYear) {
if dateInPeriod(periodStart, periodEnd, dateThisPeriod) {
contactsWithSpecialDays = append(contactsWithSpecialDays, contact["Display Name"].(string))
specialDayMessages = append(
specialDayMessages,
fmt.Sprintf("%s has a special day labelled '%s'", contact["Display Name"].(string), day.Label),
)
m := fmt.Sprintf("%s has a special day labelled '%s'", contact["Display Name"].(string), day.Label)
if !today {
m = fmt.Sprintf("%s on %s", m, date.Format("January 02"))
}
specialDayMessages = append(specialDayMessages, m)
}
}
}
}

// handle when both are set
if len(contactsWithSpecialDays) > 0 && len(contactsWithBirthdays) > 0 {
allNames := append(contactsWithSpecialDays, contactsWithBirthdays...)
allMessages := []string{}

for _, message := range specialDayMessages {
allMessages = append(allMessages, fmt.Sprintf("* %s", message))
}
for _, name := range contactsWithBirthdays {
allMessages = append(allMessages, fmt.Sprintf("* %s has a birthday", name))
for _, message := range birthdayMessages {
allMessages = append(allMessages, fmt.Sprintf("* %s", message))
}

initialList := strings.Join(allNames[0:len(allNames)-1], ", ")
return true,
fmt.Sprintf("%s & %s have events", initialList, allNames[len(allNames)-1]),
fmt.Sprintf("%s have events", joinNamesList(allNames, ",", "&")),
strings.Join(allMessages, "\n"),
nil
}

if len(specialDayMessages) == 1 {
// handle when only birthdays are set
if len(contactsWithBirthdays) == 1 {
return true,
specialDayMessages[0],
specialDayMessages[0],
fmt.Sprintf("%s's Birthday", contactsWithBirthdays[0]),
fmt.Sprintf("* %s", birthdayMessages[0]),
nil
}

if len(specialDayMessages) > 1 {
initialList := strings.Join(contactsWithSpecialDays[0:len(contactsWithSpecialDays)-1], ", ")
if len(contactsWithBirthdays) > 1 {
return true,
fmt.Sprintf("%s & %s have special days", initialList, contactsWithSpecialDays[len(contactsWithSpecialDays)-1]),
fmt.Sprintf("* %s", strings.Join(specialDayMessages, "\n* ")),
fmt.Sprintf("%d birthdays", len(contactsWithBirthdays)),
fmt.Sprintf("* %s", strings.Join(birthdayMessages, "\n* ")),
nil
}

if len(contactsWithBirthdays) == 1 {
// handle when only special days are set
if len(specialDayMessages) == 1 {
return true,
fmt.Sprintf("%s's Birthday", contactsWithBirthdays[0]),
fmt.Sprintf("It's %s's birthday", contactsWithBirthdays[0]),
specialDayMessages[0],
specialDayMessages[0],
nil
}

if len(contactsWithBirthdays) > 1 {
initialList := strings.Join(contactsWithBirthdays[0:len(contactsWithBirthdays)-1], ", ")
if len(specialDayMessages) > 1 {
return true,
fmt.Sprintf("%d birthdays", len(contactsWithBirthdays)),
fmt.Sprintf("%s & %s have birthdays", initialList, contactsWithBirthdays[len(contactsWithBirthdays)-1]),
fmt.Sprintf("%s have special days", joinNamesList(contactsWithSpecialDays, ",", "&")),
fmt.Sprintf("* %s", strings.Join(specialDayMessages, "\n* ")),
nil
}

Expand All @@ -143,3 +157,9 @@ func dateInPeriod(periodStart, periodEnd, date time.Time) bool {
}
return false
}

func joinNamesList(names []string, separator, finalSeparator string) string {
initialList := strings.Join(names[0:len(names)-1], separator+" ")

return fmt.Sprintf("%s %s %s", initialList, finalSeparator, names[len(names)-1])
}

0 comments on commit 0d13807

Please sign in to comment.