예제 #1
0
func parseReminder(from, body string) (*remind.Reminder, error) {
	parts := regexRemindMe.FindStringSubmatch(body)
	if len(parts) < 7 {
		err := errors.New("Could not schedule your reminder. Be sure to" +
			" use military time (24-hour time) when saying something like," +
			"\n\nRemind me to take out the trash @ 18:00 daily")
		log.Printf("Error sending after failed time parsing: %v\n", err)
		return nil, err
	}

	// len(parts) >= 7

	// log.Printf("%d parts == %#v\n", len(parts), parts)

	// parts[0] is the entire SMS message; ignore
	description := parts[1]
	around := (parts[2] == "around")
	nextRun, err := parseTime(parts[3], parts[5])
	if err != nil {
		return nil, err
	}

	impliedDaily := (parts[4] == "starting")

	var period time.Duration
	if impliedDaily || parts[6] == "daily" {
		period = 24 * time.Hour
	}

	var plusMinus time.Duration
	if around {
		// TODO: Make configurable
		plusMinus = 60 * time.Minute
	}

	reminder := &remind.Reminder{
		Recipient:   from,
		Description: strings.ToUpper(description[0:1]) + description[1:],
		NextRun:     nextRun,
		Period:      period,
		PlusMinus:   plusMinus,

		Raw:     body,
		Created: remind.Now(),
	}

	return reminder, nil
}
예제 #2
0
func parseTime(hhmm string, day string) (time.Time, error) {
	when := strings.SplitN(hhmm, ":", 2)
	hours, _ := strconv.Atoi(when[0])
	mins, _ := strconv.Atoi(when[1])

	now := remind.Now()

	if day == "" || day == "today" || day == "tonight" || day == "tomorrow" {
		nowHours, nowMins, nowSecs := now.Clock()
		today := now.
			Add(time.Duration(-nowHours) * time.Hour).
			Add(time.Duration(-nowMins) * time.Minute).
			Add(time.Duration(-nowSecs) * time.Second)

		nextRun := today.
			Add(time.Duration(hours) * time.Hour).
			Add(time.Duration(mins) * time.Minute)

		if nextRun.Before(now) || day == "tomorrow" {
			// Tomorrow
			nextRun = nextRun.Add(24 * time.Hour)
		}

		return nextRun, nil
	}

	// Guaranteed: day is of the form `\d?\d/\d?\d`

	monthDay := strings.SplitN(day, "/", 2)
	month, _ := strconv.Atoi(monthDay[0])
	dayNum, _ := strconv.Atoi(monthDay[1])

	nextRun := time.Date(now.Year(), time.Month(month), dayNum,
		hours, mins, 0, 0, remind.LosAngeles)

	if nextRun.Before(now) {
		// Next year
		nextRun = time.Date(now.Year()+1, time.Month(month), dayNum,
			hours, mins, 0, 0, remind.LosAngeles)
	}

	return nextRun, nil
}
예제 #3
0
func TestReminderRegex(t *testing.T) {
	nowYear, nowMonth, nowDay := remind.Now().Date()

	tests := []struct {
		body string
		rem  remind.Reminder
	}{
		{
			"Remind me to buy milk at 14:45 tomorrow",
			remind.Reminder{
				Description: "Buy milk",
				NextRun: time.Date(nowYear, nowMonth, nowDay+1,
					14, 45, 0, 0, remind.LosAngeles),
			},
		},
		{
			"Remind me to do $tuFF at 23:59 today",
			remind.Reminder{
				Description: "Do $tuFF",
				NextRun: time.Date(nowYear, nowMonth, nowDay,
					23, 59, 0, 0, remind.LosAngeles),
			},
		},
		{
			"Remind me to do  whatever at 23:59",
			remind.Reminder{
				Description: "Do  whatever",
				NextRun: time.Date(nowYear, nowMonth, nowDay,
					23, 59, 0, 0, remind.LosAngeles),
			},
		},
		{
			"  remind me to write_GO/code!!.(?)  @ 23:59 on  12/09",
			remind.Reminder{
				Description: "Write_GO/code!!.(?)",
				NextRun: time.Date(nowYear, 12, 9,
					23, 59, 0, 0, remind.LosAngeles),
			},
		},
		{
			"Remind me to take out the trash @ 18:00",
			remind.Reminder{
				Description: "Take out the trash",
				NextRun: time.Date(nowYear, nowMonth, nowDay,
					18, 00, 0, 0, remind.LosAngeles),
			},
		},
		{
			"Remind me to take out the trash @ 18:00 starting 1/1",
			remind.Reminder{
				Description: "Take out the trash",
				NextRun: time.Date(nowYear+1, 1, 1,
					18, 00, 0, 0, remind.LosAngeles),
				Period: 24 * time.Hour,
			},
		},
		{
			"Remind me to take out the trash @ 18:00 on 1/1 daily",
			remind.Reminder{
				Description: "Take out the trash",
				NextRun: time.Date(nowYear+1, 1, 1,
					18, 00, 0, 0, remind.LosAngeles),
				Period: 24 * time.Hour,
			},
		},
	}

	for _, test := range tests {
		r, err := parseReminder("", test.body)
		if err != nil {
			t.Errorf("Error parsing `%s`: %v", test.body, err)
			continue
		}

		assert.Equal(t, r.Description, test.rem.Description, "Description is wrong")
		assert.Equal(t, r.NextRun, test.rem.NextRun, "NextRun is wrong")
		assert.Equal(t, r.Period, test.rem.Period, "Period is wrong")
		assert.Equal(t, r.PlusMinus, time.Duration(0), "PlusMinus is wrong")

		r, _ = parseReminder("", test.body+" daily")
		assert.Equal(t, r.Period, 24*time.Hour, "Period is wrong (daily)")
	}
}
예제 #4
0
func init() {
	rand.Seed(remind.Now().Unix())
}
예제 #5
0
func main() {
	if len(os.Args) < 5 {
		log.Fatalf("Usage: %s <to_number> <start_time> <finish_time> <msg 1> [<msg 2> ...]\n", filepath.Base(os.Args[0]))
	}

	toNumber := os.Args[1]
	startStr := os.Args[2]  // \d?\d:\d\d
	finishStr := os.Args[3] // \d?\d:\d\d
	messages := os.Args[4:]

	if !regexTime.MatchString(startStr) {
		log.Fatalf("Start time must be of the form hh:mm; you typed '%s'", startStr)
	}
	if !regexTime.MatchString(finishStr) {
		log.Fatalf("Finish time must be of the form hh:mm; you typed '%s'", finishStr)
	}

	startHour, _ := strconv.Atoi(startStr[:2])
	startMinute, _ := strconv.Atoi(startStr[3:])

	finishHour, _ := strconv.Atoi(finishStr[:2])
	finishMinute, _ := strconv.Atoi(finishStr[3:])

	now := remind.Now()

	year, month, day := now.Date()
	start := time.Date(year, month, day, startHour, startMinute,
		0, 0, remind.LosAngeles)
	finish := time.Date(year, month, day, finishHour, finishMinute,
		0, 0, remind.LosAngeles)

	reminders, err := remind.IntervalSMS(toNumber, messages, start, finish)
	if err != nil {
		log.Fatalf("Error from IntervalSMS: %v\n", err)
	}

	wg := &sync.WaitGroup{}
	wg.Add(len(reminders))

	for _, rem := range reminders {
		go func(rem *remind.Reminder) {
			defer wg.Done()

			if rem.NextRun.Before(now) {
				log.Printf("Reminder `%s` scheduled for the past (%s ago); not running\n",
					rem.Description, now.Sub(rem.NextRun))
				return
			}

			sleep := rem.NextRun.Sub(now)
			log.Printf("Reminder `%s` will run in %s\n", rem.Description, sleep)
			time.Sleep(sleep)

			if err := rem.SendSMS(); err != nil {
				log.Printf("Error sending Reminder `%v` to %s: %v\n",
					rem.Description, rem.Recipient, err)
				return
			}
			log.Printf("Reminder `%s` sent successfully\n", rem.Description)
		}(rem)
	}

	wg.Wait()

	log.Printf("All %d Reminders finished; exiting\n", len(reminders))
}