-
Notifications
You must be signed in to change notification settings - Fork 0
/
text-me-when.go
142 lines (129 loc) · 4.16 KB
/
text-me-when.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"regexp"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sns"
"github.com/adamkpickering/reminder-boi/reminder"
)
// Sends an SMS message to a phone number via AWS SNS. The phone number must be in E.164 format.
func send_message(sns_client *sns.SNS, message string, phone_number string) error {
pi := &sns.PublishInput{
Message: &message,
PhoneNumber: &phone_number,
}
if err := pi.Validate(); err != nil {
return fmt.Errorf("pi.Validate: %w", err)
}
_, err := sns_client.Publish(pi)
if err != nil {
return fmt.Errorf("sns_client.Publish: %w", err)
}
return nil
}
// Iterates through reminders and fires the ones that should be fired at the eval_time.
func fire_reminders(eval_time time.Time, phone_number string, sns_client *sns.SNS,
reminder_list []reminder.ReminderV1) {
for _, reminder := range reminder_list {
if reminder.ShouldRun(eval_time) {
err := send_message(sns_client, reminder.Message, phone_number)
if err != nil {
log.Printf("send_message failed: %s", err)
continue
}
log.Printf("sent message \"%s\" to %s", reminder.Message, phone_number)
}
}
}
func main() {
// set up logging
log.SetOutput(os.Stdout)
// parse CLI flags
flag.Usage = func() {
usage_header := "Usage: %s [OPTIONS] PHONE_NUMBER\n" +
"\n" +
" Checks once a minute for reminders whose messages should be sent out.\n" +
" PHONE_NUMBER is the phone number, in E.164 format, that you want the messages\n" +
" to be sent to.\n" +
"\n" +
" The environment variables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and\n" +
" AWS_DEFAULT_REGION are required to send text messages via AWS SNS. For more\n" +
" information on what these mean please see the AWS documentation.\n" +
"\n" +
"Options:\n"
fmt.Fprintf(flag.CommandLine.Output(), usage_header, os.Args[0])
flag.PrintDefaults()
}
reminders_path := flag.String("c", "/etc/text-me-when.json", "The path to the reminders config")
send_test := flag.Bool("t", false, "Send a test SMS to the configured phone number before entering main loop")
flag.Parse()
// parse phone number
if flag.NArg() != 1 {
flag.Usage()
os.Exit(1)
}
phone_number := flag.Args()[0]
match, err := regexp.MatchString(`^\+[0-9]{11,15}$`, phone_number)
if err != nil {
fmt.Printf("There was a problem while validating phone number: %s\n", err)
os.Exit(1)
}
if !match {
fmt.Printf("%s is not a valid phone number. It must consist of a + followed by up to 15 digits.\n")
os.Exit(1)
}
// read environment variables
region_key := "AWS_DEFAULT_REGION"
region, ok := os.LookupEnv(region_key)
if !ok {
fmt.Printf("Could not find required env var %s.\n", region_key)
os.Exit(1)
}
// construct sns client
creds := credentials.NewEnvCredentials()
cfg := aws.NewConfig().WithCredentials(creds).WithRegion(region)
session := session.Must(session.NewSession(cfg))
sns_client := sns.New(session)
log.Print("constructed AWS SNS client")
// parse config file
raw_file, err := ioutil.ReadFile(*reminders_path)
if err != nil {
fmt.Printf("Failed to read config file: %s\n", err)
os.Exit(1)
}
reminder_list := make([]reminder.ReminderV1, 0)
err = json.Unmarshal(raw_file, &reminder_list)
if err != nil {
fmt.Printf("Failed to parse config file: %s\n", err)
os.Exit(1)
}
log.Printf("read in %d reminders from reminder config", len(reminder_list))
// send test message if configured
if *send_test {
msg := "text-me-when: this is a test message. If you got this, " +
"you can be sure that message sending is working."
err := send_message(sns_client, msg, phone_number)
if err != nil {
fmt.Printf("There was a problem with sending test message: %s\n", err)
os.Exit(1)
}
log.Printf("sent test message to %s", phone_number)
}
// main loop
var wait_time time.Duration = 60
log.Print("entering main loop")
ticker := time.NewTicker(wait_time * time.Second)
for {
received_time := <-ticker.C
log.Print("checking reminders")
fire_reminders(received_time, phone_number, sns_client, reminder_list)
}
}