Working auth and photo json endpoint
Signed-off-by: Kris Nóva <kris@nivenly.com>
This commit is contained in:
parent
ef275f97f4
commit
e4323b6047
2032 changed files with 821464 additions and 52 deletions
21
vendor/gopkg.in/ugjka/go-tz.v2/LICENSE
generated
vendored
Normal file
21
vendor/gopkg.in/ugjka/go-tz.v2/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 ugjka <esesmu@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
21
vendor/gopkg.in/ugjka/go-tz.v2/tz/LICENSE
generated
vendored
Normal file
21
vendor/gopkg.in/ugjka/go-tz.v2/tz/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 ugjka <esesmu@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
41
vendor/gopkg.in/ugjka/go-tz.v2/tz/bound.go
generated
vendored
Normal file
41
vendor/gopkg.in/ugjka/go-tz.v2/tz/bound.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
package tz
|
||||
|
||||
import "math"
|
||||
|
||||
func getBoundingBox(points []Point) []Point {
|
||||
if len(points) == 0 {
|
||||
return []Point{{0, 0}, {0, 0}}
|
||||
}
|
||||
|
||||
minX := math.Inf(1)
|
||||
minY := math.Inf(1)
|
||||
|
||||
maxX := math.Inf(-1)
|
||||
maxY := math.Inf(-1)
|
||||
|
||||
for _, v := range points {
|
||||
minX = math.Min(minX, v.Lon)
|
||||
minY = math.Min(minY, v.Lat)
|
||||
|
||||
maxX = math.Max(maxX, v.Lon)
|
||||
maxY = math.Max(maxY, v.Lat)
|
||||
}
|
||||
|
||||
return []Point{
|
||||
{math.Min(minX, maxX), math.Min(minY, maxY)},
|
||||
{math.Max(minX, maxX), math.Max(minY, maxY)},
|
||||
}
|
||||
}
|
||||
|
||||
func inBoundingBox(box []Point, point *Point) bool {
|
||||
|
||||
if point.Lat < box[0].Lat || box[1].Lat < point.Lat {
|
||||
return false
|
||||
}
|
||||
|
||||
if point.Lon < box[0].Lon || box[1].Lon < point.Lon {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
3
vendor/gopkg.in/ugjka/go-tz.v2/tz/gen.go
generated
vendored
Normal file
3
vendor/gopkg.in/ugjka/go-tz.v2/tz/gen.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
//go:generate go run tzshapefilegen/main.go -release 2020d
|
||||
|
||||
package tz
|
91
vendor/gopkg.in/ugjka/go-tz.v2/tz/geojson.go
generated
vendored
Normal file
91
vendor/gopkg.in/ugjka/go-tz.v2/tz/geojson.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
package tz
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// FeatureCollection ...
|
||||
type FeatureCollection struct {
|
||||
featureCollection
|
||||
}
|
||||
|
||||
type featureCollection struct {
|
||||
Features []*Feature
|
||||
}
|
||||
|
||||
//Feature ...
|
||||
type Feature struct {
|
||||
feature
|
||||
}
|
||||
|
||||
type feature struct {
|
||||
Geometry Geometry
|
||||
Properties struct {
|
||||
Tzid string
|
||||
}
|
||||
}
|
||||
|
||||
//Geometry ...
|
||||
type Geometry struct {
|
||||
geometry
|
||||
}
|
||||
|
||||
type geometry struct {
|
||||
Coordinates [][]Point
|
||||
BoundingBoxes [][]Point
|
||||
}
|
||||
|
||||
var jPolyType struct {
|
||||
Type string
|
||||
Geometries []*Geometry
|
||||
}
|
||||
|
||||
var jPolygon struct {
|
||||
Coordinates [][][]float64
|
||||
}
|
||||
|
||||
var jMultiPolygon struct {
|
||||
Coordinates [][][][]float64
|
||||
}
|
||||
|
||||
//UnmarshalJSON ...
|
||||
func (g *Geometry) UnmarshalJSON(data []byte) (err error) {
|
||||
if err := json.Unmarshal(data, &jPolyType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if jPolyType.Type == "Polygon" {
|
||||
if err := json.Unmarshal(data, &jPolygon); err != nil {
|
||||
return err
|
||||
}
|
||||
pol := make([]Point, len(jPolygon.Coordinates[0]))
|
||||
for i, v := range jPolygon.Coordinates[0] {
|
||||
pol[i].Lon = v[0]
|
||||
pol[i].Lat = v[1]
|
||||
}
|
||||
b := getBoundingBox(pol)
|
||||
g.BoundingBoxes = append(g.BoundingBoxes, b)
|
||||
g.Coordinates = append(g.Coordinates, pol)
|
||||
return nil
|
||||
}
|
||||
|
||||
if jPolyType.Type == "MultiPolygon" {
|
||||
if err := json.Unmarshal(data, &jMultiPolygon); err != nil {
|
||||
return err
|
||||
}
|
||||
g.BoundingBoxes = make([][]Point, len(jMultiPolygon.Coordinates))
|
||||
g.Coordinates = make([][]Point, len(jMultiPolygon.Coordinates))
|
||||
for j, poly := range jMultiPolygon.Coordinates {
|
||||
pol := make([]Point, len(poly[0]))
|
||||
for i, v := range poly[0] {
|
||||
pol[i].Lon = v[0]
|
||||
pol[i].Lat = v[1]
|
||||
}
|
||||
b := getBoundingBox(pol)
|
||||
g.BoundingBoxes[j] = b
|
||||
g.Coordinates[j] = pol
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
79
vendor/gopkg.in/ugjka/go-tz.v2/tz/raycast.go
generated
vendored
Normal file
79
vendor/gopkg.in/ugjka/go-tz.v2/tz/raycast.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
package tz
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
type polygon []Point
|
||||
|
||||
func newPoint(lon, lat *float64) *Point {
|
||||
return &Point{*lon, *lat}
|
||||
}
|
||||
|
||||
func (p polygon) centroid() Point {
|
||||
x := 0.0
|
||||
y := 0.0
|
||||
numPoints := float64(len(p))
|
||||
for _, p := range p {
|
||||
x += p.Lon
|
||||
y += p.Lat
|
||||
}
|
||||
return Point{x / numPoints, y / numPoints}
|
||||
}
|
||||
|
||||
func (p polygon) isClosed() bool {
|
||||
if len(p) < 3 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Returns whether or not the current Polygon contains the passed in Point.
|
||||
func (p polygon) contains(point *Point) bool {
|
||||
if !p.isClosed() {
|
||||
return false
|
||||
}
|
||||
|
||||
start := len(p) - 1
|
||||
end := 0
|
||||
|
||||
contains := intersectsWithRaycast(point, &p[start], &p[end])
|
||||
|
||||
for i := 1; i < len(p); i++ {
|
||||
if intersectsWithRaycast(point, &p[i-1], &p[i]) {
|
||||
contains = !contains
|
||||
}
|
||||
}
|
||||
|
||||
return contains
|
||||
}
|
||||
|
||||
// https://rosettacode.org/wiki/Ray-casting_algorithm#Go
|
||||
func intersectsWithRaycast(point, start, end *Point) bool {
|
||||
if start.Lat > end.Lat {
|
||||
start, end = end, start
|
||||
}
|
||||
for point.Lat == start.Lat || point.Lat == end.Lat {
|
||||
point.Lat = math.Nextafter(point.Lat, math.Inf(1))
|
||||
}
|
||||
if point.Lat < start.Lat || point.Lat > end.Lat {
|
||||
return false
|
||||
}
|
||||
if start.Lon > end.Lon {
|
||||
if point.Lon > start.Lon {
|
||||
return false
|
||||
}
|
||||
if point.Lon < end.Lon {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if point.Lon > end.Lon {
|
||||
return false
|
||||
}
|
||||
if point.Lon < start.Lon {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return (point.Lat-start.Lat)/(point.Lon-start.Lon) >= (end.Lat-start.Lat)/(end.Lon-start.Lon)
|
||||
}
|
160
vendor/gopkg.in/ugjka/go-tz.v2/tz/tz.go
generated
vendored
Normal file
160
vendor/gopkg.in/ugjka/go-tz.v2/tz/tz.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
// Package tz provides timezone lookup for a given location
|
||||
//
|
||||
// Features
|
||||
//
|
||||
// * The timezone shapefile is embedded in the build binary using go-bindata
|
||||
//
|
||||
// * Supports overlapping zones
|
||||
//
|
||||
// * You can load your own geojson shapefile if you want
|
||||
//
|
||||
// * Sub millisecond lookup even on old hardware
|
||||
//
|
||||
// Problems
|
||||
//
|
||||
// * The shapefile is simplified using a lossy method so it may be innacurate along the borders
|
||||
//
|
||||
// * This is purerly in-memory. Uses ~50MB of ram
|
||||
package tz
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
func init() {
|
||||
load()
|
||||
}
|
||||
|
||||
func load() {
|
||||
g, err := gzip.NewReader(bytes.NewBuffer(tzShapeFile))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer g.Close()
|
||||
|
||||
if err := json.NewDecoder(g).Decode(&tzdata); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
buildCenterCache()
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
|
||||
var tzdata FeatureCollection
|
||||
|
||||
type centers map[string][]Point
|
||||
|
||||
var centerCache centers
|
||||
|
||||
// Point describes a location by Latitude and Longitude
|
||||
type Point struct {
|
||||
Lon float64
|
||||
Lat float64
|
||||
}
|
||||
|
||||
// ErrNoZoneFound is returned when a zone for the given point is not found in the shapefile
|
||||
var ErrNoZoneFound = errors.New("no corresponding zone found in shapefile")
|
||||
|
||||
// ErrOutOfRange is returned when latitude exceeds 90 degrees or longitude exceeds 180 degrees
|
||||
var ErrOutOfRange = errors.New("point's coordinates out of range")
|
||||
|
||||
// GetZone returns a slice of strings containing time zone id's for a given Point
|
||||
func GetZone(p Point) (tzid []string, err error) {
|
||||
if p.Lon > 180 || p.Lon < -180 || p.Lat > 90 || p.Lat < -90 {
|
||||
return nil, ErrOutOfRange
|
||||
}
|
||||
var id string
|
||||
for _, v := range tzdata.Features {
|
||||
if v.Properties.Tzid == "" {
|
||||
continue
|
||||
}
|
||||
id = v.Properties.Tzid
|
||||
polys := v.Geometry.Coordinates
|
||||
bboxes := v.Geometry.BoundingBoxes
|
||||
for i := 0; i < len(polys); i++ {
|
||||
//Check bounding box first
|
||||
if !inBoundingBox(bboxes[i], &p) {
|
||||
continue
|
||||
}
|
||||
if polygon(polys[i]).contains(&p) {
|
||||
tzid = append(tzid, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(tzid) > 0 {
|
||||
return tzid, nil
|
||||
}
|
||||
return getClosestZone(&p)
|
||||
}
|
||||
|
||||
func distanceFrom(p1, p2 *Point) float64 {
|
||||
d0 := (p1.Lon - p2.Lon)
|
||||
d1 := (p1.Lat - p2.Lat)
|
||||
return math.Sqrt(d0*d0 + d1*d1)
|
||||
}
|
||||
|
||||
func getClosestZone(point *Point) (tzid []string, err error) {
|
||||
mindist := math.Inf(1)
|
||||
var winner string
|
||||
for id, v := range centerCache {
|
||||
for _, p := range v {
|
||||
tmp := distanceFrom(&p, point)
|
||||
if tmp < mindist {
|
||||
mindist = tmp
|
||||
winner = id
|
||||
}
|
||||
}
|
||||
}
|
||||
// Limit search radius
|
||||
if mindist > 2.0 {
|
||||
return getNauticalZone(point)
|
||||
}
|
||||
return append(tzid, winner), nil
|
||||
}
|
||||
|
||||
func getNauticalZone(point *Point) (tzid []string, err error) {
|
||||
z := point.Lon / 7.5
|
||||
z = (math.Abs(z) + 1) / 2
|
||||
z = math.Floor(z)
|
||||
if z == 0 {
|
||||
return append(tzid, "Etc/GMT"), nil
|
||||
}
|
||||
if point.Lon < 0 {
|
||||
return append(tzid, fmt.Sprintf("Etc/GMT+%.f", z)), nil
|
||||
}
|
||||
return append(tzid, fmt.Sprintf("Etc/GMT-%.f", z)), nil
|
||||
}
|
||||
|
||||
//BuildCenterCache builds centers for polygons
|
||||
func buildCenterCache() {
|
||||
centerCache = make(centers)
|
||||
var tzid string
|
||||
for _, v := range tzdata.Features {
|
||||
if v.Properties.Tzid == "" {
|
||||
continue
|
||||
}
|
||||
tzid = v.Properties.Tzid
|
||||
for _, poly := range v.Geometry.Coordinates {
|
||||
centerCache[tzid] = append(centerCache[tzid], polygon(poly).centroid())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LoadGeoJSON loads a custom GeoJSON shapefile from a Reader
|
||||
func LoadGeoJSON(r io.Reader) error {
|
||||
tzdata = FeatureCollection{}
|
||||
err := json.NewDecoder(r).Decode(&tzdata)
|
||||
if err != nil {
|
||||
load()
|
||||
return err
|
||||
}
|
||||
buildCenterCache()
|
||||
debug.FreeOSMemory()
|
||||
return nil
|
||||
}
|
5
vendor/gopkg.in/ugjka/go-tz.v2/tz/tzshapefile.go
generated
vendored
Normal file
5
vendor/gopkg.in/ugjka/go-tz.v2/tz/tzshapefile.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue