-
Notifications
You must be signed in to change notification settings - Fork 0
/
reminder.go
161 lines (137 loc) · 3.83 KB
/
reminder.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package main
import (
"context"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"gorm.io/gorm"
)
const (
Daily = "daily"
Monthly = "monthly"
Once = "once"
Weekly = "weekly"
)
var frequencies = []string{
Daily,
Monthly,
Once,
Weekly,
}
type Reminder struct {
gorm.Model
Call bool `json:"call"`
Day int `json:"day"`
DayOfWeek string `json:"day_of_week"`
Frequency string `json:"frequency" binding:"required"`
Hour int `json:"hour" binding:"required"`
Message string `json:"message" binding:"required"`
Minute int `json:"minute"`
Month string `json:"month"`
Second int `json:"second"`
Year int `json:"year"`
Zone string `json:"zone" binding:"required"`
}
func postReminders(c *gin.Context) {
var reminder Reminder
if err := c.ShouldBindJSON(&reminder); err != nil {
log.Errorf("Invalid arguments to POST /reminders: %v", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
fmt.Println(err)
return
}
// Custom Validations
// TODO: Break these out into a function or use as tag if possible
// TODO: Validate right params given frequency
reminder.Frequency = strings.ToLower(reminder.Frequency)
_, ok := find(frequencies, reminder.Frequency)
if !ok {
err := fmt.Errorf("Invalid frequency: %v", reminder.Frequency)
log.Errorf("Failed to create reminder: %v", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := db.Create(&reminder).Error; err != nil {
log.Errorf("Failed to create reminder: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create reminder"})
}
c.JSON(http.StatusCreated, &reminder)
resetWatcher()
}
func resetWatcher() {
reminders, err := getReminders(db)
if err != nil {
log.Error("Failed to refetch reminders: ", err)
return
}
watcher.reminders = reminders
}
func getReminders(db *gorm.DB) ([]Reminder, error) {
log.Info("Fetching reminders from database...")
reminders := []Reminder{}
if err := db.Find(&reminders).Error; err != nil {
return reminders, fmt.Errorf("Failed to fetch data: %v\n", err)
}
log.Info("Fetched reminders from database")
return reminders, nil
}
func (r *Reminder) matchesSingleDay(t time.Time) bool {
return r.Day == t.Day() && r.Month == t.Month().String() && r.Year == t.Year()
}
func (r *Reminder) matchesDay(t time.Time) bool {
if r.Frequency == Once {
return r.matchesSingleDay(t)
}
if r.Frequency == Daily {
return true
}
if r.Frequency == Weekly {
return r.DayOfWeek == t.Weekday().String()
}
if r.Frequency == Monthly {
return r.Day == t.Day()
}
return false
}
func (r *Reminder) matchesTime(t time.Time) bool {
return r.Hour == t.Hour() && r.Minute == t.Minute() && r.Second == t.Second()
}
func (r *Reminder) MatchesDayAndTime(tick time.Time) bool {
locale, err := time.LoadLocation(r.Zone)
if err != nil {
log.Error("Failed to set local time: ", err)
return false
}
t := tick.In(locale)
return r.matchesDay(t) && r.matchesTime(t)
}
func (r *Reminder) SendMessage(client Client, from string, to string) {
if r.Call {
log.Infof("Calling reminder from %v to %v...\n", twilioFromNumber, twilioToNumber)
data := url.Values{}
data.Set("From", twilioFromNumber)
data.Set("To", twilioToNumber)
msg := fmt.Sprintf(
"<Response><Say voice=\"Polly.Joanna\">%s</Say></Response>",
r.Message,
)
data.Set("Twiml", msg)
_, err := client.Calls().Create(context.Background(), data)
if err != nil {
log.Error("Failed to send reminder: ", err)
return
}
} else {
log.Infof("Sending reminder via SMS from %v to %v...\n", twilioFromNumber, twilioToNumber)
_, err := client.Messages().SendMessage(from, to, r.Message, nil)
if err != nil {
log.Error("Failed to send reminder: ", err)
return
}
}
log.Info("Reminder sent: ", r)
}