2018-09-16 19:09:40 +02:00
|
|
|
package models
|
2018-07-18 15:17:56 +02:00
|
|
|
|
|
|
|
import (
|
2019-12-08 15:05:35 +01:00
|
|
|
"sort"
|
2018-08-09 23:10:05 +02:00
|
|
|
"time"
|
2018-10-31 07:14:33 +01:00
|
|
|
|
|
|
|
"github.com/jinzhu/gorm"
|
2019-12-06 10:26:57 +01:00
|
|
|
"github.com/photoprism/photoprism/internal/util"
|
2019-06-09 05:22:53 +02:00
|
|
|
uuid "github.com/satori/go.uuid"
|
2018-07-18 15:17:56 +02:00
|
|
|
)
|
|
|
|
|
2018-11-06 19:02:03 +01:00
|
|
|
// A photo can have multiple images and sidecar files
|
2018-07-18 15:17:56 +02:00
|
|
|
type Photo struct {
|
2019-06-04 18:26:35 +02:00
|
|
|
Model
|
2019-07-02 18:25:46 +02:00
|
|
|
PhotoUUID string `gorm:"unique_index;"`
|
2019-12-06 10:26:57 +01:00
|
|
|
PhotoToken string `gorm:"type:varchar(64);"`
|
2019-07-02 18:25:46 +02:00
|
|
|
PhotoPath string `gorm:"type:varchar(128);index;"`
|
|
|
|
PhotoName string
|
|
|
|
PhotoTitle string
|
|
|
|
PhotoTitleChanged bool
|
|
|
|
PhotoDescription string `gorm:"type:text;"`
|
|
|
|
PhotoNotes string `gorm:"type:text;"`
|
|
|
|
PhotoArtist string
|
|
|
|
PhotoFavorite bool
|
|
|
|
PhotoPrivate bool
|
2019-12-06 10:26:57 +01:00
|
|
|
PhotoNSFW bool
|
2019-07-02 18:25:46 +02:00
|
|
|
PhotoStory bool
|
2019-07-02 22:14:20 +02:00
|
|
|
PhotoLat float64 `gorm:"index;"`
|
|
|
|
PhotoLong float64 `gorm:"index;"`
|
2019-07-02 18:25:46 +02:00
|
|
|
PhotoAltitude int
|
|
|
|
PhotoFocalLength int
|
|
|
|
PhotoIso int
|
2019-11-07 19:00:26 +01:00
|
|
|
PhotoFNumber float64
|
2019-07-02 18:25:46 +02:00
|
|
|
PhotoExposure string
|
|
|
|
PhotoViews uint
|
|
|
|
Camera *Camera
|
2019-07-15 22:54:54 +02:00
|
|
|
CameraID uint `gorm:"index;"`
|
2019-07-02 18:25:46 +02:00
|
|
|
Lens *Lens
|
2019-07-15 22:54:54 +02:00
|
|
|
LensID uint `gorm:"index;"`
|
2019-07-02 18:25:46 +02:00
|
|
|
Country *Country
|
2019-07-15 22:54:54 +02:00
|
|
|
CountryID string `gorm:"index;"`
|
2019-07-02 18:25:46 +02:00
|
|
|
CountryChanged bool
|
|
|
|
Location *Location
|
|
|
|
LocationID uint
|
|
|
|
LocationChanged bool
|
|
|
|
LocationEstimated bool
|
2019-07-02 22:14:20 +02:00
|
|
|
TakenAt time.Time `gorm:"index;"`
|
2019-09-19 23:23:39 +02:00
|
|
|
TakenAtLocal time.Time
|
2019-07-02 18:25:46 +02:00
|
|
|
TakenAtChanged bool
|
|
|
|
TimeZone string
|
|
|
|
Labels []*PhotoLabel
|
2019-12-04 15:14:04 +01:00
|
|
|
Albums []*PhotoAlbum
|
2019-07-02 18:25:46 +02:00
|
|
|
Files []*File
|
2018-08-15 09:59:51 +02:00
|
|
|
}
|
2019-06-04 18:26:35 +02:00
|
|
|
|
|
|
|
func (m *Photo) BeforeCreate(scope *gorm.Scope) error {
|
2019-12-06 10:26:57 +01:00
|
|
|
if err := scope.SetColumn("PhotoUUID", uuid.NewV4().String()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := scope.SetColumn("PhotoToken", util.RandomToken(4)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2019-06-04 18:26:35 +02:00
|
|
|
}
|
2019-12-08 15:05:35 +01:00
|
|
|
|
|
|
|
func (m *Photo) IndexKeywords(keywords []string, db *gorm.DB) {
|
|
|
|
var keywordIds []uint
|
|
|
|
|
|
|
|
// Index title and description
|
|
|
|
keywords = append(keywords, util.Keywords(m.PhotoTitle)...)
|
|
|
|
keywords = append(keywords, util.Keywords(m.PhotoDescription)...)
|
|
|
|
last := ""
|
|
|
|
|
|
|
|
sort.Strings(keywords)
|
|
|
|
|
|
|
|
for _, w := range keywords {
|
|
|
|
if len(w) < 3 || w == last {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
last = w
|
|
|
|
kw := NewKeyword(w).FirstOrCreate(db)
|
|
|
|
|
|
|
|
if kw.Skip {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
keywordIds = append(keywordIds, kw.ID)
|
|
|
|
|
|
|
|
NewPhotoKeyword(m.ID, kw.ID).FirstOrCreate(db)
|
|
|
|
}
|
|
|
|
|
|
|
|
db.Where("photo_id = ? AND keyword_id NOT IN (?)", m.ID, keywordIds).Delete(&PhotoKeyword{})
|
|
|
|
}
|