Skip to content

Instantly share code, notes, and snippets.

@mgalgs
Last active August 29, 2015 14:23
Show Gist options
  • Save mgalgs/642924e792e73e0de3ef to your computer and use it in GitHub Desktop.
Save mgalgs/642924e792e73e0de3ef to your computer and use it in GitHub Desktop.
itamaraty checker
#!/bin/bash
(
cat | msmtp -a default --read-recipients <<EOF
Subject: Summary of visa appointment checker
From: [email protected]
To: [email protected]
The earliest Visa appointment we were able to find today was:
$(cat /tmp/itamaraty-tracker)
EOF
) &
# for some reason the msmtp command above was hanging forever... Just sleep
# and then kill everything:
sleep 120
rm -v /tmp/itamaraty-tracker
kill %1
// -*- compile-command: "go build itamaraty.go"; -*-
package main
import (
"bufio"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"regexp"
"strings"
"time"
"github.com/andrew-d/go-termutil"
"github.com/PuerkitoBio/goquery"
)
const LAYOUT_ITMRTY = "20060102"
const LAYOUT_READABLE = "Monday, January 02, 2006"
const TRACKER_FILE = "/tmp/itamaraty-tracker"
func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s: %s", msg, err)
panic(fmt.Sprintf("%s: %s", msg, err))
}
}
func getDoc(url string) *goquery.Document {
if termutil.Isatty(os.Stdin.Fd()) {
doc, err := goquery.NewDocument(url)
failOnError(err, fmt.Sprintf("Couldn't download %s", url))
return doc
} else {
doc, err := goquery.NewDocumentFromReader(bufio.NewReader(os.Stdin))
failOnError(err, "Couldn't parse doc on stdin")
return doc
}
panic("BOGOMIPS")
}
func updateTrackerFile(earliest time.Time) {
contents, err := ioutil.ReadFile(TRACKER_FILE)
if err == nil {
timestr := strings.TrimSpace(string(contents[:]))
existing, err := time.Parse(LAYOUT_READABLE, timestr)
failOnError(err, fmt.Sprintf("Couldn't convert time string from tracker file: %s", timestr))
if existing.Before(earliest) {
fmt.Printf("Not updating tracker file since %q is not earlier than %q\n",
earliest, existing)
return
} else {
fmt.Printf("Updating tracker file since %q is earlier than %q\n",
earliest, existing)
}
} else {
fmt.Println("Updating tracker file since we failed to open it")
}
data := []byte(earliest.Format(LAYOUT_READABLE + "\n"))
err = ioutil.WriteFile(TRACKER_FILE, data, 0777)
failOnError(err, fmt.Sprintf("Couldn't write to tracker file: %s", TRACKER_FILE))
}
func main() {
url := "https://booknow.appointment-plus.com/1egll91k/?selection_form=yes&wt_c_id=&wt_d=&d=appointplus184&page=10&m=2&type=72&auth=yes&action=log_in&action2=&customer_id=&show_services=&temp_addon_id=&customer_location_id=321&vo=&selected_pets=&pet_count=&pet_list=&selected_children=&child_count=&children_list=&staff_switch_loc=&day_name=any&rep_id=&location_id=321&id=321&headquarters_id=321&service_id=1366&event="
target_date_str := "20150721"
target_date, _ := time.Parse(LAYOUT_ITMRTY, target_date_str)
doc := getDoc(url)
earliest, _ := time.Parse("2006", "3000")
doc.Find("#cv-leftnav-item-calendar-available-id").Each(func(i int, s *goquery.Selection) {
href, exists := s.Attr("href")
if !exists {
panic(fmt.Sprintf("Bogus calendar item: %s", s))
}
// javascript:dosubmit('20150825', 'viewappts', 'no','Child', 2)
re := regexp.MustCompile(`.*dosubmit\('(\d+)',.*`)
matches := re.FindStringSubmatch(href)
datestr := matches[1]
t, err := time.Parse(LAYOUT_ITMRTY, datestr)
failOnError(err, fmt.Sprintf("Couldn't parse date string: %s", datestr))
if t.Before(earliest) {
earliest = t
}
if t.Before(target_date) {
pretty_t := t.Format("Monday, January 2")
fmt.Printf("Found an earlier appointment! It's on %s. Sending mail now...\n", pretty_t)
msgfmt := "Subject: Found an earlier visa appointment\n" +
"From: [email protected]\n" +
"To: [email protected], [email protected]\n\n" +
"It's on %s\n" +
"Go book it now (after responding to this message so that mitchallen\n" +
"and sonnierae don't both book it):\n\n" +
"https://booknow.appointment-plus.com/1egll91k/\n"
msg := fmt.Sprintf(msgfmt, pretty_t)
mailcmd := exec.Command("msmtp", "-a", "default", "--read-recipients")
mailcmd.Stdin = strings.NewReader(msg)
err := mailcmd.Run()
failOnError(err, "Failed to run msmtp command!")
}
})
fmt.Printf("Couldn't find an earlier appointment :(.\nEarliest we found was %s\n", earliest.Format(LAYOUT_READABLE))
updateTrackerFile(earliest)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment