1
Fork 0

Start on image proccessing

This commit is contained in:
viktorstrate 2020-02-02 00:29:42 +01:00
parent a57c111630
commit d81e945b68
8 changed files with 720 additions and 16 deletions

View File

@ -1,3 +1,4 @@
DROP TABLE IF EXISTS photo;
DROP TABLE IF EXISTS album;
DROP TABLE IF EXISTS photo_url;
DROP TABLE IF EXISTS photo_exif;

View File

@ -1,12 +1,28 @@
CREATE TABLE IF NOT EXISTS photo_url (
url_id int NOT NULL AUTO_INCREMENT,
path varchar(256) NUT NULL,
token varchar(256) NOT NULL,
width int NOT NULL,
height int NOT NULL,
PRIMARY KEY (url_id)
);
CREATE TABLE IF NOT EXISTS photo_exif (
exif_id int NOT NULL AUTO_INCREMENT,
camera varchar(256),
maker varchar(256),
lens varchar(256),
dateShot timestamp,
file_size_bytes bigint,
exposure varchar(256),
aperature float,
iso int(6),
focal_length float,
flash varchar(256),
PRIMARY KEY (exif_id)
);
CREATE TABLE IF NOT EXISTS album (
album_id int NOT NULL AUTO_INCREMENT,
title varchar(256) NOT NULL,
@ -23,12 +39,14 @@ CREATE TABLE IF NOT EXISTS photo (
photo_id int NOT NULL AUTO_INCREMENT,
title varchar(256) NOT NULL,
path varchar(512) NOT NULL UNIQUE,
-- original_url int NOT NULL,
-- thumbnail_url int NOT NULL,
original_url int NOT NULL,
thumbnail_url int NOT NULL,
album_id int NOT NULL,
-- exif_id int NOT NULL,
exif_id int,
PRIMARY KEY (photo_id),
FOREIGN KEY (album_id) REFERENCES album(album_id),
FOREIGN KEY (exif_id) REFERENCES photo_exif(exif_id),
FOREIGN KEY (original_url) REFERENCES photo_url(url_id),
FOREIGN KEY (thumbnail_url) REFERENCES photo_url(url_id)
);

View File

@ -10,6 +10,7 @@ import (
"strconv"
"sync"
"sync/atomic"
"time"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/introspection"
@ -70,6 +71,7 @@ type ComplexityRoot struct {
Photo struct {
Album func(childComplexity int) int
Exif func(childComplexity int) int
ID func(childComplexity int) int
Original func(childComplexity int) int
Path func(childComplexity int) int
@ -77,6 +79,20 @@ type ComplexityRoot struct {
Title func(childComplexity int) int
}
PhotoExif struct {
Aperture func(childComplexity int) int
Camera func(childComplexity int) int
DateShot func(childComplexity int) int
Exposure func(childComplexity int) int
FileSize func(childComplexity int) int
Flash func(childComplexity int) int
FocalLength func(childComplexity int) int
Iso func(childComplexity int) int
Lens func(childComplexity int) int
Maker func(childComplexity int) int
Photo func(childComplexity int) int
}
PhotoURL struct {
Height func(childComplexity int) int
URL func(childComplexity int) int
@ -257,6 +273,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Photo.Album(childComplexity), true
case "Photo.exif":
if e.complexity.Photo.Exif == nil {
break
}
return e.complexity.Photo.Exif(childComplexity), true
case "Photo.id":
if e.complexity.Photo.ID == nil {
break
@ -292,6 +315,83 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Photo.Title(childComplexity), true
case "PhotoEXIF.aperture":
if e.complexity.PhotoExif.Aperture == nil {
break
}
return e.complexity.PhotoExif.Aperture(childComplexity), true
case "PhotoEXIF.camera":
if e.complexity.PhotoExif.Camera == nil {
break
}
return e.complexity.PhotoExif.Camera(childComplexity), true
case "PhotoEXIF.dateShot":
if e.complexity.PhotoExif.DateShot == nil {
break
}
return e.complexity.PhotoExif.DateShot(childComplexity), true
case "PhotoEXIF.exposure":
if e.complexity.PhotoExif.Exposure == nil {
break
}
return e.complexity.PhotoExif.Exposure(childComplexity), true
case "PhotoEXIF.fileSize":
if e.complexity.PhotoExif.FileSize == nil {
break
}
return e.complexity.PhotoExif.FileSize(childComplexity), true
case "PhotoEXIF.flash":
if e.complexity.PhotoExif.Flash == nil {
break
}
return e.complexity.PhotoExif.Flash(childComplexity), true
case "PhotoEXIF.focalLength":
if e.complexity.PhotoExif.FocalLength == nil {
break
}
return e.complexity.PhotoExif.FocalLength(childComplexity), true
case "PhotoEXIF.iso":
if e.complexity.PhotoExif.Iso == nil {
break
}
return e.complexity.PhotoExif.Iso(childComplexity), true
case "PhotoEXIF.lens":
if e.complexity.PhotoExif.Lens == nil {
break
}
return e.complexity.PhotoExif.Lens(childComplexity), true
case "PhotoEXIF.maker":
if e.complexity.PhotoExif.Maker == nil {
break
}
return e.complexity.PhotoExif.Maker(childComplexity), true
case "PhotoEXIF.photo":
if e.complexity.PhotoExif.Photo == nil {
break
}
return e.complexity.PhotoExif.Photo(childComplexity), true
case "PhotoURL.height":
if e.complexity.PhotoURL.Height == nil {
break
@ -574,11 +674,35 @@ type Photo {
thumbnail: PhotoURL
"The album that holds the photo"
album: Album!
# exif: PhotoEXIF
exif: PhotoEXIF
# shares: [ShareToken]
# downloads: [PhotoDownload]
}
"EXIF metadata from the camera"
type PhotoEXIF {
photo: Photo
"The model name of the camera"
camera: String
"The maker of the camera"
maker: String
"The name of the lens"
lens: String
dateShot: Time
"The formatted filesize of the image"
fileSize: String
"The exposure time of the image"
exposure: String
"The aperature stops of the image"
aperture: Float
"The ISO setting of the image"
iso: Int
"The focal length of the lens, when the image was taken"
focalLength: String
"A formatted description of the flash settings, when the image was taken"
flash: String
}
`},
)
@ -1461,6 +1585,414 @@ func (ec *executionContext) _Photo_album(ctx context.Context, field graphql.Coll
return ec.marshalNAlbum2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx, field.Selections, res)
}
func (ec *executionContext) _Photo_exif(ctx context.Context, field graphql.CollectedField, obj *models.Photo) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "Photo",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Exif, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*models.PhotoExif)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOPhotoEXIF2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoExif(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_photo(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Photo, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*models.Photo)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOPhoto2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhoto(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_camera(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Camera, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_maker(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Maker, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_lens(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Lens, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_dateShot(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.DateShot, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*time.Time)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_fileSize(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.FileSize, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_exposure(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Exposure, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_aperture(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Aperture, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*float64)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_iso(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Iso, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*int)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOInt2ᚖint(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_focalLength(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.FocalLength, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_flash(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoEXIF",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Flash, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoURL_url(ctx context.Context, field graphql.CollectedField, obj *models.PhotoURL) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
@ -3499,6 +4031,52 @@ func (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, ob
if out.Values[i] == graphql.Null {
invalids++
}
case "exif":
out.Values[i] = ec._Photo_exif(ctx, field, obj)
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch()
if invalids > 0 {
return graphql.Null
}
return out
}
var photoEXIFImplementors = []string{"PhotoEXIF"}
func (ec *executionContext) _PhotoEXIF(ctx context.Context, sel ast.SelectionSet, obj *models.PhotoExif) graphql.Marshaler {
fields := graphql.CollectFields(ec.RequestContext, sel, photoEXIFImplementors)
out := graphql.NewFieldSet(fields)
var invalids uint32
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("PhotoEXIF")
case "photo":
out.Values[i] = ec._PhotoEXIF_photo(ctx, field, obj)
case "camera":
out.Values[i] = ec._PhotoEXIF_camera(ctx, field, obj)
case "maker":
out.Values[i] = ec._PhotoEXIF_maker(ctx, field, obj)
case "lens":
out.Values[i] = ec._PhotoEXIF_lens(ctx, field, obj)
case "dateShot":
out.Values[i] = ec._PhotoEXIF_dateShot(ctx, field, obj)
case "fileSize":
out.Values[i] = ec._PhotoEXIF_fileSize(ctx, field, obj)
case "exposure":
out.Values[i] = ec._PhotoEXIF_exposure(ctx, field, obj)
case "aperture":
out.Values[i] = ec._PhotoEXIF_aperture(ctx, field, obj)
case "iso":
out.Values[i] = ec._PhotoEXIF_iso(ctx, field, obj)
case "focalLength":
out.Values[i] = ec._PhotoEXIF_focalLength(ctx, field, obj)
case "flash":
out.Values[i] = ec._PhotoEXIF_flash(ctx, field, obj)
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@ -4515,6 +5093,17 @@ func (ec *executionContext) marshalOPhoto2ᚖgithubᚗcomᚋviktorstrateᚋphoto
return ec._Photo(ctx, sel, v)
}
func (ec *executionContext) marshalOPhotoEXIF2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoExif(ctx context.Context, sel ast.SelectionSet, v models.PhotoExif) graphql.Marshaler {
return ec._PhotoEXIF(ctx, sel, &v)
}
func (ec *executionContext) marshalOPhotoEXIF2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoExif(ctx context.Context, sel ast.SelectionSet, v *models.PhotoExif) graphql.Marshaler {
if v == nil {
return graphql.Null
}
return ec._PhotoEXIF(ctx, sel, v)
}
func (ec *executionContext) marshalOPhotoURL2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoURL(ctx context.Context, sel ast.SelectionSet, v models.PhotoURL) graphql.Marshaler {
return ec._PhotoURL(ctx, sel, &v)
}
@ -4549,6 +5138,29 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as
return ec.marshalOString2string(ctx, sel, *v)
}
func (ec *executionContext) unmarshalOTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) {
return graphql.UnmarshalTime(v)
}
func (ec *executionContext) marshalOTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler {
return graphql.MarshalTime(v)
}
func (ec *executionContext) unmarshalOTime2ᚖtimeᚐTime(ctx context.Context, v interface{}) (*time.Time, error) {
if v == nil {
return nil, nil
}
res, err := ec.unmarshalOTime2timeᚐTime(ctx, v)
return &res, err
}
func (ec *executionContext) marshalOTime2ᚖtimeᚐTime(ctx context.Context, sel ast.SelectionSet, v *time.Time) graphql.Marshaler {
if v == nil {
return graphql.Null
}
return ec.marshalOTime2timeᚐTime(ctx, sel, *v)
}
func (ec *executionContext) marshalOUser2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx context.Context, sel ast.SelectionSet, v models.User) graphql.Marshaler {
return ec._User(ctx, sel, &v)
}

View File

@ -2,6 +2,10 @@
package models
import (
"time"
)
type Album struct {
ID string `json:"id"`
Title *string `json:"title"`
@ -29,6 +33,31 @@ type Photo struct {
Thumbnail *PhotoURL `json:"thumbnail"`
// The album that holds the photo
Album *Album `json:"album"`
Exif *PhotoExif `json:"exif"`
}
// EXIF metadata from the camera
type PhotoExif struct {
Photo *Photo `json:"photo"`
// The model name of the camera
Camera *string `json:"camera"`
// The maker of the camera
Maker *string `json:"maker"`
// The name of the lens
Lens *string `json:"lens"`
DateShot *time.Time `json:"dateShot"`
// The formatted filesize of the image
FileSize *string `json:"fileSize"`
// The exposure time of the image
Exposure *string `json:"exposure"`
// The aperature stops of the image
Aperture *float64 `json:"aperture"`
// The ISO setting of the image
Iso *int `json:"iso"`
// The focal length of the lens, when the image was taken
FocalLength *string `json:"focalLength"`
// A formatted description of the flash settings, when the image was taken
Flash *string `json:"flash"`
}
type PhotoURL struct {

View File

@ -35,12 +35,8 @@ func NewUserFromRow(row *sql.Row) (*User, error) {
user := User{}
if err := row.Scan(&user.UserID, &user.Username, &user.Password, &user.RootPath, &user.Admin); err != nil {
if err == sql.ErrNoRows {
return nil, ErrorInvalidUserCredentials
} else {
return nil, err
}
}
return &user, nil
}
@ -64,8 +60,12 @@ func AuthorizeUser(database *sql.DB, username string, password string) (*User, e
user, err := NewUserFromRow(row)
if err != nil {
if err == sql.ErrNoRows {
return nil, ErrorInvalidUserCredentials
} else {
return nil, err
}
}
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
if err == bcrypt.ErrMismatchedHashAndPassword {
@ -107,7 +107,7 @@ func (user *User) GenerateAccessToken(database *sql.DB) (*AccessToken, error) {
if _, err := rand.Read(bytes); err != nil {
return nil, errors.New(fmt.Sprintf("Could not generate token: %s\n", err.Error()))
}
const CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
const CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
for i, b := range bytes {
bytes[i] = CHARACTERS[b%byte(len(CHARACTERS))]
}

View File

@ -89,8 +89,32 @@ type Photo {
thumbnail: PhotoURL
"The album that holds the photo"
album: Album!
# exif: PhotoEXIF
exif: PhotoEXIF
# shares: [ShareToken]
# downloads: [PhotoDownload]
}
"EXIF metadata from the camera"
type PhotoEXIF {
photo: Photo
"The model name of the camera"
camera: String
"The maker of the camera"
maker: String
"The name of the lens"
lens: String
dateShot: Time
"The formatted filesize of the image"
fileSize: String
"The exposure time of the image"
exposure: String
"The aperature stops of the image"
aperture: Float
"The ISO setting of the image"
iso: Int
"The focal length of the lens, when the image was taken"
focalLength: String
"A formatted description of the flash settings, when the image was taken"
flash: String
}

View File

@ -0,0 +1,15 @@
package scanner
import (
"database/sql"
"path"
)
func ProcessImage(tx *sql.Tx, photoPath string, albumId int) error {
photoName := path.Base(photoPath)
_, err := tx.Exec("INSERT IGNORE INTO photo (title, path, album_id) VALUES (?, ?, ?)", photoName, photoPath, albumId)
if err != nil {
return err
}
}

View File

@ -84,7 +84,11 @@ func scan(database *sql.DB, user *models.User) {
photoPath := path.Join(albumPath, item.Name())
if !item.IsDir() && isPathImage(photoPath) {
tx.Exec("INSERT IGNORE INTO photo (title, path, original_url, thumbnail_url, album_id)")
if err := ProcessImage(tx, photoPath, albumId); err != nil {
fmt.Printf("ERROR: Could not proccess image %s: %s", photoPath, err)
tx.Rollback()
return
}
}
}
@ -144,6 +148,7 @@ func directoryContainsPhotos(rootPath string) bool {
var supported_mimetypes = [...]string{
"image/jpeg",
"image/png",
"image/tiff",
"image/x-canon-cr2",
"image/bmp",
}