diff --git a/store/store.go b/store/store.go index 1deacb2..d76837a 100644 --- a/store/store.go +++ b/store/store.go @@ -2,14 +2,26 @@ package store import ( "os" + "fmt" "bufio" "strings" + "io/ioutil" ) type Row struct { Data []string } +func ReadData(path string) []byte { + d, err := ioutil.ReadFile(path) + if err != nil { + fmt.Println(err) + return []byte(``) + } + + return d +} + func ReadRows(path, delimiter string) *[]Row { f, _ := os.Open(path) @@ -28,14 +40,14 @@ func ReadRows(path, delimiter string) *[]Row { return &rows } -func WriteData(path, data, delimeter string) { - f, err := os.OpenFile(path, os.O_CREATE | os.O_RDWR, 0644) +func WriteData(path string, data []byte) { + f, err := os.OpenFile(path, os.O_CREATE | os.O_RDWR | os.O_TRUNC, 0644) if err != nil { fmt.Println(err) } defer f.Close() - _, err = f.WriteString(data) + _, err = f.Write(data) if err != nil { fmt.Println(err) } @@ -48,7 +60,7 @@ func WriteRows(path string, rows *[]Row, delimeter string) { } defer f.Close() - for _, r := range rows { + for _, r := range *rows { _, err = f.WriteString(strings.Join(r.Data, delimeter)) if err != nil { fmt.Println(err) diff --git a/where/where.go b/where/where.go index 0e41edc..9b67e8d 100644 --- a/where/where.go +++ b/where/where.go @@ -13,11 +13,19 @@ import ( "flag" "time" "text/template" + + "github.com/thebaer/geo" + "github.com/thebaer/tildes/store" +) + +const ( + locDataJSON = "/home/bear/public_html/where.json" ) func main() { // Get arguments outFilePtr := flag.String("f", "where", "Outputted HTML filename (without .html)") + geocodeAPIKeyPtr := flag.String("k", "", "Google Geocoding API key") flag.Parse() // Get online users with `who` @@ -26,18 +34,32 @@ func main() { // Fetch user locations based on IP address for i := range users { getGeo(&users[i]) + getFuzzyCoords(&users[i], *geocodeAPIKeyPtr) } + // Write user coord data + cacheUserLocations(&users) + // Generate page generate(users, *outFilePtr) } type user struct { - Name string - IP string - Region string - Country string - CurrentTime string + Name string `json:"name"` + IP string `json:"ip"` + Region string `json:"region"` + Country string `json:"country"` + CurrentTime string `json:"current_time"` + Latitude float64 `json:"lat"` + Longitude float64 `json:"lng"` +} + +type publicUser struct { + Name string `json:"name"` + Region string `json:"region"` + Country string `json:"country"` + Latitude float64 `json:"lat"` + Longitude float64 `json:"lng"` } var ipRegex = regexp.MustCompile("(([0-9]{1,3}[.-]){3}[0-9]{1,3})") @@ -136,6 +158,39 @@ func getGeo(u *user) { } } +func getFuzzyCoords(u *user, apiKey string) { + fmt.Printf("Fetching %s fuzzy coordinates...\n", u.Name) + + loc := prettyLocation(u.Region, u.Country) + addr, err := geo.Geocode(loc, apiKey) + + if err != nil { + fmt.Println(err) + return + } + + u.Latitude = addr.Lat + u.Longitude = addr.Lng +} + +func cacheUserLocations(users *[]user) { + // Read user data + res := &map[string]publicUser{} + if err := json.Unmarshal(store.ReadData(locDataJSON), &res); err != nil { + fmt.Println(err) + } + + // Update user data + for i := range *users { + u := (*users)[i] + (*res)[u.Name] = publicUser{Name: u.Name, Region: u.Region, Country: u.Country, Latitude: u.Latitude, Longitude: u.Longitude} + } + + // Write user data + json, _ := json.Marshal(res) + store.WriteData(locDataJSON, json) +} + func prettyLocation(region, country string) string { if region != "" { return fmt.Sprintf("%s, %s", region, country)