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 // Gross if err != nil && err.Error() == "no exif data" { return mediaItem, nil } return mediaItem, err } func deriveDecimalCoordinate(degrees, minutes uint32, seconds float64) float64 { return float64(degrees) + (float64(minutes) / 60) + (seconds / 3600) }