121 lines
3.4 KiB
Go
121 lines
3.4 KiB
Go
|
package graph
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"net/http"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"github.com/dsoprea/go-exif/v3"
|
||
|
exifcommon "github.com/dsoprea/go-exif/v3/common"
|
||
|
"github.com/google/uuid"
|
||
|
"reichard.io/imagini/graph/model"
|
||
|
)
|
||
|
|
||
|
func getContextHTTP(ctx context.Context) (*http.ResponseWriter, *http.Request, error) {
|
||
|
authContext := ctx.Value("auth").(*model.AuthContext)
|
||
|
|
||
|
resp := authContext.AuthResponse
|
||
|
if resp == nil {
|
||
|
return nil, nil, errors.New("Context Error")
|
||
|
}
|
||
|
|
||
|
req := authContext.AuthRequest
|
||
|
if resp == nil {
|
||
|
return nil, nil, errors.New("Context Error")
|
||
|
}
|
||
|
|
||
|
return resp, req, nil
|
||
|
}
|
||
|
|
||
|
func getContextIDs(ctx context.Context) (string, string, error) {
|
||
|
authContext := ctx.Value("auth").(*model.AuthContext)
|
||
|
accessToken := *authContext.AccessToken
|
||
|
|
||
|
uid, ok := accessToken.Get("sub")
|
||
|
if !ok {
|
||
|
return "", "", errors.New("Context Error")
|
||
|
}
|
||
|
|
||
|
did, ok := accessToken.Get("did")
|
||
|
if !ok {
|
||
|
return "", "", errors.New("Context Error")
|
||
|
}
|
||
|
|
||
|
userID, err := uuid.Parse(uid.(string))
|
||
|
if err != nil {
|
||
|
return "", "", errors.New("Context Error")
|
||
|
}
|
||
|
|
||
|
deviceID, err := uuid.Parse(did.(string))
|
||
|
if err != nil {
|
||
|
return "", "", errors.New("Context Error")
|
||
|
}
|
||
|
|
||
|
return userID.String(), deviceID.String(), nil
|
||
|
}
|
||
|
|
||
|
func deriveDeviceType(r *http.Request) model.DeviceType {
|
||
|
userAgent := strings.ToLower(r.Header.Get("User-Agent"))
|
||
|
if strings.Contains(userAgent, "ios-imagini") {
|
||
|
return model.DeviceTypeIOs
|
||
|
} else if strings.Contains(userAgent, "android-imagini") {
|
||
|
return model.DeviceTypeAndroid
|
||
|
} else if strings.Contains(userAgent, "chrome") {
|
||
|
return model.DeviceTypeChrome
|
||
|
} else if strings.Contains(userAgent, "firefox") {
|
||
|
return model.DeviceTypeFirefox
|
||
|
} else if strings.Contains(userAgent, "msie") {
|
||
|
return model.DeviceTypeInternetExplorer
|
||
|
} else if strings.Contains(userAgent, "edge") {
|
||
|
return model.DeviceTypeEdge
|
||
|
} else if strings.Contains(userAgent, "safari") {
|
||
|
return model.DeviceTypeSafari
|
||
|
}
|
||
|
return model.DeviceTypeUnknown
|
||
|
}
|
||
|
|
||
|
func mediaItemFromEXIFData(filePath string) (*model.MediaItem, error) {
|
||
|
rawExif, err := exif.SearchFileAndExtractExif(filePath)
|
||
|
entries, _, err := exif.GetFlatExifData(rawExif, nil)
|
||
|
|
||
|
decLong := float64(1)
|
||
|
decLat := float64(1)
|
||
|
|
||
|
mediaItem := &model.MediaItem{}
|
||
|
for _, v := range entries {
|
||
|
if v.TagName == "DateTimeOriginal" {
|
||
|
formattedTime, _ := time.Parse("2006:01:02 15:04:05", v.Formatted)
|
||
|
mediaItem.ExifDate = &formattedTime
|
||
|
} else if v.TagName == "GPSLatitude" {
|
||
|
latStruct := v.Value.([]exifcommon.Rational)
|
||
|
decLat *= deriveDecimalCoordinate(
|
||
|
latStruct[0].Numerator/latStruct[0].Denominator,
|
||
|
latStruct[1].Numerator/latStruct[1].Denominator,
|
||
|
float64(latStruct[2].Numerator)/float64(latStruct[2].Denominator),
|
||
|
)
|
||
|
} else if v.TagName == "GPSLongitude" {
|
||
|
longStruct := v.Value.([]exifcommon.Rational)
|
||
|
decLong *= deriveDecimalCoordinate(
|
||
|
longStruct[0].Numerator/longStruct[0].Denominator,
|
||
|
longStruct[1].Numerator/longStruct[1].Denominator,
|
||
|
float64(longStruct[2].Numerator)/float64(longStruct[2].Denominator),
|
||
|
)
|
||
|
} else if v.TagName == "GPSLatitudeRef" && v.Formatted == "S" {
|
||
|
decLat *= -1
|
||
|
} else if v.TagName == "GPSLongitudeRef" && v.Formatted == "W" {
|
||
|
decLong *= -1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mediaItem.Latitude = &decLat
|
||
|
mediaItem.Longitude = &decLong
|
||
|
|
||
|
return mediaItem, err
|
||
|
}
|
||
|
|
||
|
func deriveDecimalCoordinate(degrees, minutes uint32, seconds float64) float64 {
|
||
|
return float64(degrees) + (float64(minutes) / 60) + (seconds / 3600)
|
||
|
}
|